package entity

import (
	"database/sql/driver"
)

type (
	// Cloud is the cloud DBaaS runs in. The laptop is "local"
	ProviderStatus       string
	ProfileStatus        string
	ComponentName        string
	ProfileVersionStatus string
	PrecheckStatus       string
	MeteringKind         string
	DMJobModifyType      string
)

const (
	PD      ComponentName = "pd"      // Placement Driver
	TiKV    ComponentName = "tikv"    // TiKV
	TiDB    ComponentName = "tidb"    // TiDB
	TiFlash ComponentName = "tiflash" // TiFlash
	TiCDC   ComponentName = "ticdc"   // TiCDC

	CloudAdminUser = "cloud_admin" // cloudadmin user for controlplane to access customer tidb cluster

	// DMPrecheck Status
	// ┌──────┐       ┌───────┐      ┌────────┐
	// │FAILED│◄──────┤RUNNING├─────►│CANCELED│
	// └──────┘       └───┬───┘      └────────┘
	//               ┌────▼───┐
	//               │FINISHED│
	//               └────────┘
	// the precheck job and precheck item starts with `running`
	// and get `canceled` if the user cancel it.
	// The status turns `finished` if all items succeed for a precheck job
	// or item is successfully run by the agent.
	// The status becomes `failed` if any internal error occurs
	// in the above procedure.
	PrecheckStatusFinished PrecheckStatus = "finished"
	PrecheckStatusFailed   PrecheckStatus = "failed"
	PrecheckStatusCancel   PrecheckStatus = "canceled"
	PrecheckStatusRunning  PrecheckStatus = "running"
	PrecheckStatusPending  PrecheckStatus = "pending"

	// MeteringKind
	MeteringKindNode     MeteringKind = "node"
	MeteringKindEndpoint MeteringKind = "endpoint"
	MeteringKindInput    MeteringKind = "input"
	MeteringKindOutput   MeteringKind = "output"
	MeteringKindNat      MeteringKind = "nat"

	// DMJobModifyType
	DMJobModifyTypeScaleUpDown DMJobModifyType = "scale-up-down"
)

type (
	// enum
	ImportStatus      string
	ImportTableResult string
	ImportIntoStatus  string
	DetachType        string
	DevTierIdleStage  string // the idle stage of dev tier, such as: warning, shutdown
	DevTierTrialStage string // the ending stage of dev tier, such as: one-month before end
	DataFormat        uint32
	DataSource        uint32
	PeeringStatus     string // the status of aws/gcp vpc peering
	// Cloud is the cloud DBaaS runs in. The laptop is "local"
	Cloud string

	ConnMethod string
	// PLEndpointPhase inner status of private link endpoint
	// newly created is in pending, deleted will be in deleted state phase.
	// phase transition:
	//  ┌───┐  ┌───────┐                          ┌──────────┐  ┌──────────┐
	//  │new│─►│pending├─────────────────────────►│available │  │deleted   │
	//  └─┬─┘  └───┬──▲┘                          └───┬──────┘  └──────────┘
	//    │        │  └────┌──────────────────┐   ▲   │         (any phase can turn into deleted)
	//    │        ├──────►│pending-acceptance├───┘   │
	//    │        │       └────────┬─────────┘       ▼
	//    │        │                │             ┌──────┐
	//    └────────┴────────────────┴────────────►│failed│
	//                                            └──────┘
	// 	new -> pending: start create it
	// 	new -> failed: for deduplication
	// 	pending -> available: endpoint is available
	// 	pending -> pending-acceptance: endpoint need manually accept
	// 	pending-acceptance -> pending: endpoint has manually accepted
	// 	pending/pending-acceptance -> failed: if endpoint request is failed, rejected or expired
	// 	pending-acceptance -> available: user manually accept the request
	// 	available -> failed: endpoint might be rejected/deleted
	// 	available -> deleted: if the endpoint is not used by any job for some time
	PLEndpointPhase string
	// DFJobPhase job lifecycle in dataflow-service.
	// newly created job is in creating phase. deleted job(from any phase) will be in deleting phase
	// dataflow-worker will create or delete in background in async way.
	// job will be in finished phase if it's a full mode job and finished,
	// background worker will delete the underlying resources.
	// phase transition:
	//                 ┌────────────┐
	//                 │ modifying  │
	//                 └───┬────▲───┘
	//                     │    │
	//                     │    │
	// ┌────────────┐  ┌───▼────┴───┐   ┌────────────┐   ┌────────────┐
	// │  creating  ├──►  created   ├───► finishing  ├───►  finished  │
	// └────────────┘  └────────────┘   └────────────┘   └────────────┘
	//      ┌────────┐     ┌───────┐
	//      │deleting├────►│deleted│
	//      └────────┘     └───────┘
	// (from any phase except deleted)
	//
	// 	creating -> created
	// 	any phase -> deleting -> deleted.
	// 	created -> unrecoverable (if the job met an unrecoverable error)
	// 	created -> finishing (if a one-time job finished)
	//  finishing -> finished (if a one-time job is cleaned)
	//  created -> modifying (if the job changes the spec)
	//  modifying -> created (if the job finishes scaling up/down)
	DFJobPhase      string
	ServiceCode     string
	DBType          string
	DMJobMode       string
	DMShardMode     string
	DMCollationMode string
	DMImportMode    string
	DMStageType     string
	DMStagePhase    string
	ArchType        string
	ImportExecutor  string
)

