package scale

import (
	"time"

	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	corev1 "k8s.io/api/core/v1"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"

	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
)

// MemberScaleType represents the type of scaling operation
type MemberScaleType string

const (
	MemberScaleTypeNone            MemberScaleType = "none"
	MemberScaleTypeScaleUp         MemberScaleType = "scaleUp"
	MemberScaleTypeScaleDown       MemberScaleType = "scaleDown"
	MemberScaleTypeScaleOut        MemberScaleType = "scaleOut"
	MemberScaleTypeScaleIn         MemberScaleType = "scaleIn"
	MemberScaleConfigVersionChange MemberScaleType = "configVersionChange"
	MemberScaleStorageSizeChange   MemberScaleType = "storageSizeChange"
)

// ScaleStatusTracked represents the tracked scale status of a cluster
// key: MemberPrefix:ComponentGroupKey -> value: []string -> [component status: xxx, scale type: xxx]
// key: NodeGroupPrefix:AutoScalingGroupName -> value: []string -> [node group status: xxx, node instance id: xxx, node instance type: xxx, node health status: xxx, node lifecycle state: xxx]
type ScaleStatusTracked struct {
	AClusterMsg       map[string][]string `json:"a_cluster_msg,omitempty" yaml:"aClusterMsg,omitempty"`
	ClusterId         string              `json:"cluster_id" yaml:"clusterId"`
	TenantId          string              `json:"tenant_id,omitempty" yaml:"tenantId,omitempty"`
	ProjectId         string              `json:"project_id,omitempty" yaml:"projectId,omitempty"`
	Namespace         string              `json:"namespace,omitempty" yaml:"namespace,omitempty"`
	GroupId           string              `json:"group_id,omitempty" yaml:"groupId,omitempty"`
	ClusterFullSynced bool                `json:"cluster_full_synced,omitempty" yaml:"clusterFullSynced,omitempty"`
	IsSynced          bool                `json:"is_synced,omitempty" yaml:"isSynced,omitempty"`
	// LastProbeTime is the time of last status check
	LastProbeTime               time.Time                   `json:"last_probe_time,omitempty" yaml:"lastProbeTime,omitempty"`
	LastUpdateTimeFromTiDBCloud time.Time                   `json:"last_update_time_from_tidbcloud,omitempty" yaml:"lastUpdateTimeFromTiDBCloud,omitempty"`
	ComponentMemberStatus       map[string]CompMemberStatus `json:"component_member_status,omitempty" yaml:"componentMemberStatus,omitempty"`
	AutoScalingGroupListStatus  AutoScalingGroupListStatus  `json:"auto_scaling_group_list_status,omitempty" yaml:"autoScalingGroupListStatus,omitempty"`
	ComponentScaleChange        map[string]ScaleChange      `json:"component_scale_change,omitempty" yaml:"componentScaleChange,omitempty"`
}

// ScaleChange represents the change in scale resources
type ScaleChange struct {
	StatusResourceInfo MemberResourceInfo `json:"status_resource_info,omitempty" yaml:"statusResourceInfo,omitempty"`
	SpecResourceInfo   MemberResourceInfo `json:"spec_resource_info,omitempty" yaml:"specResourceInfo,omitempty"`
}

// MemberConditionType represents the type of member condition
type MemberConditionType string

const (
	MemberPodRunning  MemberConditionType = "PodRunning"
	MemberNodeReady   MemberConditionType = "NodeReady"
	MemberPVCReady    MemberConditionType = "PVCReady"
	MemberStoreOnline MemberConditionType = "StoreOnline"
)

