package main

import (
	"fmt"
	"strings"

	"github.com/tidwall/gjson"
)

type InsertionRule struct {
	PanelTitle string
	NewContent string
}

var insertionRules = []InsertionRule{
	{
		PanelTitle: `Duration`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.999, tidb_server_handle_query_duration_seconds_bucket:le:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "999-ByRecordingRules",
              "refId": ""
            },
            {
              "expr": "histogram_quantile(0.99, tidb_server_handle_query_duration_seconds_bucket:le:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "99-ByRecordingRules",
              "refId": ""
            },
            {
              "expr": "histogram_quantile(0.95, tidb_server_handle_query_duration_seconds_bucket:le:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "95-ByRecordingRules",
              "refId": ""
            },
            {
              "expr": "histogram_quantile(0.80, tidb_server_handle_query_duration_seconds_bucket:le:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "80-ByRecordingRules",
              "refId": ""
            }`,
	},
	{
		PanelTitle: `999 Duration`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.999, tidb_server_handle_query_duration_seconds_bucket:le_sqltype:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{sql_type}}-ByRecordingRules",
              "refId": ""
            }`,
	},
	{
		PanelTitle: `99 Duration`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.99, tidb_server_handle_query_duration_seconds_bucket:le_sqltype:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{sql_type}}-ByRecordingRules",
              "refId": ""
            }`,
	},
	{
		PanelTitle: `95 Duration`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.95, tidb_server_handle_query_duration_seconds_bucket:le_sqltype:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{sql_type}}-ByRecordingRules",
              "refId": ""
            }`,
	},
	{
		PanelTitle: `80 Duration`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.80, tidb_server_handle_query_duration_seconds_bucket:le_sqltype:sum:rate)",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{sql_type}}-ByRecordingRules",
              "refId": ""
            }`,
	},
	{
		PanelTitle: `Duration 80 By Instance`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.80, tidb_server_handle_query_duration_seconds_bucket:le_instance:sum:rate{instance=~\"$instance\"})",
              "format": "time_series",
              "hide": false,
              "intervalFactor": 2,
              "legendFormat": "{{instance}}-ByRecordingRules",
              "refId": "",
              "step": 60
            }`,
	},
	{
		PanelTitle: `Duration 95 By Instance`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.95, tidb_server_handle_query_duration_seconds_bucket:le_instance:sum:rate{instance=~\"$instance\"})",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{ instance }}-ByRecordingRules",
              "refId": "",
              "step": 60
            }`,
	},
	{
		PanelTitle: `Duration 99 By Instance`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.99, tidb_server_handle_query_duration_seconds_bucket:le_instance:sum:rate{instance=~\"$instance\"})",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{instance}}-ByRecordingRules",
              "refId": "",
              "step": 60
            }`,
	},
	{
		PanelTitle: `Duration 999 By Instance`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.999, tidb_server_handle_query_duration_seconds_bucket:le_instance:sum:rate{instance=~\"$instance\"})",
              "format": "time_series",
              "intervalFactor": 2,
              "legendFormat": "{{instance}}-ByRecordingRules",
              "refId": "",
              "step": 60
            }`,
	},
	{
		PanelTitle: `99% gRPC message duration`,
		NewContent: `,
            {
              "expr": "histogram_quantile(0.99, tikv_grpc_msg_duration_seconds_bucket:le_type:sum:rate{type!=\"kv_gc\"})",
              "format": "time_series",
              "interval": "",
              "intervalFactor": 2,
              "legendFormat": "{{type}}-ByRecordingRules",
              "refId": "",
              "step": 10
            }`,
	},
	{ // v9.0.0
		PanelTitle: `gRPC message duration$optional_quantile`,
		NewContent: `,
            {
              "expr": "histogram_quantile($optional_quantile, tikv_grpc_msg_duration_seconds_bucket:le_type:sum:rate{type!=\"kv_gc\"})",
              "format": "time_series",
              "interval": "",
              "intervalFactor": 2,
              "legendFormat": "{{type}}-$optional_quantile-ByRecordingRules",
              "refId": "",
              "step": 10
            }`,
	},
}

func InsertNewExpr(s, substr, insert string) string {
	index := strings.Index(s, substr)
	if index == -1 {
		return s
	}
	end := index + len(substr)
	return s[:end] + insert + s[end:]
}

func AddPanelExprUseRecordingRule(path, rawBoard string) string {
	if !strings.Contains(path, "tidb.json") && !strings.Contains(path, "overview.json") &&
		!strings.Contains(path, "tikv_details.json") && !strings.Contains(path, "tikv_summary.json") {
		return rawBoard
	}

	m := make(map[string]InsertionRule)
	for _, rule := range insertionRules {
		m[rule.PanelTitle] = rule
	}

	panels := gjson.Get(rawBoard, "panels")
	panels.ForEach(func(_, value gjson.Result) bool {
		if gjson.Get(value.Raw, "panels").Exists() {
			subPanels := gjson.Get(value.Raw, "panels")
			subPanels.ForEach(func(_, subValue gjson.Result) bool {
				title := gjson.Get(subValue.Raw, "title")
				if v, exists := m[title.Str]; exists {
					raw := gjson.Get(subValue.Raw, fmt.Sprintf("targets.%d", gjson.Get(subValue.Raw, "targets.#").Int()-1)).Raw
					if title.Str == "Duration" && !strings.Contains(raw, "tidb_server_handle_query_duration_seconds_bucket") {
						return true
					}
					rawBoard = InsertNewExpr(rawBoard, raw, v.NewContent)
				}
				return true
			})
		}
		return true
	})
	return rawBoard
}
