package networkcapacity

import (
	"fmt"

	"github.com/tidbcloud/infra-provider/regional-server/pkg/consts"
)

type HighAvailabilityType int

const (
	HighAvailabilityRegional HighAvailabilityType = iota + 1
	HighAvailabilityZonal
)

type ResultCategory string

const (
	ResultCategorySupported        ResultCategory = "SUPPORTED"
	ResultCategoryPrefixRange      ResultCategory = "PREFIX_RANGE"
	ResultCategorySubnetShape      ResultCategory = "SUBNET_SHAPE"
	ResultCategoryEndpointCapacity ResultCategory = "ENDPOINT_CAPACITY"
	ResultCategoryZeroNodeCapacity ResultCategory = "ZERO_NODE_CAPACITY"
)

type Input struct {
	Provider                 string
	PrefixLength             int
	HighAvailability         HighAvailabilityType
	RegionZones              []string
	ConfiguredNodeZones      []string
	EndpointSubnetsEnabled   bool
	PrivateLinkEndpointZones []string
	ReservedAdminPodIPs      int64
}

type Result struct {
	Supported          bool
	SupportedNodeCount int64
	Category           ResultCategory
}

func Evaluate(input Input) (Result, error) {
	if input.Provider != consts.ProviderTypeEKS {
		return Result{}, fmt.Errorf("network capacity evaluation is unsupported for provider %q", input.Provider)
	}
	if input.PrefixLength < 0 || input.PrefixLength > 32 {
		return Result{}, fmt.Errorf("prefix length must be between 0 and 32")
	}
	if input.ReservedAdminPodIPs < 0 {
		return Result{}, fmt.Errorf("reserved admin pod IPs must not be negative")
	}
	switch input.HighAvailability {
	case HighAvailabilityRegional, HighAvailabilityZonal:
	default:
		return Result{}, fmt.Errorf("unknown high availability type %d", input.HighAvailability)
	}

	return evaluateAWS(input)
}

func unsupported(category ResultCategory) Result {
	return Result{Category: category}
}

func supported(count int64) Result {
	return Result{
		Supported:          true,
		SupportedNodeCount: count,
		Category:           ResultCategorySupported,
	}
}

func ValidateResult(result Result) error {
	if result.Supported {
		if result.SupportedNodeCount <= 0 {
			return fmt.Errorf("supported result must have a positive node count")
		}
		return nil
	}
	if result.SupportedNodeCount != 0 {
		return fmt.Errorf("unsupported result must have a zero node count")
	}
	return nil
}
