package config

import (
	"time"

	"github.com/tidbcloud/pkgv2/gormutil"

	"github.com/tidbcloud/tidb-management-service/utilities/featuregate"
)

type Config struct {
	MysqlConfig  gormutil.Config `mapstructure:"mysql"`
	ProxyConfig  ProxyConfig     `mapstructure:"proxy"`
	ServerConfig ServerConfig    `mapstructure:"server"`
	AwsConfig    AwsConfig       `mapstructure:"aws"`
	// TODO: remove after migrating cloud admin
	CoreSvcSecretStore *SecretConfig      `mapstructure:"core-svc-secret"`
	Eventbus           Eventbus           `mapstructure:"eventbus"`
	RegionServerConfig RegionServerConfig `mapstructure:"regionalserver"  validate:"required"`
	BizConfig          BizConfig          `mapstructure:"biz"`
	BillingConfig      BillingConfig      `mapstructure:"billing"`
}

type ServerConfig struct {
	SecretStore           *SecretConfig                      `mapstructure:"secret"`
	DependentSvcAddresses DependentSvcAddresses              `mapstructure:"dependentServiceAddresses"`
	FeatureGates          map[string]featuregate.FeatureGate `mapstructure:"featureGates"`
}

type DependentSvcAddresses struct {
	Billing2               string     `mapstructure:"billing2"               default:"billing2:18888"              validate:"required"`
	AccountProviderSvcAddr string     `mapstructure:"accountProviderSvcAddr" default:"account-provider-grpc:10000"`
	WaitTimeoutInMilliSec  int        `mapstructure:"waitTimeoutInMilliSec"  default:"5000"`
	O11yConfig             O11yConfig `mapstructure:"o11yConfig"`
	ConfigCenterAddr       string     `mapstructure:"configCenterAddr"`
}

type O11yConfig struct {
	GlobalServerDomain string `mapstructure:"globalServerDomain"`
	BizType            string `mapstructure:"bizType"`
	Auth0Domain        string `mapstructure:"auth0Domain"`
	Auth0ClientID      string `mapstructure:"auth0ClientID"`
	Auth0Audience      string `mapstructure:"auth0Audience"`
	Auth0Secret        string `mapstructure:"auth0Secret"`
}

type AwsConfig struct {
	// AWS private certificate authority (CA) ARN.
	PCAArn string `mapstructure:"pcaArn" validate:"required"`
	// AWS KMS customer master key (CMK) ARN.
	CMKArn string `mapstructure:"cmkArn" validate:"required"`
}

type Eventbus struct {
	ProxyAddress    string `mapstructure:"proxyAddress"`
	RetryTimes      uint   `mapstructure:"retryTimes"      default:"15"`
	NumOfGoroutines uint   `mapstructure:"numOfGoroutines" default:"5"`
}

type SecretConfig struct {
	SecretKey  string `mapstructure:"secretKey"`
	Region     string `mapstructure:"region"`
	Profile    string `mapstructure:"profile"`
	RetryCount int    `mapstructure:"retryCount" default:"5"`
}

type ProxyConfig struct {
	Auth0Domain       string `mapstructure:"auth0Domain"       validate:"required"`
	Auth0ClientID     string `mapstructure:"auth0ClientID"     validate:"required"`
	Auth0ClientSecret string `mapstructure:"auth0ClientSecret"`
	Auth0Audience     string `mapstructure:"auth0Audience"     validate:"required"`
}

type RegionServerConfig struct {
	RequestTimeoutInSec   int `mapstructure:"requestTimeoutInSec"   validate:"required"`
	RetryCount            int `mapstructure:"retryCount"            validate:"required"`
	RetryWaitTimeoutInSec int `mapstructure:"retryWaitTimeoutInSec" validate:"required"`
}

