package load

import "time"

// timerange -> digest -> records
type TimeRangeRecords map[TimeRange]map[string][]*StmtRecord

func (trs TimeRangeRecords) AddRecord(record *StmtRecord) {
	tr := TimeRange{record.Begin, record.End}
	if _, ok := trs[tr]; !ok {
		trs[tr] = make(map[string][]*StmtRecord)
	}
	trs[tr][record.Digest] = append(trs[tr][record.Digest], record)
}

func (trs TimeRangeRecords) Traverse(fn func(record *StmtRecord)) {
	for _, dgRecords := range trs {
		for _, records := range dgRecords {
			for _, record := range records {
				fn(record)
			}
		}
	}
}

func (trs TimeRangeRecords) Clone() TimeRangeRecords {
	res := make(TimeRangeRecords, len(trs))
	for tr, dgRecords := range trs {
		res[tr] = make(map[string][]*StmtRecord, len(dgRecords))
		for digest, records := range dgRecords {
			res[tr][digest] = make([]*StmtRecord, len(records))
			copy(res[tr][digest], records)
		}
	}
	return res
}

type TimeRange struct {
	Begin int64
	End   int64
}

// Port from https://github.com/pingcap/tidb/blob/v7.5.6/pkg/util/stmtsummary/v2/record.go#L38
type StmtRecord struct {
	// Each record is summarized between [Begin, End).
	Begin int64 `json:"begin"`
	End   int64 `json:"end"`
	// Immutable
	SchemaName    string `json:"schema_name"`
	Digest        string `json:"digest"`
	PlanDigest    string `json:"plan_digest"`
	StmtType      string `json:"stmt_type"`
	NormalizedSQL string `json:"normalized_sql"`
	TableNames    string `json:"table_names"`
	IsInternal    bool   `json:"is_internal"`
	// Basic
	SampleSQL        string   `json:"sample_sql"`
	Charset          string   `json:"charset"`
	Collation        string   `json:"collation"`
	PrevSQL          string   `json:"prev_sql"`
	SamplePlan       string   `json:"sample_plan"`
	SampleBinaryPlan string   `json:"sample_binary_plan"`
	PlanHint         string   `json:"plan_hint"`
	IndexNames       []string `json:"index_names"`
	ExecCount        int64    `json:"exec_count"`
	SumErrors        int      `json:"sum_errors"`
	SumWarnings      int      `json:"sum_warnings"`
	// Latency
	SumLatency        time.Duration `json:"sum_latency"`
	MaxLatency        time.Duration `json:"max_latency"`
	MinLatency        time.Duration `json:"min_latency"`
	SumParseLatency   time.Duration `json:"sum_parse_latency"`
	MaxParseLatency   time.Duration `json:"max_parse_latency"`
	SumCompileLatency time.Duration `json:"sum_compile_latency"`
	MaxCompileLatency time.Duration `json:"max_compile_latency"`
	// Coprocessor
	SumNumCopTasks       int64         `json:"sum_num_cop_tasks"`
	MaxCopProcessTime    time.Duration `json:"max_cop_process_time"`
	MaxCopProcessAddress string        `json:"max_cop_process_address"`
	MaxCopWaitTime       time.Duration `json:"max_cop_wait_time"`
	MaxCopWaitAddress    string        `json:"max_cop_wait_address"`
	// TiKV
	SumProcessTime               time.Duration `json:"sum_process_time"`
	MaxProcessTime               time.Duration `json:"max_process_time"`
	SumWaitTime                  time.Duration `json:"sum_wait_time"`
	MaxWaitTime                  time.Duration `json:"max_wait_time"`
	SumBackoffTime               time.Duration `json:"sum_backoff_time"`
	MaxBackoffTime               time.Duration `json:"max_backoff_time"`
	SumTotalKeys                 int64         `json:"sum_total_keys"`
	MaxTotalKeys                 int64         `json:"max_total_keys"`
	SumProcessedKeys             int64         `json:"sum_processed_keys"`
	MaxProcessedKeys             int64         `json:"max_processed_keys"`
	SumRocksdbDeleteSkippedCount uint64        `json:"sum_rocksdb_delete_skipped_count"`
	MaxRocksdbDeleteSkippedCount uint64        `json:"max_rocksdb_delete_skipped_count"`
	SumRocksdbKeySkippedCount    uint64        `json:"sum_rocksdb_key_skipped_count"`
	MaxRocksdbKeySkippedCount    uint64        `json:"max_rocksdb_key_skipped_count"`
	SumRocksdbBlockCacheHitCount uint64        `json:"sum_rocksdb_block_cache_hit_count"`
	MaxRocksdbBlockCacheHitCount uint64        `json:"max_rocksdb_block_cache_hit_count"`
	SumRocksdbBlockReadCount     uint64        `json:"sum_rocksdb_block_read_count"`
	MaxRocksdbBlockReadCount     uint64        `json:"max_rocksdb_block_read_count"`
	SumRocksdbBlockReadByte      uint64        `json:"sum_rocksdb_block_read_byte"`
	MaxRocksdbBlockReadByte      uint64        `json:"max_rocksdb_block_read_byte"`
	// Txn
	CommitCount          int64               `json:"commit_count"`
	SumGetCommitTsTime   time.Duration       `json:"sum_get_commit_ts_time"`
	MaxGetCommitTsTime   time.Duration       `json:"max_get_commit_ts_time"`
	SumPrewriteTime      time.Duration       `json:"sum_prewrite_time"`
	MaxPrewriteTime      time.Duration       `json:"max_prewrite_time"`
	SumCommitTime        time.Duration       `json:"sum_commit_time"`
	MaxCommitTime        time.Duration       `json:"max_commit_time"`
	SumLocalLatchTime    time.Duration       `json:"sum_local_latch_time"`
	MaxLocalLatchTime    time.Duration       `json:"max_local_latch_time"`
	SumCommitBackoffTime int64               `json:"sum_commit_backoff_time"`
	MaxCommitBackoffTime int64               `json:"max_commit_backoff_time"`
	SumResolveLockTime   int64               `json:"sum_resolve_lock_time"`
	MaxResolveLockTime   int64               `json:"max_resolve_lock_time"`
	SumWriteKeys         int64               `json:"sum_write_keys"`
	MaxWriteKeys         int                 `json:"max_write_keys"`
	SumWriteSize         int64               `json:"sum_write_size"`
	MaxWriteSize         int                 `json:"max_write_size"`
	SumPrewriteRegionNum int64               `json:"sum_prewrite_region_num"`
	MaxPrewriteRegionNum int32               `json:"max_prewrite_region_num"`
	SumTxnRetry          int64               `json:"sum_txn_retry"`
	MaxTxnRetry          int                 `json:"max_txn_retry"`
	SumBackoffTimes      int64               `json:"sum_backoff_times"`
	BackoffTypes         map[string]int      `json:"backoff_types"`
	AuthUsers            map[string]struct{} `json:"auth_users"`
	// Other
	SumMem               int64         `json:"sum_mem"`
	MaxMem               int64         `json:"max_mem"`
	SumDisk              int64         `json:"sum_disk"`
	MaxDisk              int64         `json:"max_disk"`
	SumAffectedRows      uint64        `json:"sum_affected_rows"`
	SumKVTotal           time.Duration `json:"sum_kv_total"`
	SumPDTotal           time.Duration `json:"sum_pd_total"`
	SumBackoffTotal      time.Duration `json:"sum_backoff_total"`
	SumWriteSQLRespTotal time.Duration `json:"sum_write_sql_resp_total"`
	SumResultRows        int64         `json:"sum_result_rows"`
	MaxResultRows        int64         `json:"max_result_rows"`
	MinResultRows        int64         `json:"min_result_rows"`
	Prepared             bool          `json:"prepared"`
	// The first time this type of SQL executes.
	FirstSeen time.Time `json:"first_seen"`
	// The last time this type of SQL executes.
	LastSeen time.Time `json:"last_seen"`
	// Plan cache
	PlanInCache   bool  `json:"plan_in_cache"`
	PlanCacheHits int64 `json:"plan_cache_hits"`
	PlanInBinding bool  `json:"plan_in_binding"`
	// Pessimistic execution retry information.
	ExecRetryCount uint          `json:"exec_retry_count"`
	ExecRetryTime  time.Duration `json:"exec_retry_time"`
	// Request-units summary for each type of statements.
	SumRRU            float64       `json:"sum_rru"`
	SumWRU            float64       `json:"sum_wru"`
	SumRUWaitDuration time.Duration `json:"sum_ru_wait_duration"`
	MaxRRU            float64       `json:"max_rru"`
	MaxWRU            float64       `json:"max_wru"`
	MaxRUWaitDuration time.Duration `json:"max_ru_wait_duration"`

	// RUv2 metrics
	SumRuv2 float64 `json:"sum_ruv2"`
	MaxRuv2 float64 `json:"max_ruv2"`

	// IA remote read segment metrics
	SumIaReadSegmentCount          int64   `json:"sum_ia_read_segment_count"`
	SumIaRemoteReadSegmentSize     int64   `json:"sum_ia_remote_read_segment_size"`
	SumIaRemoteReadSegmentWaitTime float64 `json:"sum_ia_remote_read_segment_wait_time"`
	MaxIaReadSegmentCount          int64   `json:"max_ia_read_segment_count"`
	MaxIaRemoteReadSegmentSize     int64   `json:"max_ia_remote_read_segment_size"`
	MaxIaRemoteReadSegmentWaitTime float64 `json:"max_ia_remote_read_segment_wait_time"`

	// Computed fields
	RelatedSchemas map[string]struct{}
}
