package tests

import (
	"testing"
	"time"

	"github.com/jfraeys/fetch_ml/internal/metrics"
)

func TestMetrics_RecordTaskSuccess(t *testing.T) {
	m := &metrics.Metrics{}
	duration := 5 * time.Second

	m.RecordTaskSuccess(duration)

	if m.TasksProcessed.Load() != 1 {
		t.Errorf("Expected 1 task processed, got %d", m.TasksProcessed.Load())
	}

	if m.TasksFailed.Load() != 0 {
		t.Errorf("Expected 0 tasks failed, got %d", m.TasksFailed.Load())
	}
}

func TestMetrics_RecordTaskFailure(t *testing.T) {
	m := &metrics.Metrics{}

	m.RecordTaskFailure()

	if m.TasksProcessed.Load() != 0 {
		t.Errorf("Expected 0 tasks processed, got %d", m.TasksProcessed.Load())
	}

	if m.TasksFailed.Load() != 1 {
		t.Errorf("Expected 1 task failed, got %d", m.TasksFailed.Load())
	}
}

func TestMetrics_RecordTaskStart(t *testing.T) {
	m := &metrics.Metrics{}

	m.RecordTaskStart()

	if m.ActiveTasks.Load() != 1 {
		t.Errorf("Expected 1 active task, got %d", m.ActiveTasks.Load())
	}
}

func TestMetrics_RecordDataTransfer(t *testing.T) {
	m := &metrics.Metrics{}
	bytes := int64(1024 * 1024 * 1024) // 1GB
	duration := 10 * time.Second

	m.RecordDataTransfer(bytes, duration)

	if m.DataTransferred.Load() != bytes {
		t.Errorf("Expected %d bytes transferred, got %d", bytes, m.DataTransferred.Load())
	}

	if m.DataFetchTime.Load() != duration.Nanoseconds() {
		t.Errorf("Expected %d nanoseconds fetch time, got %d",
			duration.Nanoseconds(), m.DataFetchTime.Load())
	}
}

func TestMetrics_SetQueuedTasks(t *testing.T) {
	m := &metrics.Metrics{}

	m.SetQueuedTasks(5)

	if m.QueuedTasks.Load() != 5 {
		t.Errorf("Expected 5 queued tasks, got %d", m.QueuedTasks.Load())
	}
}

func TestMetrics_GetStats(t *testing.T) {
	m := &metrics.Metrics{}

	// Record some data
	m.RecordTaskStart()
	m.RecordTaskSuccess(5 * time.Second)
	m.RecordTaskFailure()
	m.RecordDataTransfer(1024*1024*1024, 10*time.Second)
	m.SetQueuedTasks(3)
	m.RecordPrewarmEnvHit()
	m.RecordPrewarmEnvMiss()
	m.RecordPrewarmEnvBuilt(2 * time.Second)

	stats := m.GetStats()

	// Check all expected fields exist
	expectedFields := []string{
		"tasks_processed", "tasks_failed", "active_tasks",
		"queued_tasks", "success_rate", "avg_exec_time",
		"data_transferred_gb", "avg_fetch_time",
		"prewarm_env_hit", "prewarm_env_miss", "prewarm_env_built", "prewarm_env_time",
	}

	for _, field := range expectedFields {
		if _, exists := stats[field]; !exists {
			t.Errorf("Expected field %s in stats", field)
		}
	}

	// Check values
	if stats["tasks_processed"] != int64(1) {
		t.Errorf("Expected 1 task processed, got %v", stats["tasks_processed"])
	}

	if stats["tasks_failed"] != int64(1) {
		t.Errorf("Expected 1 task failed, got %v", stats["tasks_failed"])
	}

	if stats["active_tasks"] != int64(1) {
		t.Errorf("Expected 1 active task, got %v", stats["active_tasks"])
	}

	if stats["queued_tasks"] != int64(3) {
		t.Errorf("Expected 3 queued tasks, got %v", stats["queued_tasks"])
	}

	successRate := stats["success_rate"].(float64)
	if successRate != 0.0 { // (1 success - 1 failure) / 1 processed = 0.0
		t.Errorf("Expected success rate 0.0, got %f", successRate)
	}
	if stats["prewarm_env_hit"] != int64(1) {
		t.Errorf("Expected 1 prewarm env hit, got %v", stats["prewarm_env_hit"])
	}
	if stats["prewarm_env_miss"] != int64(1) {
		t.Errorf("Expected 1 prewarm env miss, got %v", stats["prewarm_env_miss"])
	}
	if stats["prewarm_env_built"] != int64(1) {
		t.Errorf("Expected 1 prewarm env built, got %v", stats["prewarm_env_built"])
	}
}

func TestMetrics_GetStatsEmpty(t *testing.T) {
	m := &metrics.Metrics{}
	stats := m.GetStats()

	// Should not panic and should return zero values
	if stats["tasks_processed"] != int64(0) {
		t.Errorf("Expected 0 tasks processed, got %v", stats["tasks_processed"])
	}

	if stats["success_rate"] != 0.0 {
		t.Errorf("Expected success rate 0.0, got %v", stats["success_rate"])
	}
}
