package schema

import (
	"time"

	"gorm.io/gorm"
	gormschema "gorm.io/gorm/schema"
	"gorm.io/plugin/optimisticlock"
)

type PauseResumeDBEnum string

func (PauseResumeDBEnum) GormDBDataType(db *gorm.DB, field *gormschema.Field) string {
	if db.Name() == "mysql" {
		return field.TagSettings["TYPE"]
	}
	return "text"
}

var Models = []any{
	&SharedPool{},
	&SharedPoolObjectStore{},
	&TemplateRegistry{},
	&DmCluster{},
	&TidbCluster{},
	&TidbGroup{},
	&TidbGroupEndpoint{},
	&RuConfig{},
	&AutoscalePolicyBundleSpec{},
	&AutoscaleRuntimeGuard{},
	&ScaleOperation{},
	&PauseResumeOperation{},
	&LightweightRestore{},
	&ClassicRestore{},
	&Export{},
	&ManualBackup{},
	&ManualBackupRestore{},
	&ScaleTikvDecision{},
	&BackupGcSetting{},
	&NodeInstanceGroup{},
	&DataplaneNodeInstanceGroupState{},
	&DataplaneNodeInstanceGroupLock{},
	&DataplaneNodeInstanceGroup{},
	&WorkerNodeMeteringCheckpoint{},
	&CassandraProxyState{},
}

type SharedPool struct {
	ID                        string `gorm:"type:varchar(128);primarykey"` // unique shared pool id
	DataplaneName             string `gorm:"not null;index"`               // name of the dataplane, equal to dataplaneId for dpmgr
	DataplaneInfo             string `gorm:"type:text"`                    // dataplane info in JSON format, empty when using dpmgr
	VcpusLimit                uint64 `gorm:"not null;default:0"`
	PlacementGroupEnabled     bool   `gorm:"not null;default:false"`
	DeployType                string `gorm:"column:deploy_type;type:varchar(32);not null;default:''"`
	TiflashMode               string `gorm:"column:tiflash_mode;type:varchar(32);not null;default:''"`
	CapacityMode              string `gorm:"column:capacity_mode;type:varchar(32);not null;default:'RCU_DRIVEN'"`
	PDDeploymentMode          string `gorm:"column:pd_deployment_mode;type:varchar(32);not null;default:'PD_DEPLOYMENT_MODE_MICROSERVICE'"`
	EnabledTiKVRemoteWorkers  string `gorm:"column:enabled_tikv_remote_workers;type:varchar(128);not null;default:'COPROCESSOR_WORKER,TIKV_WORKER'"`
	ConfigCenterMetaProfileID string `gorm:"column:config_center_meta_profile_id;type:varchar(128);not null;default:''"`
	CloudResourceTags         string `gorm:"column:cloud_resource_tags;type:text"`
	HighAvailabilityType      string `gorm:"column:high_availability_type;type:varchar(32);not null;default:'REGIONAL'"`
	EnableCapacityPlanner     bool   `gorm:"column:enable_capacity_planner;not null;default:false"`

	PauseResumeState      *PauseResumeDBEnum `gorm:"column:pause_resume_state;type:enum('pausing','paused','resuming');default:null"`
	SuspendComputeDesired bool               `gorm:"column:suspend_compute_desired;not null;default:false"`

	ObjectStores    []*SharedPoolObjectStore
	TemplateVersion int64 `gorm:"index"` // version of the template used to create this shared pool
	CreatedAt       time.Time
	UpdatedAt       time.Time
	DeletedAt       gorm.DeletedAt `gorm:"index"`
}

type PauseResumeOperation struct {
	ID            uint              `gorm:"primarykey"`
	SharedPoolID  string            `gorm:"type:varchar(128);not null;index:pause_resume_operation_key,unique,priority:1"`
	OperationID   string            `gorm:"type:varchar(128);not null;index:pause_resume_operation_key,unique,priority:2"`
	Type          PauseResumeDBEnum `gorm:"type:enum('pause','resume');not null"`
	Status        PauseResumeDBEnum `gorm:"type:enum('running','succeeded','failed','cancelled');not null"`
	Stage         PauseResumeDBEnum `gorm:"type:enum('precheck','flush_wal','apply_suspend','wait_suspended','apply_resume','wait_available');not null"`
	ResultSummary string            `gorm:"type:text"`
	CreatedAt     time.Time
	UpdatedAt     time.Time
	CompletedAt   *time.Time
}

