// SPDX-License-Identifier: Apache-2.0
// SPDX-FileCopyrightText: 2025 STACKIT GmbH & Co. KG

package instance

import (
	"fmt"
	"regexp"

	cliErr "github.com/stackitcloud/stackit-cli/internal/pkg/errors"
	cliUtils "github.com/stackitcloud/stackit-cli/internal/pkg/utils"
)

// Validation constants taken from OpenApi spec.
const (
	displayNameMinimumChars = 4
	displayNameMaximumChars = 8
	displayNameRegex        = `^[a-z]([-a-z0-9]*[a-z0-9])?$`
	descriptionMaxLength    = 256
	instanceIdMaxLength     = 16
	instanceIdMinLength     = displayNameMinimumChars + 1 // Instance ID is generated by extending the display name.
)

// User input flags for instance commands
const (
	DisplayNameFlag = "name"        // > displayNameMinimumChars <= displayNameMaximumChars characters + regex displayNameRegex
	DescriptionFlag = "description" // <= descriptionMaxLength characters
	PlanIdFlag      = "plan-id"     // UUID
	InstanceIdFlag  = "id"          // instance id (unique per project)
)

// Flag usage texts
const (
	DisplayNameUsage = "The displayed name to distinguish multiple instances."
	DescriptionUsage = "A user chosen description to distinguish multiple instances."
	PlanIdUsage      = "Service Plan configures the size of the Instance."
	InstanceIdUsage  = "The project-unique identifier of this instance."
)

// Flag shorthands
const (
	DisplayNameShorthand = "n"
	DescriptionShorthand = "d"
	InstanceIdShorthand  = "i"
)

// OpenApi generated code will have different types for by-instance-id and by-display-name API calls, which are currently impl. as separate endpoints.
// To make the code more flexible, we use a struct to hold the request model.
type RequestModel struct {
	Value any
}

func ValidateDisplayName(displayName *string) error {
	if displayName == nil {
		return &cliErr.FlagValidationError{
			Flag:    DisplayNameFlag,
			Details: fmt.Sprintf("%s may not be empty", DisplayNameFlag),
		}
	}

	if len(*displayName) > displayNameMaximumChars {
		return &cliErr.FlagValidationError{
			Flag:    DisplayNameFlag,
			Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DisplayNameFlag, displayNameMaximumChars),
		}
	}
	if len(*displayName) < displayNameMinimumChars {
		return &cliErr.FlagValidationError{
			Flag:    DisplayNameFlag,
			Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", DisplayNameFlag, displayNameMinimumChars),
		}
	}
	displayNameRegex := regexp.MustCompile(displayNameRegex)
	if !displayNameRegex.MatchString(*displayName) {
		return &cliErr.FlagValidationError{
			Flag:    DisplayNameFlag,
			Details: fmt.Sprintf("%s didn't match the required regex expression %s", DisplayNameFlag, displayNameRegex),
		}
	}
	return nil
}

func ValidatePlanId(planId *string) error {
	if planId == nil {
		return &cliErr.FlagValidationError{
			Flag:    PlanIdFlag,
			Details: fmt.Sprintf("%s may not be empty", PlanIdFlag),
		}
	}

	err := cliUtils.ValidateUUID(*planId)
	if err != nil {
		return &cliErr.FlagValidationError{
			Flag:    PlanIdFlag,
			Details: fmt.Sprintf("%s is not a valid UUID: %v", PlanIdFlag, err),
		}
	}
	return nil
}

func ValidateDescription(description string) error {
	if len(description) > descriptionMaxLength {
		return &cliErr.FlagValidationError{
			Flag:    DescriptionFlag,
			Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", DescriptionFlag, descriptionMaxLength),
		}
	}

	return nil
}

func ValidateInstanceId(instanceId *string) error {
	if instanceId == nil {
		return &cliErr.FlagValidationError{
			Flag:    InstanceIdFlag,
			Details: fmt.Sprintf("%s may not be empty", InstanceIdFlag),
		}
	}

	if *instanceId == "" {
		return &cliErr.FlagValidationError{
			Flag:    InstanceIdFlag,
			Details: fmt.Sprintf("%s may not be empty", InstanceIdFlag),
		}
	}
	if len(*instanceId) < instanceIdMinLength {
		return &cliErr.FlagValidationError{
			Flag:    InstanceIdFlag,
			Details: fmt.Sprintf("%s is too short (minimum length is %d characters)", InstanceIdFlag, instanceIdMinLength),
		}
	}
	if len(*instanceId) > instanceIdMaxLength {
		return &cliErr.FlagValidationError{
			Flag:    InstanceIdFlag,
			Details: fmt.Sprintf("%s is too long (maximum length is %d characters)", InstanceIdFlag, instanceIdMaxLength),
		}
	}

	return nil
}