// MemberStatus represents the status of a cluster member
type MemberStatus struct {
	Name                     string             `json:"name,omitempty" yaml:"name,omitempty"`
	NodeName                 string             `json:"node_name,omitempty" yaml:"nodeName,omitempty"`
	InstanceType             string             `json:"instance_type,omitempty" yaml:"instanceType,omitempty"`
	NodeGroup                string             `json:"node_group,omitempty" yaml:"nodeGroup,omitempty"`
	Zone                     string             `json:"zone,omitempty" yaml:"zone,omitempty"`
	LeaderCount              int32              `json:"leader_count,omitempty" yaml:"leaderCount,omitempty"`
	LeaderCountBeforeUpgrade *int32             `json:"leader_count_before_upgrade,omitempty" yaml:"leaderCountBeforeUpgrade,omitempty"`
	RegionCount              int32              `json:"region_count,omitempty" yaml:"regionCount,omitempty"`
	PVInfo                   []PVInfo           `json:"pv_info,omitempty" yaml:"pvInfo,omitempty"`
	MemberConditions         []metav1.Condition `json:"member_conditions,omitempty" yaml:"memberConditions,omitempty"`
	StoreStartTime           time.Time          `json:"store_start_time,omitempty" yaml:"storeStartTime,omitempty"`
	PodCreateTime            time.Time          `json:"pod_create_time,omitempty" yaml:"podCreateTime,omitempty"`
	// Reason is the summary reason why the member is not normal
	Reason string `json:"reason,omitempty" yaml:"reason,omitempty"`
}

// CompMemberStatus represents the status of a component member
type CompMemberStatus struct {
	ComponentType          cloudv1.ComponentType   `json:"component_type,omitempty" yaml:"componentType,omitempty"`
	GroupId                string                  `json:"group_id,omitempty" yaml:"groupId,omitempty"`
	ComponentStatus        cloudv1.ComponentStatus `json:"component_status,omitempty" yaml:"componentStatus,omitempty"`
	InstanceTypeScalePhase string                  `json:"instance_type_scale_phase,omitempty" yaml:"instanceTypeScalePhase,omitempty"`
	MemberScaleType        MemberScaleType         `json:"member_scale_type,omitempty" yaml:"memberScaleType,omitempty"`
	Condition              []metav1.Condition      `json:"condition,omitempty" yaml:"condition,omitempty"`
	NotNormalMemberStatus  []MemberStatus          `json:"not_normal_member_status,omitempty" yaml:"notNormalMemberStatus,omitempty"`
	CompMemberSetting      CompMemberSetting       `json:"comp_member_setting,omitempty" yaml:"compMemberSetting,omitempty"`
	Replicas               int32                   `json:"replicas,omitempty" yaml:"replicas,omitempty"`
	UpdatedReplicas        int32                   `json:"updated_replicas,omitempty" yaml:"updatedReplicas,omitempty"`
}

// StoreStatus represents the status of a TiKV/TiFlash store
type StoreStatus struct {
	Name                     string    `json:"name,omitempty" yaml:"name,omitempty"`
	Status                   string    `json:"status,omitempty" yaml:"status,omitempty"`
	StartTime                time.Time `json:"start_time,omitempty" yaml:"startTime,omitempty"`
	LeaderCount              int32     `json:"leader_count,omitempty" yaml:"leaderCount,omitempty"`
	LeaderCountBeforeUpgrade *int32    `json:"leader_count_before_upgrade,omitempty" yaml:"leaderCountBeforeUpgrade,omitempty"`
	RegionCount              int32     `json:"region_count,omitempty" yaml:"regionCount,omitempty"`
}

// MemberResourceInfo represents resource information for a member
type MemberResourceInfo struct {
	Replicas         int32  `json:"replicas,omitempty" yaml:"replicas,omitempty"`
	StorageSize      string `json:"storage_size,omitempty" yaml:"storageSize,omitempty"`
	StorageClassName string `json:"storage_class_name,omitempty" yaml:"storageClassName,omitempty"`
	ConfigVersion    string `json:"config_version,omitempty" yaml:"configVersion,omitempty"`
	InstanceType     string `json:"instance_type,omitempty" yaml:"instanceType,omitempty"`
}

// CompMemberSetting represents component member settings
type CompMemberSetting struct {
	TerminationGracePeriodSeconds int64  `json:"termination_grace_period_seconds,omitempty" yaml:"terminationGracePeriodSeconds,omitempty"`
	MinReadySeconds               string `json:"min_ready_seconds,omitempty" yaml:"minReadySeconds,omitempty"`
	GracefulShutdownSleepSeconds  int64  `json:"graceful_shutdown_sleep_seconds,omitempty" yaml:"gracefulShutdownSleepSeconds,omitempty"`
	PreStopHookSleepSeconds       int64  `json:"pre_stop_hook_sleep_seconds,omitempty" yaml:"preStopHookSleepSeconds,omitempty"`
}

