package config

import (
	"fmt"
	"time"

	"github.com/tidbcloud/core-svc/idl/pbgen/proto/core"
	entity "github.com/tidbcloud/core-svc/model"
)

type (
	Auth0ConnectionType string
)

const (
	Auth0DatabaseConnection     Auth0ConnectionType = "custom-email"
	Auth0SocialConnectionGoogle Auth0ConnectionType = "google-oauth2"
	Auth0SocialConnectionGithub Auth0ConnectionType = "github"
)

func (c Auth0ConnectionType) String() string {
	return string(c)
}

func (c Auth0ConnectionType) IsAuth0SocialConnection() bool {
	if c == Auth0SocialConnectionGoogle || c == Auth0SocialConnectionGithub {
		return true
	}
	return false
}

const (
	TimeFmtDTM = "2006-01-02 15:04:05"

	// SystemEmail is the email used for autonomous operations
	SystemEmail = "system@pingcap.com"

	DefaultUtcOffset    = "0"
	DefaultTidbQuota    = 20
	DefaultTikvQuota    = 30
	DefaultTiflashQuota = 30
	DefaultProjectName  = "default project"

	FinalBackupName                      = "final-backup"
	RegionDefaultBackupTimeFormat        = "15:04"
	MaxAutoBackups                uint64 = 7
	DefaultAutoBackupHour                = 2
	DevTierMaxAutoBackups         uint64 = 1
	DevTierMaxManualBackups       uint64 = 2

	PortalAuthorizationHeader = "Portal-Authorization"
	SalesforceApiKeyName      = "salesforce"
	ProfileMngApiKeyName      = "profile_mng"

	// Deployment stage
	StageProd    = "prod"
	StageStaging = "staging"

	Duration4DevTierCloseToEndStage1   = 14 * time.Hour * 24  // two week before trial end
	Duration4DevTierCloseToEndStage2   = 2 * time.Hour * 24   // two day before trial end
	Duration4DevTierTrialTotal         = 365 * time.Hour * 24 // total duration of dev tier trial
	Duration4DevTierIdleStageEncourage = 2 * time.Hour * 24
	Duration4DevTierIdleStageWarning   = 6 * time.Hour * 24
	Duration4DevTierIdleStageShutdown  = 7 * time.Hour * 24
	MaxTrafficUsagePerWeek4DevTier     = 20 * 1024 * 1024 * 1024 // 20GB
	ThrottledDevTierBandwidth          = "10KiB/s"
	DevTierImportStorageRequest        = "100Gi"

	DefaultDBOperationTimeout = 30 * time.Second

	// Max metrics key count
	MaxMetricsKeyCount = 10

	GetClusterTsoClase            = "SHOW MASTER STATUS;"
	GetGCLifeTimeClause           = "SELECT VARIABLE_VALUE FROM mysql.tidb WHERE VARIABLE_NAME = 'tikv_gc_life_time';"
	SetGCLifeTimeClause           = "SET GLOBAL TIDB_GC_LIFE_TIME='%s';"
	SetRestrictReadonlyClause     = "SET GLOBAL TIDB_RESTRICTED_READ_ONLY='%s'"
	SetSuperReadonlyClause        = "SET GLOBAL TIDB_SUPER_READ_ONLY='%s'"
	GetAuditLogStatusClause       = "SHOW GLOBAL VARIABLES WHERE VARIABLE_NAME = 'tidb_audit_redact_log'"
	SetAuditLogRedactStatusClause = "SET @@GLOBAL.tidb_audit_redact_log = %s"
	SetAuditLogMaxSize            = "SET @@GLOBAL.tidb_audit_log_max_size = 10485760"
	EnableAuditPluginClause       = "admin plugins enable audit"
	DisableAuditPluginClause      = "admin plugins disable audit"
	GetAllAuditLogAccessClause    = "SELECT id, user, db, tbl, access_type FROM mysql.tidb_audit_table_access ORDER BY id"
	DeleteAuditLogAccessClause    = "DELETE FROM mysql.tidb_audit_table_access WHERE id=%d"
	CreateAuditLogAccessClause    = "INSERT INTO mysql.tidb_audit_table_access (`user`, `db`, `tbl`, `access_type`, `create_time`) VALUES ('%s', '%s', '%s', '%s', NOW())"
	FlushAuditLogAccessClause     = "FLUSH tidb plugins audit"
	ReplicationGcLifeTime         = "72h"
	PhysicalShiftBits             = 18

	// audit log
	AuditRedactLogStatusON  = "ON"
	AuditRedactLogStatusOFF = "OFF"

	// cluster proxy
	DefaultClusterProxyTimeout  = 8
	AuditLogClusterproxyTimeout = 30

	// cluster tier
	RecommendedNodeCpuNum        int32 = 8
	RecommendedTiFlashNodeCpuNum int32 = 16
)

