package model

import (
	"fmt"
	"strconv"
	"strings"

	"github.com/samber/lo"
)

const (
	CloudProviderAWS = "aws"
	CloudProviderGCP = "gcp"
)

type TierUnitMap struct {
	Regions     []string `yaml:"regions,flow"`
	TenantIds   []uint64 `yaml:"tenantIds,flow"`
	TierUnitKey string   `yaml:"tierUnitKey"`
}

type TierUnitMapWithProvider struct {
	Provider string `yaml:"provider"`
	TierUnitMap
}

type PdTier struct {
	TierName    string `yaml:"tierName" validate:"min=1"`
	TierUnitKey string `yaml:"tierUnitKey" validate:"min=1"`
	NodeNum     int    `yaml:"nodeNum" validate:"gt=0"`
}

type TierCompute struct {
	InstanceType string `yaml:"type" validate:"min=1"`
}

type TierStorage struct {
	InstanceType  string `yaml:"type" validate:"oneof=gp2 gp3 io2 pd-ssd local-storage"`
	Iops          int    `yaml:"iops" validate:"gte=0"`
	ThroughputMi  int    `yaml:"throughputMBs" validate:"gte=0"`
	MinSizeGi     int    `yaml:"minSizeGi" validate:"gte=0"`
	MaxSizeGi     int    `yaml:"maxSizeGi" validate:"gte=0,gtefield=MinSizeGi"`
	DefaultSizeGi int    `yaml:"defaultSizeGi" validate:"gtefield=MinSizeGi,ltefield=MaxSizeGi"`
}

type ForMigration struct {
	TierName             string   `yaml:"tierName" validate:"min=1"`
	TierDisplayName      string   `yaml:"tierDisplayName" validate:"min=1"`
	NonStandardTenantIds []uint64 `yaml:"nonStandardTenantIds,flow"` // tenantId list
}

type TierYaml struct {
	ComponentType string                   `yaml:"component" validate:"oneof=pd tidb tikv tidb tiflash"`
	DeployType    string                   `yaml:"deployType" validate:"oneof=dedicated shared"`
	Name          string                   `yaml:"name" validate:"min=1"`
	DisplayName   string                   `yaml:"displayName" validate:"min=1"`
	Memo          string                   `yaml:"memo"`
	Default       bool                     `yaml:"default"`
	CpuNum        int                      `yaml:"cpu" validate:"gte=0"`      // cpuNum of devtier will be fixed 0
	MemoryGi      int                      `yaml:"memoryGi" validate:"gte=0"` // memoryGi of devtier will be fixed 0
	TierUnitMap   map[string][]TierUnitMap `yaml:"tierUnitMap"`               // key: aws, gcp
}

type TierUnitYaml struct {
	CloudProvider  string       `yaml:"provider" validate:"oneof=aws gcp"`
	ComponentType  string       `yaml:"component" validate:"oneof=pd tidb tikv tidb tiflash"`
	DeployType     string       `yaml:"deployType" validate:"oneof=dedicated shared"`
	Key            string       `yaml:"key" validate:"min=1"`
	Memo           string       `yaml:"memo"`
	DefaultNodeNum int          `yaml:"defaultNodeNum" validate:"gte=0"`
	Regions        []string     `yaml:"regions,flow"`
	Compute        TierCompute  `yaml:"compute"`
	Storage        *TierStorage `yaml:"storage"`
	PD             *PdTier      `yaml:"pd"`

	ForMigration *ForMigration `yaml:"forMigration" validate:"required"`
}

func BuildTierKey(name, deployType, componentType string) string {
	return fmt.Sprintf("%s:%s:%s", name, deployType, componentType)
}

func BuildTierUnitKey(providerName string, componentType string, computeType, storageType string, storageIops, storageThroughput int64) string {
	return fmt.Sprintf("%s:%s:%s:%s:%d:%d", providerName, componentType, computeType, storageType, storageIops, storageThroughput)
}

type ParsedTierUnitKey struct {
	ProviderName      string
	ComponentType     string
	ComputeType       string
	StorageType       string
	StorageIops       int64
	StorageThroughput int64
}

func ParseTierUnitKey(k string) *ParsedTierUnitKey {
	result := strings.Split(k, ":")
	out := &ParsedTierUnitKey{
		ProviderName:      result[0],
		ComponentType:     result[1],
		ComputeType:       result[2],
		StorageType:       result[3],
		StorageIops:       lo.Must(strconv.ParseInt(result[4], 10, 64)),
		StorageThroughput: lo.Must(strconv.ParseInt(result[5], 10, 64)),
	}
	return out
}

// IsAwsArm return true if the instance is ARM-based. For now, we hardcode it by check whether contains "g."
func IsAwsArm(instanceType string) bool {
	return strings.Contains(instanceType, "g.")
}