func (PauseResumeOperation) TableName() string {
	return "shared_pool_pause_resume_operations"
}

const (
	SharedPoolDeployTypeDefault       = ""
	SharedPoolDeployTypeSharedTiProxy = "shared_tiproxy"
)

const (
	// SharedPoolTiflashModeDefault means the legacy tiflash-write +
	// tiflash-compute architecture.
	SharedPoolTiflashModeDefault = ""
	// SharedPoolTiflashModeColumnar means the columnar architecture:
	// schema-manager + tiflash-compute, no tiflash-write.
	SharedPoolTiflashModeColumnar = "columnar"
)

const (
	SharedPoolObjectStoreTypeData     = "data"
	SharedPoolObjectStoreTypeInternal = "internal"
)

const (
	ExportStateCreating  = "creating"
	ExportStateRunning   = "running"
	ExportStateSucceeded = "succeeded"
	ExportStateFailed    = "failed"
	ExportStateCanceled  = "canceled"
	ExportStateDeleted   = "deleted"
)

type SharedPoolObjectStore struct {
	gorm.Model
	SharedPoolID string `gorm:"not null;index:sharedpool_store_type,unique,priority:1"`
	StoreType    string `gorm:"type:enum('data','internal');not null;index:sharedpool_store_type,unique,priority:2"` // Enum: 'data' or 'internal'
	StoreRegion  string `gorm:"not null"`
	StoreBucket  string `gorm:"not null"`
	StorePrefix  string `gorm:"type:varchar(128)"`
}

type DmCluster struct {
	ID              string `gorm:"type:varchar(128);primarykey"` // unique DMCluster id
	SharedPoolID    string `gorm:"type:varchar(128);index"`
	DataplaneName   string `gorm:"not null"`
	Backend         string `gorm:"column:backend;type:enum('legacy','operator-v2');not null;default:'operator-v2'"`
	TemplateVersion int64  `gorm:"index"` // version of the template used to create this dm cluster
	CreatedAt       time.Time
	UpdatedAt       time.Time
	DeletedAt       gorm.DeletedAt `gorm:"index"`
}

type TidbCluster struct {
	ID              string `gorm:"type:varchar(128);primarykey"` // unique TiDBCluster id
	TenantID        string `gorm:"type:varchar(128);index"`      // user level id
	SharedPoolID    string `gorm:"type:varchar(128);index"`
	RUMin           int64  `gorm:"not null"`
	RUMax           int64  `gorm:"not null"`
	CapacityMode    string `gorm:"column:capacity_mode;type:varchar(32);not null;default:'RCU_DRIVEN'"`
	AuditLogConfig  string `gorm:"type:text"`                        // audit log config in JSON format
	GatewayIdentity string `gorm:"type:varchar(128);not null;index"` // gateway identity
	RuVersion       int32  `gorm:"not null;default:1"`               // ru version for RU calculation formula
	TemplateVersion int64  `gorm:"index"`                            // version of the template used to create this tidb cluster
	CreatedAt       time.Time
	UpdatedAt       time.Time
	DeletedAt       gorm.DeletedAt `gorm:"index"`
}

type TidbGroup struct {
	ID              string `gorm:"type:varchar(128);primarykey"` // unique TidbGroup id
	SharedPoolID    string `gorm:"type:varchar(128);index"`
	ClusterID       string `gorm:"type:varchar(128);index"`
	TenantID        string `gorm:"type:varchar(128);index"`
	DataplaneName   string `gorm:"not null"`
	Type            string `gorm:"type:varchar(32);not null;default:'DEFAULT'"`
	Endpoint        *TidbGroupEndpoint
	TemplateVersion int64 `gorm:"index"` // version of the template used to create this tidb group
	CreatedAt       time.Time
	UpdatedAt       time.Time
	DeletedAt       gorm.DeletedAt `gorm:"index"`
}

type TidbGroupEndpoint struct {
	gorm.Model
	TidbGroupID              string `gorm:"type:varchar(128);uniqueIndex"`
	DNSIdentity              string `gorm:"type:varchar(128);not null;uniqueIndex"`
	DisablePublicDNSIdentity bool   `gorm:"not null;default:false"`
	PublicEnabled            *bool  `gorm:"default:false"`
	PrivateEnabled           *bool  `gorm:"default:false"`
}