func (s ImportStatus) String() string {
	return string(s)
}

func (s ImportTableResult) String() string {
	return string(s)
}

// enums
const (
	ImportStatusUnknown   ImportStatus = "unknown"
	ImportStatusPreparing ImportStatus = "preparing"
	ImportStatusImporting ImportStatus = "importing"
	ImportStatusCompleted ImportStatus = "completed"
	ImportStatusFailed    ImportStatus = "failed"
	ImportStatusCanceling ImportStatus = "canceling"
	ImportStatusCanceled  ImportStatus = "canceled"

	ImportIntoStatusUnknown   ImportIntoStatus = "unknown"
	ImportIntoStatusPreparing ImportIntoStatus = "preparing"
	ImportIntoStatusImporting ImportIntoStatus = "importing"
	ImportIntoStatusCompleted ImportIntoStatus = "completed"
	ImportIntoStatusFailed    ImportIntoStatus = "failed"
	ImportIntoStatusCanceling ImportIntoStatus = "canceling"
	ImportIntoStatusCanceled  ImportIntoStatus = "canceled"
	ImportIntoStatusScalingUp ImportIntoStatus = "scaling"

	// keep compatible with https://github.com/tidbcloud/dataflow-service/blob/166daf6f3e72284538e93dc1bea94a78c88f0daf/idl/idl/dataflow/dataflow/service.proto#L79-L82
	ImportDataFormatUnknown        DataFormat = 0
	ImportDataFormatSql            DataFormat = 1
	ImportDataFormatAuroraSnapshot DataFormat = 2
	ImportDataFormatCsv            DataFormat = 3
	ImportDataFormatParquet        DataFormat = 4

	ImportDataSourceUnknown DataSource = 0
	ImportDataSourceS3      DataSource = 1
	ImportDataSourceGcs     DataSource = 2
	ImportDataSourceAzblob  DataSource = 3

	ImportIntoSchemaOnlySuccessMessage = "Schema created successfully. No data files found."

	ImportTableResultSuccess ImportTableResult = "success"
	ImportTableResultWarning ImportTableResult = "warning"
	ImportTableResultError   ImportTableResult = "error"

	ConnMethodDirect      ConnMethod = "direct"
	ConnMethodPrivateLink ConnMethod = "private-link"
	ConnMethodVPCPeering  ConnMethod = "vpc-peering"

	PLEndpointPhaseNew               PLEndpointPhase = "new"
	PLEndpointPhasePending           PLEndpointPhase = "pending"
	PLEndpointPhasePendingAcceptance PLEndpointPhase = "pending-acceptance"
	PLEndpointPhaseAvailable         PLEndpointPhase = "available"
	PLEndpointPhaseFailed            PLEndpointPhase = "failed"
	PLEndpointPhaseDeleted           PLEndpointPhase = "deleted"

	DFJobPhaseCreating      DFJobPhase = "creating"
	DFJobPhaseCreated       DFJobPhase = "created"
	DFJobPhaseUnrecoverable DFJobPhase = "unrecoverable"
	DFJobPhaseDeleting      DFJobPhase = "deleting"
	DFJobPhaseDeleted       DFJobPhase = "deleted"
	DFJobPhaseModifying     DFJobPhase = "modifying"
	DFJobPhaseFinishing     DFJobPhase = "finishing"
	DFJobPhaseFinished      DFJobPhase = "finished"

	ServiceCodeDM ServiceCode = "dm"

	DBTypeMySQL              DBType = "mysql"
	DBTypeAWSAuroraMySQL     DBType = "aws-aurora-mysql"
	DBTypeAWSRDSMySQL        DBType = "aws-rds-mysql"
	DBTypeGoogleCloudMySQL   DBType = "google-cloud-mysql"
	DBTypeAzureFlexibleMySQL DBType = "azure-flexible-mysql"

	DMJobModeIncr DMJobMode = "incremental"
	// DMJobModeFull will start a full task in tiflow-executor directly.
	// Later we will support accelerate full mode like we do in all mode
	DMJobModeFull DMJobMode = "full"
	// DMJobModeAll will start a dump task first.
	// Then we will choose using import API + incremental task or
	// load&sync depends on user's configuration
	DMJobModeAll      DMJobMode = "all"
	DMJobModeDump     DMJobMode = "dump"
	DMJobModeLoadSync DMJobMode = "load&sync"

	DMShardModePessimistic DMShardMode = "pessimistic"
	DMShardModeOptimistic  DMShardMode = "optimistic"
	DMShardModeNone        DMShardMode = ""

	DMCollationModeLoose  DMCollationMode = "loose"
	DMCollationModeStrict DMCollationMode = "strict"

	DMImportModePhysical DMImportMode = "physical"
	DMImportModeLogical  DMImportMode = "logical"

	// dm job usually goes through three stages: dump -> load -> sync
	DMStageDump DMStageType = "dump"
	DMStageLoad DMStageType = "load"
	DMStageSync DMStageType = "sync"

	DMStagePhaseCreating  = "creating"
	DMStagePhaseCreated   = "created"
	DMStagePhaseFinished  = "finished"
	DMStagePhaseFinishing = "finishing"
	DMStagePhaseModifying = "modifying"

	// TODO(ideascf): [DM] remove me after all legacy code are cleaned
	DMWorkerVersionV2 = "v2"

	CloudNativeArch ArchType = "cloudnative"
	ThreeLayerArch  ArchType = "3layer"

	ServerTierNextGeneration = "next_generation"

	ImportIntoJobStatusPending  = "pending"
	ImportIntoJobStatusRunning  = "running"
	ImportIntoJobStatusCanceled = "canceled"
	ImportIntoJobStatusFailed   = "failed"
	ImportIntoJobStatusFinished = "finished"
)