const (
	ErrImpersonatedUser = "impersonated user is a read only user"
	ErrProjectCIDRExist = "Project CIDR already exist"
)

var (
	UserVisibleClusterComponents = []core.ComponentType{
		core.ComponentType_COMPONENT_TYPE_TIDB,
		core.ComponentType_COMPONENT_TYPE_TIKV,
		core.ComponentType_COMPONENT_TYPE_TIFLASH,
	}
	CreatingClusterStatusSet = map[core.ClusterStatus]bool{
		core.ClusterStatus_CLUSTER_STATUS_INITIALIZING: true,
		core.ClusterStatus_CLUSTER_STATUS_PREPARING:    true,
		core.ClusterStatus_CLUSTER_STATUS_LAUNCHING:    true,
	}
	ClusterStatusPb2model = map[core.ClusterStatus]entity.ClusterStatus{
		core.ClusterStatus_CLUSTER_STATUS_INITIALIZING:   entity.ClusterStatusInitializing,
		core.ClusterStatus_CLUSTER_STATUS_PREPARING:      entity.ClusterStatusPreparing,
		core.ClusterStatus_CLUSTER_STATUS_LAUNCHING:      entity.ClusterStatusLaunching,
		core.ClusterStatus_CLUSTER_STATUS_NORMAL:         entity.ClusterStatusNormal,
		core.ClusterStatus_CLUSTER_STATUS_HIBERNATED:     entity.ClusterStatusHibernated,
		core.ClusterStatus_CLUSTER_STATUS_PAUSING:        entity.ClusterStatusPausing,
		core.ClusterStatus_CLUSTER_STATUS_PAUSED:         entity.ClusterStatusPaused,
		core.ClusterStatus_CLUSTER_STATUS_RESUMING:       entity.ClusterStatusResuming,
		core.ClusterStatus_CLUSTER_STATUS_SCALING:        entity.ClusterStatusScaling,
		core.ClusterStatus_CLUSTER_STATUS_RECOVERING:     entity.ClusterStatusRecovering,
		core.ClusterStatus_CLUSTER_STATUS_DELETED:        entity.ClusterStatusDeleted,
		core.ClusterStatus_CLUSTER_STATUS_DELETECOMPLETE: entity.ClusterStatusDeletecomplete,
		core.ClusterStatus_CLUSTER_STATUS_CLEARED:        entity.ClusterStatusCleared,
	}
)

// checkClusterStatusPb2model ensure all statuses have mapping
func checkClusterStatusPb2model() {
	for key := range core.ClusterStatus_name {
		status := core.ClusterStatus(key)
		if status == core.ClusterStatus_CLUSTER_STATUS_UNSPECIFIED {
			continue
		}

		if _, ok := ClusterStatusPb2model[status]; !ok {
			panic(fmt.Sprintf("[checkClusterStatusPb2model]missing status mapping in ClusterStatusPb2model: %s", status))
		}
	}
}

func init() {
	checkClusterStatusPb2model()
}

func UserVisibleClusterComponentsContains(c core.ComponentType) bool {
	for _, v := range UserVisibleClusterComponents {
		if v == c {
			return true
		}
	}
	return false
}

var (
	// audit log
	ValidAuditLogAccessTypeOption = map[string]bool{
		"AlterTable":        true,
		"AnalyzeTable":      true,
		"Begin":             true,
		"Change":            true,
		"Commit":            true,
		"CreateDatabase":    true,
		"CreateIndex":       true,
		"CreateTable":       true,
		"CreateView":        true,
		"CreateUser":        true,
		"Delete":            true,
		"DropDatabase":      true,
		"DropIndex":         true,
		"DropView":          true,
		"DropTable":         true,
		"DescTable":         true,
		"ExplainAnalyzeSQL": true,
		"ExplainSQL":        true,
		"Replace":           true,
		"Insert":            true,
		"LoadData":          true,
		"RollBack":          true,
		"Select":            true,
		"Set":               true,
		"Show":              true,
		"TruncateTable":     true,
		"Update":            true,
		"Grant":             true,
		"Revoke":            true,
		"Deallocate":        true,
		"Execute":           true,
		"Prepare":           true,
		"Use":               true,
		"CreateBinding":     true,
		"IndexAdvise":       true,
		"DropBinding":       true,
		"Trace":             true,
		"Shutdown":          true,
		"other":             true,
	}
)
