// This file verifies decision-time TiDB tier reconstruction from historical application metrics.
package evaluation

import (
	"strings"
	"testing"
	"time"
)

func TestResolveTiDBTierAtUsesGOMAXPROCSAndMemoryQuota(t *testing.T) {
	at := time.Date(2026, 7, 1, 0, 15, 0, 0, time.UTC)
	metrics := testTiDBTierMetrics(at, map[string][2]float64{
		"tidb-0": {3, float64(13208 * 1024 * 1024)},
		"tidb-1": {3, float64(13208 * 1024 * 1024)},
	})

	observed, err := ResolveTiDBTierAt(metrics, at, 120*time.Second)
	if err != nil {
		t.Fatalf("ResolveTiDBTierAt(): %v", err)
	}
	if observed.NodeSpec != "4C16G" || observed.CPURequest.String() != "3" || observed.MemoryRequest.String() != "10350Mi" {
		t.Fatalf("observed tier = %+v, want 4C16G with 3 CPU and 10350Mi request", observed)
	}
}

func TestResolveTiDBTierAtRejectsMultipleActiveTiers(t *testing.T) {
	at := time.Date(2026, 7, 1, 0, 15, 0, 0, time.UTC)
	metrics := testTiDBTierMetrics(at, map[string][2]float64{
		"tidb-0": {3, float64(13208 * 1024 * 1024)},
		"tidb-1": {7, float64(13208 * 1024 * 1024)},
	})

	_, err := ResolveTiDBTierAt(metrics, at, 120*time.Second)
	if err == nil || !strings.Contains(err.Error(), "multiple TiDB tiers") {
		t.Fatalf("ResolveTiDBTierAt() error = %v, want multiple tiers", err)
	}
}

func TestResolveTiDBTierAtRejectsUnknownMemoryQuota(t *testing.T) {
	at := time.Date(2026, 7, 1, 0, 15, 0, 0, time.UTC)
	metrics := testTiDBTierMetrics(at, map[string][2]float64{
		"tidb-0": {3, float64(10000 * 1024 * 1024)},
	})

	_, err := ResolveTiDBTierAt(metrics, at, 120*time.Second)
	if err == nil || !strings.Contains(err.Error(), "do not map to a known historical TiDB tier") {
		t.Fatalf("ResolveTiDBTierAt() error = %v, want unknown quota", err)
	}
}

func TestResolveStableTiDBTierRejectsTierChange(t *testing.T) {
	start := time.Date(2026, 7, 1, 0, 0, 0, 0, time.UTC)
	end := start.Add(5 * time.Minute)
	metrics := []MetricSeries{
		{
			Name:   tiDBGOMAXPROCSMetric,
			Labels: map[string]string{"instance": "tidb-0"},
			Samples: []MetricSample{
				{Timestamp: start, Value: 3},
				{Timestamp: end, Value: 7},
			},
		},
		{
			Name:   tiDBMemoryQuotaMetric,
			Labels: map[string]string{"instance": "tidb-0"},
			Samples: []MetricSample{
				{Timestamp: start, Value: float64(13208 * 1024 * 1024)},
				{Timestamp: end, Value: float64(13208 * 1024 * 1024)},
			},
		},
	}

	_, err := ResolveStableTiDBTier(metrics, []time.Time{start, end}, 120*time.Second)
	if err == nil || !strings.Contains(err.Error(), "tier changes") {
		t.Fatalf("ResolveStableTiDBTier() error = %v, want tier change", err)
	}
}

func testTiDBTierMetrics(at time.Time, instances map[string][2]float64) []MetricSeries {
	metrics := make([]MetricSeries, 0, len(instances)*2)
	for instance, values := range instances {
		metrics = append(metrics,
			MetricSeries{
				Name:    tiDBGOMAXPROCSMetric,
				Labels:  map[string]string{"instance": instance},
				Samples: []MetricSample{{Timestamp: at, Value: values[0]}},
			},
			MetricSeries{
				Name:    tiDBMemoryQuotaMetric,
				Labels:  map[string]string{"instance": instance},
				Samples: []MetricSample{{Timestamp: at, Value: values[1]}},
			},
		)
	}
	return metrics
}
