package premiumupgrade

import (
	"time"

	"github.com/tidbcloud/devops/models/base"
)

type UpgradePlan struct {
	base.Updatable

	Name                   string     `gorm:"type:VARCHAR(255);not null"`
	Reason                 string     `gorm:"type:VARCHAR(1024);not null"`
	Applicant              string     `gorm:"type:VARCHAR(255);not null;uniqueIndex:uk_premium_upgrade_applicant_idempotency,priority:1"`
	OperatorEntity         string     `gorm:"type:VARCHAR(255);not null"`
	DesiredVersion         string     `gorm:"type:VARCHAR(255);not null"`
	ExecutionMode          string     `gorm:"type:VARCHAR(32);not null;default:orchestrated"`
	ScopeMode              string     `gorm:"type:VARCHAR(32);not null"`
	RequestedClusterIDs    []string   `gorm:"type:JSON;serializer:json;not null"`
	RequestedComponents    []string   `gorm:"type:JSON;serializer:json;not null"`
	ApprovalManifest       []byte     `gorm:"type:JSON;not null"`
	ManifestHash           string     `gorm:"type:CHAR(64);not null"`
	ApprovalID             *uint64    `gorm:"type:BIGINT UNSIGNED;uniqueIndex:uk_premium_upgrade_approval_id"`
	ApprovalStatus         *string    `gorm:"type:VARCHAR(32)"`
	Status                 string     `gorm:"type:VARCHAR(64);not null;index:idx_premium_upgrade_plan_status"`
	LastError              string     `gorm:"type:TEXT"`
	MaxParallelTargets     uint32     `gorm:"not null;default:1"`
	ComponentOrderRevision string     `gorm:"type:VARCHAR(32);not null"`
	IdempotencyKey         string     `gorm:"type:VARCHAR(255);not null;uniqueIndex:uk_premium_upgrade_applicant_idempotency,priority:2"`
	CancelRequestedAt      *time.Time `gorm:"type:TIMESTAMP"`
	StartedAt              *time.Time `gorm:"type:TIMESTAMP"`
	FinishedAt             *time.Time `gorm:"type:TIMESTAMP"`
	Version                uint64     `gorm:"not null;default:0"`

	Targets []*UpgradeTarget `gorm:"foreignKey:PlanID"`
}

func (UpgradePlan) TableName() string { return "premium_upgrade_plans" }

type UpgradeTarget struct {
	base.Updatable

	PlanID           uint64     `gorm:"type:BIGINT UNSIGNED;not null;uniqueIndex:uk_premium_upgrade_target_locator,priority:1;index:idx_premium_upgrade_target_plan"`
	ClusterType      string     `gorm:"type:VARCHAR(64);not null;uniqueIndex:uk_premium_upgrade_target_locator,priority:2"`
	ClusterID        string     `gorm:"type:VARCHAR(255);not null;uniqueIndex:uk_premium_upgrade_target_locator,priority:3"`
	SourceClusterIDs []string   `gorm:"type:JSON;serializer:json;not null"`
	ClusterName      string     `gorm:"type:VARCHAR(255);not null"`
	TenantIDs        []string   `gorm:"type:JSON;serializer:json;not null"`
	SharedPoolID     string     `gorm:"type:VARCHAR(255)"`
	LogicalRegion    string     `gorm:"type:VARCHAR(255)"`
	CloudProvider    string     `gorm:"type:VARCHAR(64)"`
	Status           string     `gorm:"type:VARCHAR(64);not null"`
	LastError        string     `gorm:"type:TEXT"`
	StartedAt        *time.Time `gorm:"type:TIMESTAMP"`
	FinishedAt       *time.Time `gorm:"type:TIMESTAMP"`

	Steps []*UpgradeStep `gorm:"foreignKey:TargetID"`
}

func (UpgradeTarget) TableName() string { return "premium_upgrade_targets" }

type UpgradeStep struct {
	base.Updatable

	PlanID                uint64                 `gorm:"type:BIGINT UNSIGNED;not null;index:idx_premium_upgrade_step_plan_sequence_status,priority:1;index:idx_premium_upgrade_step_plan_target_sequence,priority:1"`
	TargetID              uint64                 `gorm:"type:BIGINT UNSIGNED;not null;uniqueIndex:uk_premium_upgrade_step_group,priority:1;index:idx_premium_upgrade_step_plan_target_sequence,priority:2"`
	Sequence              uint32                 `gorm:"not null;index:idx_premium_upgrade_step_plan_sequence_status,priority:2;index:idx_premium_upgrade_step_plan_target_sequence,priority:3"`
	ApplyGroup            string                 `gorm:"type:VARCHAR(255);not null;uniqueIndex:uk_premium_upgrade_step_group,priority:2"`
	Components            []UpgradeStepComponent `gorm:"type:JSON;serializer:json;not null"`
	ApplyStrategy         string                 `gorm:"type:VARCHAR(64);not null"`
	ApplyMode             []byte                 `gorm:"type:JSON;not null"`
	ConfigurationChangeID *uint64                `gorm:"type:BIGINT UNSIGNED;uniqueIndex:uk_premium_upgrade_step_change"`
	Status                string                 `gorm:"type:VARCHAR(64);not null;index:idx_premium_upgrade_step_status_retry,priority:1;index:idx_premium_upgrade_step_plan_sequence_status,priority:3"`
	StatusReason          string                 `gorm:"type:VARCHAR(1024)"`
	AttemptCount          uint32                 `gorm:"not null;default:0"`
	NextRetryAt           *time.Time             `gorm:"type:TIMESTAMP;index:idx_premium_upgrade_step_status_retry,priority:2"`
	ApplyDeadlineAt       *time.Time             `gorm:"type:TIMESTAMP"`
	LastErrorCode         string                 `gorm:"type:VARCHAR(128)"`
	LastErrorMessage      string                 `gorm:"type:TEXT"`
	Version               uint64                 `gorm:"not null;default:0"`
	StartedAt             *time.Time             `gorm:"type:TIMESTAMP"`
	FinishedAt            *time.Time             `gorm:"type:TIMESTAMP"`
}

func (UpgradeStep) TableName() string { return "premium_upgrade_steps" }

type UpgradeStepComponent struct {
	Component    string `json:"component"`
	FromVersion  string `json:"from_version"`
	ToVersion    string `json:"to_version"`
	FromImageTag string `json:"from_image_tag,omitempty"`
	ToImageTag   string `json:"to_image_tag,omitempty"`
}
