package models

func NewCreateClusterInfo(provider, name, region, rootPassword string, is_dev_tier bool,
	port, tidbCount, tikvCount, tiflashCount, tidbStorage, tikvStorage, tiflashStorage int, tidbNodeSize,
	tikvNodeSize, tiflashNodeSize string) *CreateClusterReq {

	if is_dev_tier == false {
		if tiflashCount == 0 {
			return &CreateClusterReq{Name: name, Region: region, CloudProvider: provider,
				ClusterType: "DEDICATED",
				Config: &ClusterConfig{
					RootPassword: rootPassword,
					Port:         int32(port),
					Components: &ClusterComponents{
						Tidb: &TiDBComponent{NodeSize: tidbNodeSize, StorageSizeGib: int32(tidbStorage), NodeQuantity: int32(tidbCount)},
						Tikv: &TiKVComponent{NodeSize: tikvNodeSize, StorageSizeGib: int32(tikvStorage), NodeQuantity: int32(tikvCount)},
					},
					IpAccessList: []*IpAccessListItem{
						{
							Cidr:        "0.0.0.0/0",
							Description: "allow all",
						},
					},
				},
			}
		} else {
			return &CreateClusterReq{Name: name, Region: region, CloudProvider: provider,
				ClusterType: "DEDICATED",
				Config: &ClusterConfig{
					RootPassword: rootPassword,
					Port:         int32(port),
					Components: &ClusterComponents{
						Tidb:    &TiDBComponent{NodeSize: tidbNodeSize, StorageSizeGib: int32(tidbStorage), NodeQuantity: int32(tidbCount)},
						Tikv:    &TiKVComponent{NodeSize: tikvNodeSize, StorageSizeGib: int32(tikvStorage), NodeQuantity: int32(tikvCount)},
						Tiflash: &TiFlashComponent{NodeSize: tiflashNodeSize, StorageSizeGib: int32(tiflashStorage), NodeQuantity: int32(tiflashCount)},
					},
					IpAccessList: []*IpAccessListItem{
						{
							Cidr:        "0.0.0.0/0",
							Description: "allow all",
						},
					},
				},
			}
		}

	} else {
		return &CreateClusterReq{Name: name, Region: region, CloudProvider: provider,
			ClusterType: "DEVELOPER",
			Config: &ClusterConfig{
				RootPassword: rootPassword,
				IpAccessList: []*IpAccessListItem{
					{
						Cidr:        "0.0.0.0/0",
						Description: "allow all",
					},
				},
			},
		}
	}
}

type UpdateClusName struct {
	ClusterName string `json:"cluster_name"`
}

type Cidr struct {
	Cidr        string `json:"cidr"`
	Description string `json:"description"`
}

func NewCidr(cidr, description string) *Cidr {
	return &Cidr{cidr, description}
}

type AWSVpc struct {
	TenantRegion    string `json:"tenant_region"`
	TenantVpcId     string `json:"tenant_vpc_id"`
	TenantAccountId string `json:"tenant_account_id"`
	TenantVpcCidr   string `json:"tenant_vpc_cidr"`
	Region          string `json:"region"`
}

func NewAWSVpc(tenantRegion, tenantVpcId, tenantAccountId, tenantVpcCidr, region string) *AWSVpc {
	return &AWSVpc{tenantRegion, tenantVpcId,
		tenantAccountId, tenantVpcCidr, region}
}

type GCPVpc struct {
	TenantProjectId   string `json:"tenant_project_id"`
	TenantVpcRegion   string `json:"tenant_vpc_region"`
	RenantNetworkName string `json:"tenant_network_name"`
	Region            string `json:"region"`
	GcpVpcCidr        string `json:"tenant_vpc_cidr"`
}

func NewGCPVpc(tenantProjectId, tenantVpcRegion, renantNetworkName, region, gcpVpcCidr string) *GCPVpc {
	return &GCPVpc{tenantProjectId, tenantVpcRegion,
		renantNetworkName, region, gcpVpcCidr}
}