type CassandraProxyState struct {
	ClusterID          string `gorm:"type:varchar(128);primaryKey"`
	SharedPoolID       string `gorm:"type:varchar(128);not null;index"`
	HostID             string `gorm:"type:varchar(128);not null"`
	NodeSpec           string `gorm:"type:varchar(64);not null"`
	Image              string `gorm:"type:varchar(512);not null;default:''"`
	NodeQuota          string `gorm:"type:text;not null"`
	Phase              string `gorm:"type:varchar(32);not null;index"`
	PrivatelinkDNSName string `gorm:"type:varchar(256);not null;default:''"`
	CreatedAt          time.Time
	UpdatedAt          time.Time
	DeletedAt          gorm.DeletedAt `gorm:"index"`
}

func (CassandraProxyState) TableName() string {
	return "cassandra_proxy_states"
}

type RuConfig struct {
	gorm.Model
	Scope  string `gorm:"type:enum('shared_pool','tenant');not null;index:scope_name,unique,priority:1"`
	Name   string `gorm:"type:varchar(128);not null;index:scope_name,unique,priority:2"`
	Config string `gorm:"type:text;not null"` // RU config in JSON format
}

type AutoscalePolicy struct {
	ID                    uint `gorm:"primarykey"`
	CreatedAt             time.Time
	UpdatedAt             time.Time
	SubjectType           string `gorm:"type:enum('shared_pool','cluster');not null;index:policy_subject_key,unique,priority:1"`
	SubjectID             string `gorm:"type:varchar(128);not null;index:policy_subject_key,unique,priority:2"`
	ComponentType         string `gorm:"type:varchar(64);not null;index:policy_subject_key,unique,priority:3"`
	Direction             string `gorm:"type:enum('scale_out','scale_in');not null;index:policy_subject_key,unique,priority:4"`
	Capability            string `gorm:"type:enum('node_count','node_spec','disk_size','iops','throughput');not null;index:policy_subject_key,unique,priority:5"`
	Trigger               string `gorm:"type:enum('cpu','disk','io','rcu','import','restore','manual');not null;index:policy_subject_key,unique,priority:6"`
	State                 string `gorm:"type:enum('disabled','enabled');not null"`
	EffectiveParamsJSON   string `gorm:"type:text"`
	PolicyHash            string `gorm:"type:varchar(128);not null;default:''"`
	MaterializedFrom      string `gorm:"type:varchar(64);not null;default:''"`
	MaterializedSubjectID string `gorm:"type:varchar(128);not null;default:''"`
	LastModifiedSource    string `gorm:"type:varchar(64);not null;default:''"`
}

type AutoscaleRuntimeGuard struct {
	gorm.Model
	ScopeType     string     `gorm:"type:enum('region','shared_pool');not null;index:runtime_guard_key,unique,priority:1"`
	ScopeID       string     `gorm:"type:varchar(128);not null;index:runtime_guard_key,unique,priority:2"`
	GuardType     string     `gorm:"type:enum('forbid_scale_in');not null;index:runtime_guard_key,unique,priority:3"`
	ComponentType string     `gorm:"type:varchar(64);not null;default:'';index:runtime_guard_key,unique,priority:4"`
	Reason        string     `gorm:"type:text"`
	Source        string     `gorm:"type:varchar(64);not null;default:''"`
	ExpiresAt     *time.Time `gorm:"index"`
}

// AutoscalePolicyBundleSpec is the regional store for the policy-shaped
// RPCs (see docs/design/tenant-aware-autoscale-policy-redesign.md
// §Policy Interface Design). One row per (scope, subject_id) holding
// the canonical AutoscalePolicySpecBundle. apply_to_all_shared_pools is
// nullable to encode the 3-state google.protobuf.BoolValue semantic at
// the request boundary (nil = follow DEFAULT scope; true / false = explicit).
//
// This is additive — does not modify the existing `autoscale_policies`
// table that the 3 auto-scaling callers (ScaleSharedPool /
// CreateTiKVCapacityReservation / RCU cron) consult via
// EvaluateAutoscalePolicy.
type AutoscalePolicyBundleSpec struct {
	// Explicit ID/CreatedAt/UpdatedAt instead of gorm.Model — this
	// table must NOT carry a DeletedAt soft-delete column. The unique
	// key is (scope, subject_id) and does not include deleted_at, so a
	// soft-deleted row would collide with a subsequent upsert
	// (ON DUPLICATE KEY UPDATE never clears deleted_at), leaving the
	// row permanently invisible to GORM's default scope. The sibling
	// AutoscalePolicy table drops gorm.Model for the same reason.
	ID                    uint `gorm:"primarykey"`
	CreatedAt             time.Time
	UpdatedAt             time.Time
	Scope                 string `gorm:"type:enum('default','tenant','shared_pool','cluster');not null;index:bundle_scope_subject,unique,priority:1"`
	SubjectID             string `gorm:"type:varchar(255);not null;index:bundle_scope_subject,unique,priority:2"`
	SpecsJSON             string `gorm:"type:text;not null"`
	ApplyToAllSharedPools *bool  `gorm:"type:tinyint(1);default:null"`
	BundleHash            string `gorm:"type:varchar(64);not null;default:''"`
}

