package model

import "time"

type TiDBCluster struct {
	TestbedID         int64  `json:"-" dbstore:"testbedID"`
	TestbedName       string `json:"-" dbstore:"testbedName"`
	TestbedPlanExecID int64  `json:"-" dbstore:"testbedPlanExecID"`

	TiWorkloadClusterID string `json:"-" dbstore:"tiWorkloadClusterID"`
	TiWorkloadAgentID   string `json:"-" dbstore:"tiWorkloadAgentID"`

	TiDBCloudOrgID     string `json:"orgID,omitempty" dbstore:"orgID"`
	TiDBCloudProjectID string `json:"projectID,omitempty" dbstore:"projectID"`
	TiDBCloudClusterID string `json:"clusterID" dbstore:"clusterID"`

	MinRU int64 `json:"minRU,omitempty" dbstore:"minRU"`
	MaxRU int64 `json:"maxRU,omitempty" dbstore:"maxRU"`

	Host string `json:"-" dbstore:"host"`
	Port int    `json:"-" dbstore:"port"`

	// TODO: Add the CloudRegion to the TiDBCluster struct
	// CloudRegion string `json:"cloudRegion,omitempty" dbstore:"cloudRegion"`
	Type ClusterType `json:"type" dbstore:"type"`
}

func (t TiDBCluster) IsCreated() bool {
	return t.TiDBCloudClusterID != ""
}

func (t TiDBCluster) IsCreating() bool {
	return t.TiDBCloudClusterID == ""
}

func (t TiDBCluster) IsRegisting2TiWorkload() bool {
	return t.TiWorkloadAgentID != "" && t.TiWorkloadClusterID == ""
}

func (t TiDBCluster) IsRegisted2TiWorkload() bool {
	return t.TiWorkloadClusterID != ""
}

func (t TiDBCluster) ShouldRegister2TiWorkload() bool {
	return t.IsCreated() && t.TiWorkloadAgentID == ""
}

func (t TiDBCluster) HasConnection() bool {
	return t.Host != "" && t.Port != 0
}

type SampleDBOptions struct {
	DBLimit    int               `json:"db_limit,omitempty" query:"db_limit"`
	TableLimit int               `json:"table_limit,omitempty" query:"table_limit"`
	WithData   bool              `json:"with_data,omitempty" query:"with_data"`
	RowOptions SampleDataOptions `json:"row_options,omitempty" query:"row_options"`
}

type SampleDataOptions struct {
	DBName    string `json:"db_name,omitempty" query:"db_name"`
	TableName string `json:"table_name,omitempty" query:"table_name"`

	Limit int `json:"limit,omitempty" query:"limit"` // Max rows per table
	// SampleMethod SampleMethod `json:"sample_method,omitempty"` // Not supported now
	// Cutoff is the max lenght of the string
	Cutoff int `json:"cutoff,omitempty" query:"cutoff"`
}

type ColumnConstraint struct {
	ConstraintName     string `json:"constraint_name,omitempty"`
	ColumnName         string `json:"column_name,omitempty"`
	RefTableName       string `json:"ref_table_name,omitempty"`
	RefTableColumnName string `json:"ref_table_column_name,omitempty"`
}

type Column struct {
	Col      string `json:"col,omitempty"`
	DataType string `json:"data_type,omitempty"`
	MainType string `json:"main_type,omitempty"`
	TypeDesc string `json:"type_desc,omitempty"`

	Null    string `json:"null,omitempty"`
	Default string `json:"default,omitempty"`
	Extra   string `json:"extra,omitempty"`
	Key     string `json:"key,omitempty"`

	Constraints []ColumnConstraint `json:"constraints,omitempty"`
}

type Columns []Column

type Table struct {
	Name string `json:"name,omitempty"`
	Data

	Type            string `json:"type,omitempty"`
	CreateStatement string `json:"create_statement,omitempty"`
	ErrorMessage    string `json:"error_message,omitempty"`
}

type DataBase struct {
	Name   string  `json:"name,omitempty"`
	Tables []Table `json:"tables,omitempty"`

	ErrorMessage string `json:"error_message,omitempty"`
}

type Data struct {
	Columns Columns    `json:"columns,omitempty"`
	Rows    [][]string `json:"rows,omitempty"`
}

type TableQueryResult struct {
	Table
	// StartTime   time.Time
	// EndTime     time.Time
	// ExecuteTime float64
	RowCount int `json:"row_count,omitempty"`

	*SampleDataOptions `json:"options,omitempty"`
}

type DBSampleResult struct {
	Databases []DataBase `json:"databases,omitempty"`
	// StartTime   time.Time
	// EndTime     time.Time
	// ExecuteTime float64
	DBCount int   `json:"db_count,omitempty"`
	Version int64 `json:"version,omitempty"`

	*SampleDBOptions `json:"options,omitempty"`
}

// Since version = time.Now().UTC().Unix()
// we can get the version time
func (db *DBSampleResult) VersionTime() time.Time {
	return time.Unix(db.Version, 0).UTC()
}

func (db *DBSampleResult) IsOutdated() bool {
	// Check if the database version is older than 24 hours
	versionTime := db.VersionTime()
	return time.Since(versionTime) > 24*time.Hour
}