type BankCardInfo struct {
	Type       string `form:"payment_method_data[type]"`
	Email      string `form:"payment_method_data[billing_details][email]"`
	Phone      string `form:"payment_method_data[billing_details][phone]"`
	Name       string `form:"payment_method_data[billing_details][name]"`
	Line1      string `form:"payment_method_data[billing_details][address][line1]"`
	City       string `form:"payment_method_data[billing_details][address][city]"`
	Country    string `form:"payment_method_data[billing_details][address][country]"`
	PostalCode string `form:"payment_method_data[billing_details][address][postal_code]"`

	State    string `form:"payment_method_data[billing_details][address][state]"`
	Number   string `form:"payment_method_data[card][number]"`
	Cvc      string `form:"payment_method_data[card][cvc]"`
	ExpMonth string `form:"payment_method_data[card][exp_month]"`
	ExpYear  string `form:"payment_method_data[card][exp_year]"`
	Guid     string `form:"payment_method_data[guid]"`
	Muid     string `form:"payment_method_data[muid]"`
	Sid      string `form:"payment_method_data[sid]"`

	PastedFields              string `form:"payment_method_data[pasted_fields]"`
	PaymentUserAgent          string `form:"payment_method_data[payment_user_agent]"`
	TimeOnPage                string `form:"payment_method_data[time_on_page]"`
	Referrer                  string `form:"payment_method_data[referrer]"`
	ExpectedPaymentMethodType string `form:"expected_payment_method_type"`
	UseStripeSdk              string `form:"use_stripe_sdk"`
	WebauthnUvpaAvailable     string `form:"webauthn_uvpa_available"`
	SpcEligible               string `form:"spc_eligible"`
	Key                       string `form:"key"`
	ClientSecret              string `form:"client_secret"`
}

func NewBankCardInfo(number, client_secret string) *BankCardInfo {
	return &BankCardInfo{"card", "zhongmin@pingcap.com", "15608225", "test", "test",
		"test", "US", "100000", "test", number, "123", "03",
		"23", "ffc076db-2625-4130-a12b-a5c7a0e29ad1d38d9d", "5b761adb-a1b8-4023-b3f3-73ba0ea31169d96979",
		"65ba5cc1-513f-4b62-a525-8b1535f955cee0c83f", "number", "stripe.js/08e0cc1e0; stripe-js-v3/08e0cc1e0",
		"367261", "https://staging.tidbcloud.com/", "card", "true",
		"true", "false", "",
		client_secret}
}

type EditBandCard struct {
	Id             string    `json:"id"`
	Card           *CardInfo `json:"card"`
	BillingDetails *Detail   `json:"billing_details"`
	Orgid          string    `json:"org_id"`
}

type CardInfo struct {
	Brand       string `json:"brand"`
	Country     string `json:"country"`
	ExpMonth    string `json:"exp_month"`
	ExpYear     string `json:"exp_year"`
	Fingerprint string `json:"fingerprint"`
	Funding     string `json:"funding"`
	Last4       string `json:"last4"`
}

func NewCardInfo(brand, fingerprint, last4 string) *CardInfo {
	return &CardInfo{brand, "US",
		"3", "2023", fingerprint, "credit", last4}
}

type Detail struct {
	Address *AddreeInfo `json:"address"`
	Email   string      `json:"email"`
	Name    string      `json:"name"`
	Phone   string      `json:"phone"`
}

func NewDetail(name string) *Detail {
	addressInfo := NewAddreeInfo()
	return &Detail{addressInfo, "zhongmin@pingcap.com", name, "15608225"}
}

type AddreeInfo struct {
	City       string `json:"city"`
	Country    string `json:"country"`
	Line1      string `json:"line1"`
	Line2      string `json:"line2"`
	PostalCode string `json:"postal_code"`
	State      string `json:"state"`
}

func NewAddreeInfo() *AddreeInfo {
	return &AddreeInfo{"test", "US", "test", "", "100000", "test"}
}

func NewEditBandCard(id, brand, fingerprint, last4, name, org_id string) *EditBandCard {
	cardInfo := NewCardInfo(brand, fingerprint, last4)
	detail := NewDetail(name)
	return &EditBandCard{id, cardInfo, detail, org_id}
}

type SetDefaultBankCard struct {
	DefaultSource string `json:"default_source"`
}

func NewSetDefaultBankCard(defaultSource string) *SetDefaultBankCard {
	return &SetDefaultBankCard{defaultSource}
}

type InviteUser struct {
	Email string `json:"email"`
	Role  string `json:"role"`
}