// ScaleOperation is scoped to M1 (horizontal scale-out cancel). Columns for
// later milestones (e.g. a stage column for M2, retention-cleanup timestamps)
// are added additively when those milestones actually read/write them.
type ScaleOperation struct {
	gorm.Model
	SharedPoolID      string     `gorm:"type:varchar(128);not null;index:scale_operation_key,unique,priority:1;index:scale_operation_component_status,priority:1"`
	ComponentID       string     `gorm:"type:varchar(128);not null;default:'';index:scale_operation_component_status,priority:2"`
	ScaleOperationID  string     `gorm:"type:varchar(128);not null;index:scale_operation_key,unique,priority:2"`
	ComponentType     int32      `gorm:"not null;default:0"`
	Status            string     `gorm:"type:enum('running','succeeded','canceling','canceled','cancel_failed');not null;index:scale_operation_component_status,priority:3;index:scale_operation_status"`
	Cancelable        bool       `gorm:"not null;default:false"`
	OriginalCount     uint32     `gorm:"not null;default:0"`
	TargetCount       uint32     `gorm:"not null;default:0"`
	ReadyCount        uint32     `gorm:"not null;default:0"`
	PendingCount      uint32     `gorm:"not null;default:0"`
	ResultSummary     string     `gorm:"type:text"`
	OriginalQuotaJSON string     `gorm:"type:longtext"`
	EvidenceJSON      string     `gorm:"type:longtext"`
	CompletedAt       *time.Time `gorm:"index"`
}

const (
	LightweightRestoreStatusRunning   = "running"
	LightweightRestoreStatusSucceeded = "succeeded"
	LightweightRestoreStatusFailed    = "failed"
	LightweightRestoreStatusCancelled = "cancelled"

	LightweightRestoreActionCreateTiBR        = "create-tibr"
	LightweightRestoreActionScaleTiKV         = "scale-tikv"
	LightweightRestoreActionExecRestore       = "exec-restore"
	LightweightRestoreActionExecPackedBackup  = "exec-packed-backup"
	LightweightRestoreActionExecRestorePacked = "exec-restore-packed"
	LightweightRestoreActionRestartTiDB       = "restart-tidb"
	LightweightRestoreActionDeleteTiBR        = "delete-tibr"
	LightweightRestoreActionGrantAccess       = "grant-access"
	LightweightRestoreActionRevokeAccess      = "revoke-access"
)

type LightweightRestore struct {
	gorm.Model

	// from input
	RestoreID string `gorm:"type:varchar(128);not null;unique"`

	// generate during execution
	Status          string `gorm:"type:enum('running','succeeded','failed', 'cancelled');not null"`
	ExecutedActions string `gorm:"type:text"` // record the executed actions, separated by comma, the latest one may be done or executing
	FailureSource   string `gorm:"type:varchar(32)"`
	FailureCode     string `gorm:"type:varchar(128)"`
	FailureMessage  string `gorm:"type:text"`

	// from input & mapping
	SourceSharedPoolID  string `gorm:"type:varchar(128);index"`
	TargetSharedPoolID  string `gorm:"type:varchar(128);index"`
	SourceClusterID     string `gorm:"type:varchar(128);index"`
	TargetClusterID     string `gorm:"type:varchar(128);index"`
	TargetPdClusterID   string `gorm:"type:varchar(128)"`
	TargetKeyspace      string `gorm:"type:varchar(128)"`
	SourceKeyspace      string `gorm:"type:varchar(128)"`
	KernelBackupID      string `gorm:"type:varchar(128)"`
	KernelBackupName    string `gorm:"type:varchar(128)"`
	BackupDataSizeBytes uint64 `gorm:""`
	PointInTime         string `gorm:"type:varchar(128)"`

	// generate during execution
	PackedPath string `gorm:"type:text"`
	// only use in cross shared pool restore
	PitrBackupName          string `gorm:"type:varchar(128)"`
	PitrBackupDataSizeBytes uint64 `gorm:""`
	// refer to the PlanScale record
	ScaleID *uint              `gorm:""`
	Scale   *ScaleTikvDecision `gorm:"foreignKey:ScaleID;references:ID"`
}

