package diagnosis

import (
	"errors"
	"fmt"
)

// define proto
type InsertMetricsSampleParam struct {
	Timestamp   int64             `json:"timestamp"`
	Measurement string            `json:"measurement"`
	TiDBCluster string            `json:"tidb_cluster"`
	Fields      map[string]any    `json:"fields"`
	Tags        map[string]string `json:"tags"`
}

func (param *InsertMetricsSampleParam) Validate() error {
	if param.Timestamp == 0 {
		return errors.New("timestamp is empty")
	}
	if len(param.Measurement) == 0 {
		return errors.New("measurement is empty")
	}
	if len(param.TiDBCluster) == 0 {
		return errors.New("tidb_cluster is empty")
	}
	if len(param.Fields) == 0 {
		return errors.New("fields is empty")
	}
	return nil
}

func (param *InsertMetricsSampleParam) GetTags() map[string]string {
	return param.Tags
}

type InsertMetricsSampleData struct{}

type TsRange struct {
	StartTS int64 `json:"start_ts"`
	EndTS   int64 `json:"end_ts"`
}

// GetRollUpParam return timestamp in unix and the window size
func (tr *TsRange) GetRollUpParam() (int64, string) {
	return tr.EndTS, fmt.Sprintf("%vs", tr.EndTS-tr.StartTS)
}

type QueryAnnotationsParam struct {
	TsRange
	TiDBCluster string `json:"tidb_cluster"`
	Measurement string `json:"measurement"`
}

// GetRollUpParam return timestamp in unix and the window size
func (param *QueryAnnotationsParam) GetRollUpParam() (int64, string) {
	return param.TsRange.GetRollUpParam()
}

func (param *QueryAnnotationsParam) Validate() error {
	if param.StartTS == 0 {
		return errors.New("start_ts is empty")
	}
	if param.EndTS == 0 {
		return errors.New("end_ts is empty")
	}
	if param.StartTS > param.EndTS {
		return errors.New("end_ts is smaller than start_ts")
	}
	if len(param.TiDBCluster) == 0 {
		return errors.New("tidb_cluster is empty")
	}
	return nil
}

type Annotation struct {
	Name       string `json:"name"`
	Datasource string `json:"datasource"`
	IconColor  string `json:"iconColor"`
	Enable     bool   `json:"enable"`
	ShowLine   bool   `json:"showLine"`
	Query      string `json:"query"`
}

type QueryAnnotationItem struct {
	Annotation *Annotation `json:"annotation"`
	Time       int64       `json:"time"`
	TimeEnd    int64       `json:"timeEnd,omitempty"`
	Title      string      `json:"title"`
	Tags       string      `json:"tags"`
	Text       string      `json:"text"`
	PanelID    int64       `json:"panelId"`
}

func DefaultAnomalyAnnotation() *Annotation {
	return &Annotation{
		Name:       "Anomaly Point",
		Datasource: "Clinic",
		IconColor:  "rgba(255, 96, 96, 1)",
		Enable:     true,
		ShowLine:   true,
		Query:      "",
	}
}

type QueryAnnotationsData = []QueryAnnotationItem

type QueryNodeGraphParam struct {
	TsRange
	Measurement string `json:"measurement"`
	TiDBCluster string `json:"tidb_cluster"`
}

func (param *QueryNodeGraphParam) GetRollUpParam() (int64, string) {
	return param.TsRange.GetRollUpParam()
}

func (param *QueryNodeGraphParam) Validate() error {
	if param.StartTS == 0 {
		return errors.New("start_ts is empty")
	}
	if param.EndTS == 0 {
		return errors.New("end_ts is empty")
	}
	if len(param.TiDBCluster) == 0 {
		return errors.New("tidb_cluster is empty")
	}
	return nil
}

type Node struct {
	ID            string `json:"id"`
	Title         string `json:"title"`
	SubTitle      string `json:"subTitle"`
	MainStat      string `json:"mainStat"`
	SecondaryStat string `json:"secondaryStat"`
	// TODO(shenjun): rename following fields
	ArcPositive      float64 `json:"arc__similarity"`
	ArcNegative      float64 `json:"arc__nusimilarity"`
	ArcPositiveColor string  `json:"arc__similarity_color"`
	ArcNegativeColor string  `json:"arc__nusimilarity_color"`
}

func DefaultNode() *Node {
	return &Node{
		ArcPositiveColor: "red",
		ArcNegativeColor: "green",
	}
}

type Edge struct {
	ID            string `json:"id"`
	Source        string `json:"source"`
	Target        string `json:"target"`
	MainStat      string `json:"mainStat,omitempty"`
	SecondaryStat string `json:"secondaryStat,omitempty"`
}

func DefaultEdge() *Edge {
	return &Edge{}
}

type QueryNodeGraphData struct {
	Nodes []*Node `json:"nodes"`
	Edges []*Edge `json:"edges"`
}

type QueryDynamicTextValueParam struct {
	TsRange
	TiDBCluster string `json:"tidb_cluster"`
	Measurement string `json:"measurement"`
	Default1    string `json:"default_1"`
}

func (param *QueryDynamicTextValueParam) Validate() error {
	if param.StartTS == 0 {
		return errors.New("start_ts is empty")
	}
	if param.EndTS == 0 {
		return errors.New("end_ts is empty")
	}
	if len(param.TiDBCluster) == 0 {
		return errors.New("tidb_cluster is empty")
	}
	if len(param.Measurement) == 0 {
		return errors.New("measurement is empty")
	}
	return nil
}

type QueryDynamicTextValueData map[string]any