func NewInviteUser(email string) *InviteUser {
	return &InviteUser{email, "member"}
}

type Auth0User struct {
	Password string `json:"password"`
	Token    string `json:"token"`
}

func NewAuth0User(password, token string) *Auth0User {
	return &Auth0User{password, token}
}

type Authenticate struct {
	ClientId        string `json:"client_id"`
	Username        string `json:"username"`
	Password        string `json:"password"`
	Realm           string `json:"realm"`
	Credential_type string `json:"credential_type"`
}

func NewAuthenticate(clientId, username, password string) *Authenticate {
	return &Authenticate{clientId, username, password,
		"custom-email", "http://auth0.com/oauth/grant-type/password-realm"}
}

type Authorize struct {
	ClientId     string `url:"client_id"`
	ResponseType string `url:"response_type"`
	RedirectUri  string `url:"redirect_uri"`
	Scope        string `url:"scope"`
	Realm        string `url:"realm"`
	State        string `url:"state"`
	Nonce        string `url:"nonce"`
	LoginTicket  string `url:"login_ticket"`
	Auth0Client  string `url:"auth0Client"`
}

func NewAuthorize(clientId, redirectUri,
	state, nonce, loginTicket, auth0Client string) *Authorize {
	return &Authorize{clientId, "token id_token", redirectUri,
		"openid email", "custom-email", state, nonce, loginTicket, auth0Client}
}

type Acception struct {
	FirstName string `json:"first_name"`
	LastName  string `json:"last_name"`
	Email     string `json:"email"`
	OrgId     string `json:"org_id"`
}

func NewAcception(email, org_id string) *Acception {
	return &Acception{"test", "test", email, org_id}
}

type ImportData struct {
	//ClusterId string `json:"cluster_id"`
	SourceUrl          string `json:"source_url"`
	TargetUsername     string `json:"target_username"`
	Filter             string `json:"filter"`
	TargetPassword     string `json:"target_password"`
	DataSourceType     int    `json:"data_source_type"`
	Region             string `json:"region"`
	DataFormat         int    `json:"data_format"`
	AwsRoleArn         string `json:"aws_role_arn"`
	CsvFormat          *Csv   `json:"csv_format"`
	ObjectNamePattern  string `json:"object_name_pattern"`
	TargetTablePattern string `json:"target_table_pattern"`
}

type Csv struct {
	BackslashEscape   bool   `json:"backslash_escape"`
	Delimiter         string `json:"delimiter"`
	Header            bool   `json:"header"`
	NotNull           bool   `json:"not_null"`
	Null              string `json:"null"`
	Separator         string `json:"separator"`
	TrimLastSeparator bool   `json:"trim_last_separator"`
}

func NewImportData(sourceUrl,
	dbPassword, importRegion string, dataFormat, dataSourceType int, awsRoleArn, ObjectNamePattern, TargetTablePattern string) *ImportData {
	csv := &Csv{true, "\"", true, false, "\\N", ",", false}
	return &ImportData{sourceUrl, "root", "",
		dbPassword, dataSourceType, importRegion, dataFormat, awsRoleArn, csv, ObjectNamePattern, TargetTablePattern}
}

type Token struct {
	Auth0ClientSecret string `json:"auth0_client_secret"`
	Auth0ClientId     string `json:"auth0_client_id"`
	Auth0Domain       string `json:"auth0_domain"`
	Email             string `json:"email"`
}

func NewToken(auth0ClientSecret, auth0ClientId, auth0Domain, email string) *Token {
	return &Token{auth0ClientSecret, auth0ClientId, auth0Domain, email}
}

type NodeProfilesRequest struct {
	IsDevTier bool   `json:"is_dev_tier"`
	OrgId     string `json:"org_id"`
	Provider  string `json:"provider"`
	Region    string `json:"region"`
}

func NewNodeProfilesRequest(isDevTier bool, orgId, provider, region string) *NodeProfilesRequest {
	return &NodeProfilesRequest{isDevTier, orgId, provider, region}
}

type NodeProfilesResponse struct {
	NodeProfiles []NodeProfile `json:"node_profiles"`
	Resp         BaseResp      `json:"base_resp"`
}

type NodeProfile struct {
	ComponentType string    `json:"component_type"`
	Profiles      []profile `json:"profiles"`
}

