package diskcheck

import (
	"fmt"
	"os"
	"strings"
)

// isMockEnabled checks if mock mode is enabled
func isMockEnabled() bool {
	return os.Getenv("DISKCHECK_MOCK") == "1"
}

// mockQueryResult returns carefully crafted mock data
// Scenarios:
// 1. TiDB Issue + Impacted:    high disk latency + EBS exceeded + high TiDB ratio
// 2. TiDB Issue + Non-Impacted: high disk latency + EBS exceeded + low TiDB ratio
// 3. Jitter Event + Impacted:   high disk latency + EBS not exceeded + high TiDB ratio
// 4. Jitter Event + Non-Impacted: high disk latency + EBS not exceeded + low TiDB ratio
func mockQueryResult(query, promURL string, start, end int64) (*QueryResult, error) {
	queryLower := strings.ToLower(query)

	// Base timestamp (fixed value for reproducible results)
	baseTime := int64(1774540800) // 2026-03-27 00:00:00

	result := &QueryResult{
		Status: "success",
	}

	// Disk latency query - construct high latency data
	if strings.Contains(queryLower, "node_disk_read_time") ||
		strings.Contains(queryLower, "node_disk_write_time") {
		result.Data.Result = generateDiskLatencyResult(baseTime)
		return result, nil
	}

	// EBS throughput exceeded - exceeded in first half, not in second half
	if strings.Contains(queryLower, "exceeded_tp") {
		result.Data.Result = generateEBSResult(baseTime, "throughput", start, end)
		return result, nil
	}

	// EBS IOPS exceeded
	if strings.Contains(queryLower, "exceeded_iops") {
		result.Data.Result = generateEBSResult(baseTime, "iops", start, end)
		return result, nil
	}

	// kube_pod_info - map pod to node
	if strings.Contains(queryLower, "kube_pod_info") {
		result.Data.Result = generateKubePodInfoResult(baseTime)
		return result, nil
	}

	// TiDB latency - construct fluctuations
	if strings.Contains(queryLower, "tidb_server_handle_query_duration") {
		result.Data.Result = generateTiDBDurationResult(baseTime)
		return result, nil
	}

	// TiFlash latency
	if strings.Contains(queryLower, "tiflash_coprocessor_request_duration") &&
		strings.Contains(queryLower, "run_mpp_task") {
		result.Data.Result = generateTiFlashDurationResult(baseTime)
		return result, nil
	}

	// TiFlash Raft metrics
	if strings.Contains(queryLower, "tiflash_raft_wait_index") {
		result.Data.Result = generateConstantResult(baseTime, 0.001)
		return result, nil
	}
	if strings.Contains(queryLower, "tiflash_raft_batch_read_index") {
		result.Data.Result = generateConstantResult(baseTime, 0.002)
		return result, nil
	}

	// Other queries return empty
	result.Data.Result = []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}{}
	return result, nil
}