const (
	ClassicRestoreStatusRunning   = "running"
	ClassicRestoreStatusSucceeded = "succeeded"
	ClassicRestoreStatusFailed    = "failed"
	ClassicRestoreStatusCancelled = "cancelled"

	ClassicRestoreActionScaleTiKV        = "scale-tikv"
	ClassicRestoreActionExecRestore      = "exec-restore"
	ClassicRestoreActionDeleteRestore    = "delete-restore"
	ClassicRestoreActionDeleteCloudAdmin = "delete-cloud-admin"
	ClassicRestoreActionRestartTiDB      = "restart-tidb"
)

type ClassicRestore struct {
	gorm.Model

	// from input
	RestoreID string `gorm:"type:varchar(128);not null;unique"`

	// generate during execution
	Status          string `gorm:"type:enum('running','succeeded','failed', 'cancelled');not null"`
	ExecutedActions string `gorm:"type:text"` // record the executed actions, separated by comma, the latest one may be done or executing
	FailureSource   string `gorm:"type:varchar(32)"`
	FailureCode     string `gorm:"type:varchar(128)"`
	FailureMessage  string `gorm:"type:text"`

	// from input & mapping
	SourceBackupStorage  string             `gorm:"type:varchar(1024)"`
	SourceRegion         string             `gorm:"type:varchar(128)"`
	BackupDataSizeBytes  uint64             `gorm:""`
	BackupCloudProvider  string             `gorm:"type:varchar(128)"`
	ClassicBackupAuth    *ClassicBackupAuth `gorm:"type:JSON;serializer:json;"`
	SourceRoleARN        string             `gorm:"type:varchar(2048)"`
	SourceRoleExternalID string             `gorm:"type:varchar(1224)"`
	TargetSharedPoolID   string             `gorm:"type:varchar(128);index"`
	TargetClusterID      string             `gorm:"type:varchar(128);index"`

	// refer to the PlanScale record
	ScaleID *uint              `gorm:""`
	Scale   *ScaleTikvDecision `gorm:"foreignKey:ScaleID;references:ID"`
}

const (
	ManualBackupStatusRunning   = "running"
	ManualBackupStatusSucceeded = "succeeded"
	ManualBackupStatusFailed    = "failed"
	ManualBackupStatusDeleting  = "deleting"
	ManualBackupStatusDeleted   = "deleted"

	ManualBackupActionCreateTiBR     = "create-tibr"
	ManualBackupActionExecBackup     = "exec-backup"
	ManualBackupActionExecPackBackup = "exec-pack-backup"
	ManualBackupActionExecCopyBackup = "exec-copy-backup"
	ManualBackupActionDeleteTiBR     = "delete-tibr"
	ManualBackupActionDeleteData     = "delete-data"
	ManualBackupActionMarkSucceeded  = "mark-succeeded"
	ManualBackupActionMarkDeleted    = "mark-deleted"
)

type ManualBackup struct {
	gorm.Model

	// from input
	BackupID  string `gorm:"type:varchar(128);not null;uniqueIndex:uk_backup_cluster"`
	ClusterID string `gorm:"type:varchar(128);not null;uniqueIndex:uk_backup_cluster"`

	// runtime status
	Status          string `gorm:"type:enum('running','succeeded','failed', 'deleting', 'deleted');not null"`
	ExecutedActions string `gorm:"type:text"`

	// infos
	SharedPoolID     string `gorm:"type:varchar(128);index"`
	KernelBackupName string `gorm:"type:varchar(256)"`
	PackedPath       string `gorm:"type:text"`
	CopyMetaPath     string `gorm:"type:text"` // used in restore
	CopyPrefix       string `gorm:"type:text"` // used for deletion
	BackupTs         uint64 `gorm:""`
	BackupSize       uint64 `gorm:""`
	RestoreSize      uint64 `gorm:""`

	LifecycleRuleAdded   *time.Time `gorm:"index"`
	LifecycleRuleDeleted *time.Time `gorm:""`
}