// NodeStatus represents the status of a node
type NodeStatus struct {
	HealthStatus   string `json:"health_status,omitempty" yaml:"healthStatus,omitempty"`
	InstanceID     string `json:"instance_id,omitempty" yaml:"instanceId,omitempty"`
	InstanceType   string `json:"instance_type,omitempty" yaml:"instanceType,omitempty"`
	LifecycleState string `json:"lifecycle_state,omitempty" yaml:"lifecycleState,omitempty"`
}

// AutoScalingGroupListStatus represents the status of auto scaling groups
type AutoScalingGroupListStatus struct {
	AutoScalingGroupStatus map[string]AutoScalingGroupStatus `json:"auto_scaling_group_status,omitempty" yaml:"autoScalingGroupStatus,omitempty"`
	NotNormalGroupList     []string                          `json:"not_normal_group_list,omitempty" yaml:"notNormalGroupList,omitempty"`
	AllGroupListNormal     bool                              `json:"all_group_list_normal,omitempty" yaml:"allGroupListNormal,omitempty"`
}

// AutoScalingGroupStatus represents the status of an auto scaling group
type AutoScalingGroupStatus struct {
	Annotations         map[string]string `json:"annotations,omitempty" yaml:"annotations,omitempty"`
	Name                string            `json:"name" yaml:"name"`
	DesiredCapacity     *int64            `json:"desired_capacity,omitempty" yaml:"desiredCapacity,omitempty"`
	MinSize             *int64            `json:"min_size,omitempty" yaml:"minSize,omitempty"`
	MaxSize             *int64            `json:"max_size,omitempty" yaml:"maxSize,omitempty"`
	Conditions          []xpv1.Condition  `json:"conditions,omitempty" yaml:"conditions,omitempty"`
	NotNormalNodeStatus []NodeStatus      `json:"not_normal_node_status,omitempty" yaml:"notNormalNodeStatus,omitempty"`
	Status              string            `json:"status,omitempty" yaml:"status,omitempty"`
}

// PVInfo represents persistent volume information
type PVInfo struct {
	PV  *PVCDetail `json:"pv,omitempty" yaml:"pv,omitempty"`
	PVC *PVCDetail `json:"pvc,omitempty" yaml:"pvc,omitempty"`
}

// PVCDetail represents persistent volume claim detail
type PVCDetail struct {
	SpecAnnoRevision       string                                  `json:"spec_anno_revision,omitempty" yaml:"specAnnoRevision,omitempty"`
	SpecAnnoStorageClass   string                                  `json:"spec_anno_storage_class,omitempty" yaml:"specAnnoStorageClass,omitempty"`
	SpecAnnoStorageSize    string                                  `json:"spec_anno_storage_size,omitempty" yaml:"specAnnoStorageSize,omitempty"`
	StatusAnnoRevision     string                                  `json:"status_anno_revision,omitempty" yaml:"statusAnnoRevision,omitempty"`
	StatusAnnoStorageClass string                                  `json:"status_anno_storage_class,omitempty" yaml:"statusAnnoStorageClass,omitempty"`
	StatusAnnoStorageSize  string                                  `json:"status_anno_storage_size,omitempty" yaml:"statusAnnoStorageSize,omitempty"`
	Name                   string                                  `json:"name,omitempty" yaml:"name,omitempty"`
	Status                 string                                  `json:"status,omitempty" yaml:"status,omitempty"`
	Zone                   string                                  `json:"zone,omitempty" yaml:"zone,omitempty"`
	StorageClass           string                                  `json:"storage_class,omitempty" yaml:"storageClass,omitempty"`
	StorageSize            string                                  `json:"storage_size,omitempty" yaml:"storageSize,omitempty"`
	ResourceID             string                                  `json:"resource_id,omitempty" yaml:"resourceId,omitempty"`
	StorageClassAttribute  string                                  `json:"storage_class_attribute,omitempty" yaml:"storageClassAttribute,omitempty"`
	Conditions             []corev1.PersistentVolumeClaimCondition `json:"conditions,omitempty" yaml:"conditions,omitempty"`
}
