package datascience

import (
	"testing"
)

func TestPivot(t *testing.T) {
	t.Run("Pivot basico con sum", func(t *testing.T) {
		rows := []map[string]any{
			{"region": "US", "product": "A", "sales": 10},
			{"region": "US", "product": "B", "sales": 20},
			{"region": "EU", "product": "A", "sales": 15},
		}
		result := Pivot(rows, "region", "product", "sales", "sum")
		if len(result) != 2 {
			t.Fatalf("got %d rows, want 2", len(result))
		}
		var us, eu map[string]any
		for _, r := range result {
			if r["region"] == "US" {
				us = r
			} else {
				eu = r
			}
		}
		if us["A"] != 10.0 {
			t.Errorf("US.A: got %v, want 10", us["A"])
		}
		if us["B"] != 20.0 {
			t.Errorf("US.B: got %v, want 20", us["B"])
		}
		if eu["A"] != 15.0 {
			t.Errorf("EU.A: got %v, want 15", eu["A"])
		}
		if eu["B"] != 0 {
			t.Errorf("EU.B: got %v, want 0", eu["B"])
		}
	})

	t.Run("Pivot con count y mean", func(t *testing.T) {
		rows := []map[string]any{
			{"region": "US", "product": "A", "sales": 10},
			{"region": "US", "product": "A", "sales": 20},
			{"region": "EU", "product": "A", "sales": 15},
		}
		resultCount := Pivot(rows, "region", "product", "sales", "count")
		for _, r := range resultCount {
			if r["region"] == "US" && r["A"] != 2 {
				t.Errorf("count US.A: got %v, want 2", r["A"])
			}
		}

		resultMean := Pivot(rows, "region", "product", "sales", "mean")
		for _, r := range resultMean {
			if r["region"] == "US" {
				mean, ok := r["A"].(float64)
				if !ok || mean != 15.0 {
					t.Errorf("mean US.A: got %v, want 15.0", r["A"])
				}
			}
		}
	})

	t.Run("Valores faltantes rellenados con 0", func(t *testing.T) {
		rows := []map[string]any{
			{"region": "US", "product": "A", "sales": 5},
			{"region": "EU", "product": "B", "sales": 8},
		}
		result := Pivot(rows, "region", "product", "sales", "sum")
		for _, r := range result {
			if r["region"] == "US" && r["B"] != 0 {
				t.Errorf("US.B: got %v, want 0", r["B"])
			}
			if r["region"] == "EU" && r["A"] != 0 {
				t.Errorf("EU.A: got %v, want 0", r["A"])
			}
		}
	})

	t.Run("Una sola fila", func(t *testing.T) {
		rows := []map[string]any{
			{"region": "US", "product": "A", "sales": 42},
		}
		result := Pivot(rows, "region", "product", "sales", "sum")
		if len(result) != 1 {
			t.Fatalf("got %d rows, want 1", len(result))
		}
		if result[0]["A"] != 42.0 {
			t.Errorf("got %v, want 42", result[0]["A"])
		}
	})

	t.Run("Multiples valores por celda requieren agregacion", func(t *testing.T) {
		rows := []map[string]any{
			{"region": "US", "product": "A", "sales": 10},
			{"region": "US", "product": "A", "sales": 30},
		}
		resultSum := Pivot(rows, "region", "product", "sales", "sum")
		if resultSum[0]["A"] != 40.0 {
			t.Errorf("sum: got %v, want 40.0", resultSum[0]["A"])
		}
		resultMin := Pivot(rows, "region", "product", "sales", "min")
		if resultMin[0]["A"] != 10.0 {
			t.Errorf("min: got %v, want 10.0", resultMin[0]["A"])
		}
		resultMax := Pivot(rows, "region", "product", "sales", "max")
		if resultMax[0]["A"] != 30.0 {
			t.Errorf("max: got %v, want 30.0", resultMax[0]["A"])
		}
	})
}