type profile struct {
	Id               string `json:"id"`
	Name             string `json:"name"`
	DefaultNodeNum   int    `json:"default_node_num"`
	MinStorageSizeGi int    `json:"min_storage_size_gi"`
	MaxStorageSizeGi int    `json:"max_storage_size_gi"`
	DisplayName      string `json:"display_name"`
	CPU              int    `json:"cpu_num"`
	Memory           int    `json:"memory_gi"`
}

type BaseResp struct {
	ErrCode string `json:"err_code"`
	ErrMsg  string `json:"err_msg"`
}

type SetupIntent struct {
	PublicKey    string `json:"public_key"`
	ClientSecret string `json:"client_secret"`
}

// PaymentMethod is the response of payment method API
type StripePaymentMethod struct {
	ID             string          `json:"id"`
	Card           *Card           `json:"card"`
	BillingDetails *BillingDetails `json:"billing_details"`
}

// Card is the credit card
type Card struct {
	Brand       string `json:"brand"`
	Country     string `json:"country"`
	ExpMonth    uint64 `json:"exp_month,string"`
	ExpYear     uint64 `json:"exp_year,string"`
	Fingerprint string `json:"fingerprint"`
	Funding     string `json:"funding"`
	Last4       string `json:"last4"`
}

// BillingDetails is the user detail billing information
type BillingDetails struct {
	Address *Address `json:"address"`
	Email   *string  `json:"email"`
	Name    string   `json:"name"`
	Phone   *string  `json:"phone"`
}

// Address is the billing Address
type Address struct {
	City       string `json:"city"`
	Country    string `json:"country"`
	Line1      string `json:"line1"`
	Line2      string `json:"line2"`
	PostalCode string `json:"postal_code"`
	State      string `json:"state"`
}

type StripeCustomerInfo struct {
	ID            string   `json:"id"`
	TenantID      string   `json:"dbaas_id"`
	Email         string   `json:"email"`
	Name          string   `json:"name"`
	Description   string   `json:"description"`
	DefaultSource string   `json:"default_source"`
	Address       *Address `json:"address"`
}

type CostExplorerResult struct {
	BindedInvoiceCosts   Costs `json:"binded_invoice_costs"`
	UnbindedInvoiceCosts Costs `json:"unbind_invoice_costs"`
	CreditsCosts         Costs `json:"credits_costs"`
	InvoiceCosts         Costs `json:"invoice_costs"`
	TotalCosts           Costs `json:"total_costs"`
}

type Costs struct {
	CategoryCosts
	LabelsUnitsCosts map[string]LabelCosts `json:"label_unit_costs"`
}

type CategoryCosts struct {
	Price
	UnitsCosts         []UnitCosts      `json:"unit_costs,omitempty"`
	CategoryUnitsCosts map[string]Price `json:"category_unit_costs"`
}

type LabelCosts map[string]CategoryCosts

type Price struct {
	CostPrice string `json:"cost_price"`
	RawPrice  string `json:"raw_price"`
}

type UnitCosts struct {
	CostID        string            `json:"cost_id"`
	CostTimeStamp int64             `json:"cost_time_stamp"`
	Unit          string            `json:"unit"`
	Cost          int               `json:"cost"`
	Labels        map[string]string `json:"labels"`

	CostPrice       string `json:"price"`
	RawPrice        string `json:"raw_price"`
	PackageID       uint   `json:"package_id"`
	PackageVersion  uint   `json:"package_version"`
	BindedPackageID uint   `json:"binded_package_id"`
	ConsumedSource  string `json:"consumed_source"`
	InvoiceID       int    `json:"invoice_id"`
}

// audit log body struct
type AccessRecords struct {
	Org_id     string   `json:"org_id"`
	Project_id string   `json:"project_id"`
	Cluster_id string   `json:"cluster_id"`
	Record     *Records `json:"record"`
}
type Records struct {
	User_expr        string   `json:"user_expr"`
	Db_expr          string   `json:"db_expr"`
	Table_expr       string   `json:"table_expr"`
	Access_type_list []string `json:"access_type_list"`
}