// generateDiskLatencyResult generates disk latency data
// Carefully crafted timeline to ensure 4 different event types are generated:
// Insert normal intervals between sub-phases to prevent 2-minute aggregation window from merging them
//
// Timeline design:
// 0-4:   TiDB Issue + Impacted    (high latency + EBS exceeded + ratio=3.0)
// 4-8:   Normal interval (4 points=2 minutes, ensure separation from next window)
// 8-12:  TiDB Issue + Non-Impacted (high latency + EBS exceeded + ratio=1.2)
// 12-25: Normal interval (13 points=6.5 minutes, ensure EBS queries don't overlap)
// 35-39: Jitter + Impacted         (high latency + EBS not exceeded + ratio=2.5)
// 39-43: Normal interval (4 points=2 minutes)
// 43-47: Jitter + Non-Impacted     (high latency + EBS not exceeded + ratio=1.1)
// 47-60: Normal
//
// EBS query window analysis:
// - TiDB Issue query: [start-10min, end+10min] ≈ [-10, 22] (covers 0-12)
// - Jitter query: [25, 57] (covers 35-47)
// The two query windows don't overlap, ensuring Jitter won't read TiDB Issue's EBS data
func generateDiskLatencyResult(baseTime int64) []struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
} {
	var result []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}

	instances := []struct {
		name      string
		component string
		diskType  string
	}{
		{"db-tikv-0", "tikv", "io2"},
		{"db-tikv-1", "tikv", "io2"},
		{"db-tiflash-0", "tiflash", "gp3"},
		{"gcp-tikv-0", "tikv", "pd_ssd"},
		{"gcp-tikv-1", "tikv", "pd_balanced"},
		{"gcp-tiflash-0", "tiflash", "pd_extreme"},
		{"gcp-tikv-2", "tikv", "pd_standard"},
	}

	for _, inst := range instances {
		var values [][]interface{}

		for i := 0; i < 60; i++ {
			timestamp := float64(baseTime + int64(i*30))

			var value float64
			switch {
			// TiDB Issue + Impacted (0-4)
			case i >= 0 && i < 4:
				value = 0.015 + float64(i)*0.001 // 15-18ms
			// Normal interval (4-8), 2 minutes to ensure aggregation window separation
			case i >= 4 && i < 8:
				value = 0.003 // 3ms, below threshold
			// TiDB Issue + Non-Impacted (8-12)
			case i >= 8 && i < 12:
				value = 0.015 + float64(i-8)*0.001 // 15-18ms
			// Normal interval (12-25), 6.5 minutes to ensure EBS queries don't overlap
			case i >= 12 && i < 25:
				value = 0.003 // 3ms
			// Normal (waiting for EBS query window to pass) (25-35)
			case i >= 25 && i < 35:
				value = 0.003 // 3ms
			// Jitter + Impacted (35-39)
			case i >= 35 && i < 39:
				value = 0.015 + float64(i-35)*0.001 // 15-18ms
			// Normal interval (39-43), 2 minutes to ensure aggregation window separation
			case i >= 39 && i < 43:
				value = 0.003 // 3ms
			// Jitter + Non-Impacted (43-47)
			case i >= 43 && i < 47:
				value = 0.015 + float64(i-43)*0.001 // 15-18ms
			// Normal (47-60)
			default:
				value = 0.003 // 3ms
			}

			values = append(values, []interface{}{
				timestamp,
				fmt.Sprintf("%.6f", value),
			})
		}

		result = append(result, struct {
			Metric map[string]string `json:"metric"`
			Values [][]interface{}   `json:"values"`
		}{
			Metric: map[string]string{
				"instance":  inst.name,
				"component": inst.component,
				"device":    "nvme1n1",
				"disk_type": inst.diskType,
			},
			Values: values,
		})
	}

	return result
}

// generateEBSResult generates EBS exceeded data
// Returns data based on query time range, ensuring Jitter phase queries return 0
// TiDB Issue phase: 0-12 points (includes 0-4 Impacted and 8-12 Non-Impacted, with 4-8 as normal interval)
// Jitter phase: 35-47 points (includes 35-39 Impacted and 43-47 Non-Impacted, with 39-43 as normal interval)
func generateEBSResult(baseTime int64, ebsType string, queryStart, queryEnd int64) []struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
} {
	var values [][]interface{}

	// Calculate data point indices corresponding to query range
	startIdx := int((queryStart - baseTime) / 30)
	endIdx := int((queryEnd - baseTime) / 30)

	// Check if query range overlaps with TiDB Issue phase (0-12)
	tidbIssueStart := 0
	tidbIssueEnd := 12

	// If query range overlaps with TiDB Issue phase, return exceeded data
	// Otherwise return 0
	inTiDBIssue := (startIdx < tidbIssueEnd && endIdx > tidbIssueStart)

	for i := startIdx; i <= endIdx && i < 60; i++ {
		timestamp := float64(baseTime + int64(i*30))
		var value float64

		if inTiDBIssue && i >= tidbIssueStart && i < tidbIssueEnd {
			// TiDB Issue phase: exceeded
			if ebsType == "throughput" {
				value = 0.5 + float64(i)*0.02
			} else {
				value = 0.3 + float64(i)*0.01
			}
		} else {
			// Other phases (including Jitter): not exceeded
			value = 0
		}

		values = append(values, []interface{}{
			timestamp,
			fmt.Sprintf("%.6f", value),
		})
	}

	return []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}{
		{
			Metric: map[string]string{
				"instance": "ip-10-0-1-100.ec2.internal",
			},
			Values: values,
		},
	}
}

