package slowquery

import (
	"gorm.io/gorm/schema"
	"reflect"
)

// ColumnNames map json key to column names
var ColumnNames map[string]string

// SelectColumns map json key to select statements
var SelectColumns map[string]string

func init() {
	meta := reflect.TypeOf(Log{})
	ColumnNames = make(map[string]string, meta.NumField())
	SelectColumns = make(map[string]string, meta.NumField())
	for i := 0; i < meta.NumField(); i++ {
		jsonKey := meta.Field(i).Tag.Get("json")
		gormTags := schema.ParseTagSetting(meta.Field(i).Tag.Get("gorm"), ";")
		ColumnNames[jsonKey] = gormTags["COLUMN"]
		projValue := meta.Field(i).Tag.Get("proj")
		if len(projValue) > 0 {
			SelectColumns[jsonKey] = projValue
		} else {
			SelectColumns[jsonKey] = gormTags["COLUMN"]
		}
	}
}

// Log is completely copied from github.com/pingcap/tidb-dashboard/pkg/apiserver/slowquery/model.go
type Log struct {
	ID     uint64 `gorm:"column:id" json:"id"`
	Digest string `gorm:"column:Digest" json:"digest"`
	Query  string `gorm:"column:Query" json:"query"`

	Instance     string `gorm:"column:INSTANCE" json:"instance"`
	DB           string `gorm:"column:DB" json:"db"`
	ConnectionID string `gorm:"column:Conn_ID" json:"connection_id" proj:"CAST(Conn_ID AS CHAR) AS Conn_ID"`
	Success      bool   `gorm:"column:Succ" json:"success"`

	Timestamp             float64 `gorm:"column:timestamp" json:"timestamp" proj:"(UNIX_TIMESTAMP(Time) + 0E0) AS timestamp"`
	QueryTime             float64 `gorm:"column:Query_time" json:"query_time"`
	ParseTime             float64 `gorm:"column:Parse_time" json:"parse_time"`
	CompileTime           float64 `gorm:"column:Compile_time" json:"compile_time"`
	RewriteTime           float64 `gorm:"column:Rewrite_time" json:"rewrite_time"`
	PreprocSubqueriesTime float64 `gorm:"column:Preproc_subqueries_time" json:"preproc_subqueries_time"`
	OptimizeTime          float64 `gorm:"column:Optimize_time" json:"optimize_time"`
	WaitTSTime            float64 `gorm:"column:Wait_TS" json:"wait_ts"`
	CopTime               float64 `gorm:"column:Cop_time" json:"cop_time"`
	LockKeysTime          float64 `gorm:"column:LockKeys_time" json:"lock_keys_time"`
	WriteRespTime         float64 `gorm:"column:Write_sql_response_total" json:"write_sql_response_total"`
	ExecRetryTime         float64 `gorm:"column:Exec_retry_time" json:"exec_retry_time"`

	MemoryMax  float64 `gorm:"column:Mem_max" json:"memory_max"`
	DiskMax    float64 `gorm:"column:Disk_max" json:"disk_max"`
	TxnStartTS string  `gorm:"column:Txn_start_ts" json:"txn_start_ts" proj:"CAST(Txn_start_ts AS CHAR) AS Txn_start_ts"`

	// Detail
	PrevStmt string `gorm:"column:Prev_stmt" json:"prev_stmt"`
	Plan     string `gorm:"column:Plan" json:"plan" proj:"tidb_decode_plan(Plan) AS Plan"`

	// Basic
	IsInternal   bool   `gorm:"column:Is_internal" json:"is_internal"`
	IndexNames   string `gorm:"column:Index_names" json:"index_names"`
	Stats        string `gorm:"column:Stats" json:"stats"`
	BackoffTypes string `gorm:"column:Backoff_types" json:"backoff_types"`

	// Connections
	User string `gorm:"column:User" json:"user"`
	Host string `gorm:"column:Host" json:"host"`

	// Time duration
	ProcessTime            float64 `gorm:"column:Process_time" json:"process_time"`
	WaitTime               float64 `gorm:"column:Wait_time" json:"wait_time"`
	BackoffTime            float64 `gorm:"column:Backoff_time" json:"backoff_time"`
	GetCommitTSTime        float64 `gorm:"column:Get_commit_ts_time" json:"get_commit_ts_time"`
	LocalLatchWaitTime     float64 `gorm:"column:Local_latch_wait_time" json:"local_latch_wait_time"`
	ResolveLockTime        float64 `gorm:"column:Resolve_lock_time" json:"resolve_lock_time"`
	PrewriteTime           float64 `gorm:"column:Prewrite_time" json:"prewrite_time"`
	WaitPreWriteBinlogTime float64 `gorm:"column:Wait_prewrite_binlog_time" json:"wait_prewrite_binlog_time"`
	CommitTime             float64 `gorm:"column:Commit_time" json:"commit_time"`
	CommitBackoffTime      float64 `gorm:"column:Commit_backoff_time" json:"commit_backoff_time"`
	CopProcAvg             float64 `gorm:"column:Cop_proc_avg" json:"cop_proc_avg"`
	CopProcP90             float64 `gorm:"column:Cop_proc_p90" json:"cop_proc_p90"`
	CopProcMax             float64 `gorm:"column:Cop_proc_max" json:"cop_proc_max"`
	CopWaitAvg             float64 `gorm:"column:Cop_wait_avg" json:"cop_wait_avg"`
	CopWaitP90             float64 `gorm:"column:Cop_wait_p90" json:"cop_wait_p90"`
	CopWaitMax             float64 `gorm:"column:Cop_wait_max" json:"cop_wait_max"`

	// Transaction
	WriteKeys      float64 `gorm:"column:Write_keys" json:"write_keys"`
	WriteSize      float64 `gorm:"column:Write_size" json:"write_size"`
	PrewriteRegion float64 `gorm:"column:Prewrite_region" json:"prewrite_region"`
	TxnRetry       float64 `gorm:"column:Txn_retry" json:"txn_retry"`

	// Coprocessor
	RequestCount float64 `gorm:"column:Request_count" json:"request_count"`
	ProcessKeys  float64 `gorm:"column:Process_keys" json:"process_keys"`
	TotalKeys    float64 `gorm:"column:Total_keys" json:"total_keys"`
	CopProcAddr  string  `gorm:"column:Cop_proc_addr" json:"cop_proc_addr"`
	CopWaitAddr  string  `gorm:"column:Cop_wait_addr" json:"cop_wait_addr"`

	// RocksDB
	RocksdbDeleteSkippedCount float64 `gorm:"column:Rocksdb_delete_skipped_count" json:"rocksdb_delete_skipped_count"`
	RocksdbKeySkippedCount    float64 `gorm:"column:Rocksdb_key_skipped_count" json:"rocksdb_key_skipped_count"`
	RocksdbBlockCacheHitCount float64 `gorm:"column:Rocksdb_block_cache_hit_count" json:"rocksdb_block_cache_hit_count"`
	RocksdbBlockReadCount     float64 `gorm:"column:Rocksdb_block_read_count" json:"rocksdb_block_read_count"`
	RocksdbBlockReadByte      float64 `gorm:"column:Rocksdb_block_read_byte" json:"rocksdb_block_read_byte"`
}