const (
	ManualBackupRestoreStatusRunning   = "running"
	ManualBackupRestoreStatusSucceeded = "succeeded"
	ManualBackupRestoreStatusFailed    = "failed"
	ManualBackupRestoreStatusCancelled = "cancelled"

	ManualBackupRestoreActionCreateTiBR   = "create-tibr"
	ManualBackupRestoreActionExecRestore  = "exec-restore"
	ManualBackupRestoreActionDeleteTiBR   = "delete-tibr"
	ManualBackupRestoreActionMarkSuccess  = "mark-succeeded"
	ManualBackupRestoreActionScaleTiKV    = "scale-tikv"
	ManualBackupRestoreActionGrantAccess  = "grant-access"
	ManualBackupRestoreActionRevokeAccess = "revoke-access"
	ManualBackupRestoreActionRestartTiDB  = "restart-tidb"
)

type ManualBackupRestore struct {
	gorm.Model

	RestoreID string `gorm:"type:varchar(128);not null;unique"`

	Status          string `gorm:"type:enum('running','succeeded','failed','cancelled');not null"`
	ExecutedActions string `gorm:"type:text"`
	FailureSource   string `gorm:"type:varchar(32)"`
	FailureCode     string `gorm:"type:varchar(128)"`
	FailureMessage  string `gorm:"type:text"`

	SourceClusterID    string             `gorm:"type:varchar(128);index"`
	SourceBackupID     string             `gorm:"type:varchar(128)"`
	TargetSharedPoolID string             `gorm:"type:varchar(128);index"`
	TargetClusterID    string             `gorm:"type:varchar(128);index"`
	TargetPdClusterID  string             `gorm:"type:varchar(128)"`
	TargetKeyspace     string             `gorm:"type:varchar(128)"`
	BackupMetaPath     string             `gorm:"type:text"`
	RestoreSize        uint64             `gorm:""`
	SourceSharedPoolID string             `gorm:"type:varchar(128);index"`
	ScaleID            *uint              `gorm:""`
	Scale              *ScaleTikvDecision `gorm:"foreignKey:ScaleID"`
}

type ClassicBackupAuth struct {
	AccessKeyId     string `json:"access_key_id"`
	AccessKeySecret string `json:"access_key_secret"`
}

// Notice:
// 1. once this reccords exists, it means the scale decision has been made and dispatched to operator
// 2. The status transition
//   - nil -> executing: the scale decision has been made and dispatched to operator
//   - executing -> reach_expected: the scale decision has been reached the expected state
//   - deleted_at(null -> not null): the business has been finished or canceled, it means the business won't feed data to tikv.
//     if not any business feed data to tikv, you can safely making decision base on current tikv spec and usage.
type ScaleTikvDecision struct {
	gorm.Model

	SharedPoolID string `gorm:"type:varchar(128);index;uniqueIndex:uk_scale_tikv_decision_biz,priority:1"`
	BizType      string `gorm:"type:enum('lw_restore','classic_restore','manual_backup_restore','import','auto_scaler');not null;uniqueIndex:uk_scale_tikv_decision_biz,priority:2"`
	BizID        string `gorm:"type:varchar(128);index;uniqueIndex:uk_scale_tikv_decision_biz,priority:3"`
	Status       string `gorm:"type:enum('executing','reach_expected');index;not null"`

	// scale details
	NeedScale bool          `gorm:""`
	BaseOn    string        `gorm:"type:enum('tikv_usage','another_decision');not null"`
	BaseID    uint          `gorm:""` // only used when base on other scale decision
	From      TiKVSpecUsage `gorm:"type:JSON;serializer:json;not null"`
	To        TiKVSpecUsage `gorm:"type:JSON;serializer:json;not null"`
}

const (
	ScaleStatusExecuting     = "executing"
	ScaleStatusReachExpected = "reach_expected"

	BizTypeLwRestore           = "lw_restore"
	BizTypeClassicRestore      = "classic_restore"
	BizTypeManualBackupRestore = "manual_backup_restore"
	BizTypeImport              = "import"
	BizTypeAutoScaler          = "auto_scaler"
)

