package cloudconfig

import (
	"errors"
	"fmt"
	"strings"
)

type ClusterType string
type TemplateType string

const (
	// ClusterTypeTiProxy        ClusterType = "TIPROXY" not used
	ClusterTypeUnknown             ClusterType = ""
	ClusterTypeDedicatedTiDB       ClusterType = "DEDICATED_TIDB"
	ClusterTypeTiCDC               ClusterType = "TICDC"
	ClusterTypeChangefeed          ClusterType = "CHANGEFEED"
	ClusterTypeSharedPool          ClusterType = "SHARED_POOL"
	ClusterTypeLogicalCluster      ClusterType = "LOGICAL_CLUSTER"
	ClusterTypeTiCDCNG             ClusterType = "TICDC_NG"
	ClusterTypeChangefeedNG        ClusterType = "CHANGEFEED_NG"
	ClusterTypeChangefeedEssential ClusterType = "CHANGEFEED_ESSENTIAL"

	TemplateTypeUnspecified   TemplateType = "unspecified"
	TemplateTypeCustom        TemplateType = "custom"
	TemplateTypeCustomPart    TemplateType = "custom_part" // internal use only
	TemplateTypeTenantDefault TemplateType = "tenant_default"

	VersionFollowGlobal = "FOLLOW_GLOBAL"
)

type ClusterConfigurationLocator struct {
	ClusterType ClusterType `json:"cluster_type"`
	ClusterID   string      `json:"cluster_id"`
}

func IsSupportedChangefeedClusterType(clusterType string) bool {
	switch ClusterType(clusterType) {
	case ClusterTypeChangefeed, ClusterTypeChangefeedNG, ClusterTypeChangefeedEssential:
		return true
	default:
		return false
	}
}

type TenantInitConfigurationLocator struct {
	ClusterType ClusterType `json:"cluster_type"`
	TenantID    uint64      `json:"tenant_id,string"`
}

type ConfigurationTemplateLocator struct {
	ClusterType  ClusterType  `json:"cluster_type"`
	TemplateType TemplateType `json:"template_type"`
	TenantID     *string      `json:"tenant_id,omitempty"` // Own Tenant ID, only for TemplateTypeTenantDefault
	// TemplateNmae string      `json:"template_name"`
	// TemplateID  int64       `json:"template_id"`
}

type FileConfiguration struct {
	Filename          string                       `json:"filename"`
	ConfigType        string                       `json:"config_type"`
	BelongToComponent string                       `json:"belong_to_component"`
	Format            string                       `json:"format"`
	TemplateID        uint64                       `json:"template_id"`
	Text              string                       `json:"text"`
	Parameters        map[string]*UnifiedParameter `json:"all_parameters"` // key: parameter name
}

func (c FileConfiguration) ExtractCustomParameters() []*NamedParameter {
	result := make([]*NamedParameter, 0)
	for _, param := range c.Parameters {
		if param.Source == ParameterCustom {
			result = append(result, &NamedParameter{
				Name:           param.Name,
				ParameterValue: *param.Custom,
			})
		}
	}

	return result
}

type CloudInstanceType struct {
	CloudProvider string `json:"cloud_provider"`
	InstanceType  string `json:"instance_type"`
}

func FormatCloudInstanceType(i CloudInstanceType) string {
	return fmt.Sprintf("%s:%s", i.CloudProvider, i.InstanceType)
}

func ParseCloudInstanceType(s string) (CloudInstanceType, error) {
	parts := strings.Split(s, ":")
	if len(parts) != 2 {
		return CloudInstanceType{}, errors.New("invalid cloud instance type")
	}
	return CloudInstanceType{
		CloudProvider: parts[0],
		InstanceType:  parts[1],
	}, nil
}

type Component struct {
	CloudInstanceType `json:",inline"`

	Name              string `json:"name"`
	Version           string `json:"version"`
	BaseImage         string `json:"base_image"`
	OverwriteImageTag string `json:"overwrite_image_tag"`
	EffectiveImageTag string `json:"effective_image_tag"`
}

type Configuration struct {
	TargetCluster    *ClusterConfigurationLocator    `json:"target_cluster"`
	TargetTenantInit *TenantInitConfigurationLocator `json:"target_tenant"`

	Version    string                        `json:"version"`
	Components map[string]*Component         `json:"components"` // key: component name
	Files      map[string]*FileConfiguration `json:"files"`      // key: filename
}

type TenantVersions struct {
	TiDB    string `json:"tidb"`
	TiProxy string `json:"tiproxy"`
	DM      string `json:"data-migration"`
}