type BizConfig struct {
	ClusterQuota ClusterQuota `mapstructure:"clusterQuota"`

	// NormalPauseScheduleDay is the default pause schedule day for normal pause plan.
	// The min value is 1 day.
	NormalPauseScheduleDay int `mapstructure:"normalPauseScheduleDay" default:"7"`
	// NormalPauseNotifyHour is the default notify hour for normal pause plan.
	// The min value is 12 hours.
	NormalPauseNotifyHour int `mapstructure:"normalPauseNotifyHour" default:"24"`

	// MaxTidbNodeGroupCount is the maximum number of TiDB node groups allowed in a cluster.
	MaxTidbNodeGroupCount int `mapstructure:"maxTidbNodeGroupCount" default:"25"`
	// defaultMaxTidbNodeGroupCountPerProjectInGCPRegion is the max count of tidb node group in a gcp region for each project.
	// This is limited by the ip allocation implementation on GCP,
	// refer to: https://pingcap.feishu.cn/wiki/Etk8wGGDDiklBck1nCXc16ZSnSd#share-GgKLdjkgVoLCYjxfznhcAZmunIb
	MaxTidbNodeGroupCountPerProjectInGCP  int `mapstructure:"maxTidbNodeGroupCountPerProjectInGCP" default:"8"`
	AwsPrivateLinkEndpointLimitPerGroup   int `mapstructure:"maxAwsPrivateLinkEndpointLimit"       default:"15"`
	GcpPrivateLinkEndpointLimitPerGroup   int `mapstructure:"maxGcpPrivateLinkEndpointLimit"       default:"10"`
	AzurePrivateLinkEndpointLimitPerGroup int `mapstructure:"maxAzurePrivateLinkEndpointLimit"     default:"15"`

	// Timeout configuration for handling insufficient resource conditions.
	// Refer to feature spec https://pingcap.feishu.cn/wiki/AWo6wdrNiiJa9Jkbr4rc51xMntB.
	InsufficientResourceTimeout string `mapstructure:"insufficientResourceTimeoutMinutes" default:"20m"`

	ClusterService     ClusterServiceConf `mapstructure:"clusterService"`
	ClusterCertsConfig ClusterCertsConfig `mapstructure:"clusterCertsConfig"`
}

type ClusterServiceConf struct {
	ScaleOptions map[string]*featuregate.FeatureGate `mapstructure:"scaleOptions"`
}

type ClusterCertsConfig struct {
	Bucket string `mapstructure:"bucket" validate:"required"`
}

type ClusterQuota struct {
	TiDB    int `mapstructure:"tidb"    default:"10"`
	TiKV    int `mapstructure:"tikv"    default:"15"`
	TiFlash int `mapstructure:"tiflash" default:"5"`
	TiProxy int `mapstructure:"tiproxy" default:"10"`

	// if the multi_4c_tikv feature gates are enabled, the max 4c tikv node count will be determined by the following value
	Max4CTikvCount int `mapstructure:"max4cTikvCount" default:"6"`
}

type BillingConfig struct {
	RecordsToBeCleanedLimit          int           `mapstructure:"recordsToBeCleanedLimit"          default:"10000"`
	ExpireDurationForClusterMetering time.Duration `mapstructure:"expireDurationForClusterMetering" default:"10s"` // clean all NON-latest metering records
	ExpireDurationForBillingRecord   time.Duration `mapstructure:"expireDurationForBillingRecord"   default:"10s"` // clean all synced billing records
	// for instance metering switch
	InstanceMeteringSwitchTime uint64 `mapstructure:"instanceMeteringSwitchTime"`
	// for instance metering switch time block specific to tenant
	InstanceMeteringSwitchTimeBlockList []MeteringTenantFilter `mapstructure:"instanceMeteringSwitchTimeBlockList"`
	InstanceTenantSwitchFilter          []MeteringTenantFilter `mapstructure:"instanceTenantSwitchFilter"`
}

type MeteringTenantFilter struct {
	TenantID   uint64 `mapstructure:"tenantID"`
	SwitchTime uint64 `mapstructure:"switchTime"`
}