const (
	// Gcp is the GCP cloud
	Gcp = Cloud("gcp")

	// Aws is the AWS cloud
	Aws = Cloud("aws")

	// Azure is the Azure cloud
	Azure = Cloud("azure")
)

// Scan is for gorm
func (u *Cloud) Scan(value interface{}) error {
	*u = Cloud(value.([]byte))
	return nil
}

// Value is for gorm
func (u Cloud) Value() (driver.Value, error) { return string(u), nil }

func (u Cloud) String() string {
	return string(u)
}

func (m ConnMethod) DisplayName() string {
	switch m {
	case ConnMethodDirect:
		return "Public IP"
	case ConnMethodPrivateLink:
		return "Private Link"
	case ConnMethodVPCPeering:
		return "VPC Peering"
	default:
		return "<unknown>"
	}
}

func (t DBType) DisplayName() string {
	switch t {
	case DBTypeMySQL:
		return "MySQL"
	case DBTypeAWSAuroraMySQL:
		return "AWS Aurora MySQL"
	case DBTypeAWSRDSMySQL:
		return "AWS RDS MySQL"
	case DBTypeGoogleCloudMySQL:
		return "Google Cloud MySQL"
	case DBTypeAzureFlexibleMySQL:
		return "Azure Flexible MySQL"
	default:
		return "<unknown>"
	}
}

type RestoreKernelStatus string

const (
	RestoreKernelStatusPENDING RestoreKernelStatus = "pending"
	RestoreKernelStatusRUNNING RestoreKernelStatus = "running"
	RestoreKernelStatusFAILED  RestoreKernelStatus = "failed"
	RestoreKernelStatusSUCCESS RestoreKernelStatus = "success"
)