// generateKubePodInfoResult generates pod to node mapping
func generateKubePodInfoResult(baseTime int64) []struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
} {
	pods := []struct {
		pod  string
		node string
	}{
		{"db-tikv-0", "ip-10-0-1-100.ec2.internal"},
		{"db-tikv-1", "ip-10-0-1-101.ec2.internal"},
		{"db-tiflash-0", "ip-10-0-1-102.ec2.internal"},
	}

	var result []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}

	for _, p := range pods {
		var values [][]interface{}
		for i := 0; i < 40; i++ {
			timestamp := float64(baseTime + int64(i*30))
			values = append(values, []interface{}{timestamp, "1"})
		}

		result = append(result, struct {
			Metric map[string]string `json:"metric"`
			Values [][]interface{}   `json:"values"`
		}{
			Metric: map[string]string{
				"pod":  p.pod,
				"node": p.node,
			},
			Values: values,
		})
	}

	return result
}

// generateTiDBDurationResult generates TiDB latency data
// Produces different event types aligned with Disk Latency data:
// 0-4:   TiDB Issue + Impacted    (ratio=3.0)
// 4-8:   Normal interval (2 minutes)
// 8-12:  TiDB Issue + Non-Impacted (ratio=1.2)
// 12-35: Interval (normal)
// 35-39: Jitter + Impacted         (ratio=2.5)
// 39-43: Normal interval (2 minutes)
// 43-47: Jitter + Non-Impacted     (ratio=1.1)
// 47-60: Normal
func generateTiDBDurationResult(baseTime int64) []struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
} {
	var values [][]interface{}

	baseline := 0.05 // 50ms baseline

	for i := 0; i < 60; i++ {
		timestamp := float64(baseTime + int64(i*30))
		var value float64

		switch {
		// TiDB Issue + Impacted
		case i >= 0 && i < 4:
			value = baseline * 3.0 // ratio=3.0
		// Normal interval (2 minutes)
		case i >= 4 && i < 8:
			value = baseline
		// TiDB Issue + Non-Impacted
		case i >= 8 && i < 12:
			value = baseline * 1.2 // ratio=1.2
		// Interval - normal
		case i >= 12 && i < 35:
			value = baseline
		// Jitter + Impacted
		case i >= 35 && i < 39:
			value = baseline * 2.5 // ratio=2.5
		// Normal interval (2 minutes)
		case i >= 39 && i < 43:
			value = baseline
		// Jitter + Non-Impacted
		case i >= 43 && i < 47:
			value = baseline * 1.1 // ratio=1.1
		// Return to normal
		default:
			value = baseline
		}

		values = append(values, []interface{}{
			timestamp,
			fmt.Sprintf("%.6f", value),
		})
	}

	return []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}{
		{
			Metric: map[string]string{},
			Values: values,
		},
	}
}

// generateTiFlashDurationResult generates TiFlash latency data
// Timeline is consistent with TiDB
func generateTiFlashDurationResult(baseTime int64) []struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
} {
	var values [][]interface{}
	baseline := 0.1 // 100ms

	for i := 0; i < 60; i++ {
		timestamp := float64(baseTime + int64(i*30))
		var value float64

		switch {
		// TiDB Issue + Impacted
		case i >= 0 && i < 4:
			value = baseline * 3.0 // ratio=3.0
		// Normal interval (2 minutes)
		case i >= 4 && i < 8:
			value = baseline
		// TiDB Issue + Non-Impacted
		case i >= 8 && i < 12:
			value = baseline * 1.2 // ratio=1.2
		// Interval
		case i >= 12 && i < 35:
			value = baseline
		// Jitter + Impacted
		case i >= 35 && i < 39:
			value = baseline * 2.5 // ratio=2.5
		// Normal interval (2 minutes)
		case i >= 39 && i < 43:
			value = baseline
		// Jitter + Non-Impacted
		case i >= 43 && i < 47:
			value = baseline * 1.1 // ratio=1.1
		// Return to normal
		default:
			value = baseline
		}

		values = append(values, []interface{}{
			timestamp,
			fmt.Sprintf("%.6f", value),
		})
	}

	return []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}{
		{
			Metric: map[string]string{},
			Values: values,
		},
	}
}

// generateConstantResult generates constant value result
func generateConstantResult(baseTime int64, value float64) []struct {
	Metric map[string]string `json:"metric"`
	Values [][]interface{}   `json:"values"`
} {
	var values [][]interface{}

	for i := 0; i < 60; i++ {
		timestamp := float64(baseTime + int64(i*30))
		values = append(values, []interface{}{
			timestamp,
			fmt.Sprintf("%.6f", value),
		})
	}

	return []struct {
		Metric map[string]string `json:"metric"`
		Values [][]interface{}   `json:"values"`
	}{
		{
			Metric: map[string]string{},
			Values: values,
		},
	}
}