const (
	BaseOnTiKVUsage       = "tikv_usage"
	BaseOnAnotherDecision = "another_decision"
)

type TiKVSpecUsage struct {
	NodeCount           uint32 `json:"node_count"`
	TotalCapacityBytes  uint64 `json:"total_capacity_bytes"`
	TotalAvailableBytes uint64 `json:"total_available_bytes"`
	UsagePercentage     uint32 `json:"usage_percentage"`
}

const (
	// shared pool is creating
	BackupGcStatusSPCreating = "sp_creating"
	// shared pool is running
	BackupGcStatusSPRunning = "sp_running"
	// shared pool is deleting, during deleting, the gc setting will be updated by the workflow
	BackupGcStatusSPDeleting = "sp_deleting"
	// shared pool is deleted
	BackupGcStatusSPDeleted = "sp_deleted"
	// shared pool is deleted, all the auto backups are expired, this can be calculated by the lifetime of backup data
	BackupGcStatusAutoBackupExpired = "auto_backup_expired"
)

var (
	BackupGcStatusesOfLivingSharedpool = []string{BackupGcStatusSPCreating, BackupGcStatusSPRunning}
	BackupGcStatusesOfInternalChanging = []string{BackupGcStatusSPCreating, BackupGcStatusSPDeleting}
)

// backup gc setting only mark as deleted when the bucket is deleted
type BackupGcSetting struct {
	gorm.Model
	Version optimisticlock.Version

	SharedPoolID        string     `gorm:"type:varchar(128);unique"`
	Status              string     `gorm:"type:enum('sp_creating', 'sp_running', 'sp_deleting', 'sp_deleted','auto_backup_expired');index;not null"`
	SharedPoolDeletedAt *time.Time `gorm:"index"`
	// if it's nil or false, it means not has manual backup
	HasManualBackup *bool `gorm:"default:false;index"`

	// will be disabled after shared pool deleted, not allow changed by api
	// if it's nil or false, it means the life cycle is not enabled
	T2StrategyEnabled *bool `gorm:"default:false"`
	// only move data with age equal or greater than this value to T2, min is 1
	MinT2DataAgeDays uint32 `gorm:""`

	// will be disabled after shared pool deleted, not allow changed by api
	// if it's nil or false, it means the life cycle is not enabled
	T3StrategyEnabled *bool `gorm:"default:false"`
	// only move data with age equal or greater than this value to T3, min is 1
	MinT3DataAgeDays uint32 `gorm:""`

	// if it is nil or zero, it means the life cycle is not enabled
	// min is 1
	MaxT1MetaLifetimeDays   *uint32 `gorm:"default:null"`
	MaxT1WalLifetimeDays    *uint32 `gorm:"default:null"` // apply to both wal and rlog
	MaxT1PackedLifetimeDays *uint32 `gorm:"default:null"`
	// min is 30 since lifetime of S3 Standard IA object is 30 days
	MaxT2SstLifetimeDays *uint32 `gorm:"default:null"`
	// min is 90 since lifetime of S3 Standard IR object is 90 days
	MaxT3DataLifetimeDays *uint32 `gorm:"default:null"`
}

// Export records an export job (Dumpling) for a TiDB cluster.
type Export struct {
	ExportID  string `gorm:"type:varchar(128);primarykey"` // unique export id
	ClusterID string `gorm:"type:varchar(128);index"`
	State     string `gorm:"type:enum('creating','running','succeeded','failed','canceled','deleted');index;not null"`

	// from proto / request
	ExportOptions string     `gorm:"type:longtext"` // export options in JSON format
	CloudStorage  string     `gorm:"type:longtext"` // cloud storage config in JSON format
	Reason        string     `gorm:"type:text"`     // failure or status reason
	SnapshotTSO   uint64     `gorm:""`
	SnapshotTime  *time.Time `gorm:""`
	Username      string     `gorm:"type:varchar(128)"`
	Password      string     `gorm:"type:text"`

	// internal: workflow idempotency and cleanup
	TiDBGroupID     string `gorm:"type:varchar(128);index"`
	DumplingJobName string `gorm:"type:varchar(256);index"`

	CompleteTime *time.Time `gorm:""`
	CreatedAt    time.Time
	UpdatedAt    time.Time
	DeletedAt    gorm.DeletedAt `gorm:"index"`
}