func NewRecords(user_expr, db_expr, table_expr string, access_type_list []string) *Records {
	return &Records{user_expr, db_expr,
		table_expr, access_type_list}
}
func NewAccessRecords(org_id, project_id, cluster_id string, record *Records) *AccessRecords {
	return &AccessRecords{org_id, project_id,
		cluster_id, record}
}

type AuditLog struct {
	Org_id           string          `json:"org_id"`
	Project_id       string          `json:"project_id"`
	Cluster_id       string          `json:"cluster_id"`
	Enabled          bool            `json:"enabled"`
	Restart          bool            `json:"restart"`
	Audit_log_config *AuditLogConfig `json:"audit_log_config"`
}

type AuditLogConfig struct {
	Bucket_url       string `json:"bucket_url"`
	Role_arn         string `json:"role_arn"`
	Region           string `json:"region"`
	Data_source_type int    `json:"data_source_type"`
}

func NewAuditLog(org_id, project_id, cluster_id string, enabled, restart bool, audit_log_config *AuditLogConfig) *AuditLog {
	return &AuditLog{org_id, project_id, cluster_id,
		enabled, restart, audit_log_config}
}

func NewAuditLogConfig(bucket_url, role_arn, region string, data_source_type int) *AuditLogConfig {
	return &AuditLogConfig{bucket_url, role_arn, region,
		data_source_type}
}

type XAccountConfiguration struct {
	OrgId     string `json:"org_id"`
	ProjectId string `json:"project_id"`

	VpcId           string    `json:"vpc_id"`
	SecurityGroupId string    `json:"security_group_id"`
	SubnetIds       [3]string `json:"subnet_ids"`

	BucketName string `json:"bucket_name"`

	KmsKeyArn               string `json:"kms_key_arn"`
	PcaArnClusterComponents string `json:"pca_arn_cluster_components"`
	PcaArnClient            string `json:"pca_arn_client"`

	RoleArnEks       string `json:"role_arn_eks"`
	RoleArnNode      string `json:"role_arn_node"`
	RoleArnTidbCloud string `json:"role_arn_tidb_cloud"`

	Provider string `json:"provider"`
	Region   string `json:"region"`
}

func NewXAccountConfiguration(orgId, projectId, vpcId, securityGroupId, subnetId1, subnetId2, subnetId3, bucketName, kmsKeyArn, pcaArnClusterComponents, pcaArnClient, roleArnEks, roleArnNode, roleArnTidbCloud, provider, region string) *XAccountConfiguration {
	var subnetList [3]string = [3]string{subnetId1, subnetId2, subnetId3}
	return &XAccountConfiguration{orgId, projectId, vpcId, securityGroupId, subnetList, bucketName, kmsKeyArn, pcaArnClusterComponents, pcaArnClient, roleArnEks, roleArnNode, roleArnTidbCloud, provider, region}
}

// billing credits history
type CreditsHistory struct {
	Amount  string    `json:"amount"`
	History []Credits `json:"history"`
}

type Credits struct {
	Amount  string `json:"amount"`
	Created string `json:"created"`
}

type Invoice struct {
	Amount_due  string `json:"amount_due"`
	Amount_paid string `json:"amount_paid"`
	Created     string `json:"created"`
	Currency    string `json:"currency"`
	Due_date    string `json:"due_date"`
	Credit_used string `json:"credit_used"`
	Id          string `json:"id"`
	Number      string `json:"number"`
	Invoice_pdf string `json:"invoice_pdf"`
	Total       string `json:"total"`
	Paid        bool   `json:"paid"`
	Status      string `json:"status"`
}

type InvoiceList []Invoice

type PriceTable struct {
	Regions []RegionPrice `json:"regions"`
}

type RegionPrice struct {
	Name  string      `json:"name"`
	Tiers []TierPrice `json:"tiers"`
}

type TierPrice struct {
	Name string      `json:"name"`
	Rows []NodePrice `json:"rows"`
}

type NodePrice struct {
	Node    string `json:"node"`
	Storage string `json:"storage"`
	Hcpn    string `json:"hcpn"` // cpu price
	Mcpn    string `json:"mcpn"`
	Pphcpn  string `json:"pphcpn"`
	Ppmcpn  string `json:"ppmcpn"`
	Cpu     string `json:"cpu"`
	Sbph    string `json:"sbph"`
	Scgbh   string `json:"scgbh"` // memory price per GiB
}
