package datascience

import (
	"testing"
)

func TestDiffEntities(t *testing.T) {
	t.Run("entity añadida", func(t *testing.T) {
		before := []map[string]any{
			{"id": "1", "name": "Alice"},
		}
		after := []map[string]any{
			{"id": "1", "name": "Alice"},
			{"id": "2", "name": "Bob"},
		}
		result := DiffEntities(before, after, "id", nil)
		added := result["added"].([]map[string]any)
		if len(added) != 1 {
			t.Errorf("expected 1 added, got %d", len(added))
		}
		if added[0]["id"] != "2" {
			t.Errorf("expected added id=2, got %v", added[0]["id"])
		}
		if result["unchanged"].(int) != 1 {
			t.Errorf("expected 1 unchanged, got %v", result["unchanged"])
		}
	})

	t.Run("entity eliminada", func(t *testing.T) {
		before := []map[string]any{
			{"id": "1", "name": "Alice"},
			{"id": "2", "name": "Bob"},
		}
		after := []map[string]any{
			{"id": "1", "name": "Alice"},
		}
		result := DiffEntities(before, after, "id", nil)
		removed := result["removed"].([]map[string]any)
		if len(removed) != 1 {
			t.Errorf("expected 1 removed, got %d", len(removed))
		}
		if removed[0]["id"] != "2" {
			t.Errorf("expected removed id=2, got %v", removed[0]["id"])
		}
	})

	t.Run("entity modificada con detalle de campos", func(t *testing.T) {
		before := []map[string]any{
			{"id": "1", "name": "Alice", "status": "active"},
		}
		after := []map[string]any{
			{"id": "1", "name": "Alice", "status": "inactive"},
		}
		result := DiffEntities(before, after, "id", nil)
		modified := result["modified"].([]map[string]any)
		if len(modified) != 1 {
			t.Errorf("expected 1 modified, got %d", len(modified))
		}
		changes := modified[0]["changes"].(map[string]any)
		statusChange, ok := changes["status"].(map[string]any)
		if !ok {
			t.Fatalf("expected status change, got %v", changes)
		}
		if statusChange["old"] != "active" {
			t.Errorf("expected old=active, got %v", statusChange["old"])
		}
		if statusChange["new"] != "inactive" {
			t.Errorf("expected new=inactive, got %v", statusChange["new"])
		}
	})

	t.Run("entities identicas → unchanged", func(t *testing.T) {
		entities := []map[string]any{
			{"id": "1", "name": "Alice"},
			{"id": "2", "name": "Bob"},
		}
		result := DiffEntities(entities, entities, "id", nil)
		if result["unchanged"].(int) != 2 {
			t.Errorf("expected 2 unchanged, got %v", result["unchanged"])
		}
		if len(result["added"].([]map[string]any)) != 0 {
			t.Errorf("expected 0 added")
		}
		if len(result["modified"].([]map[string]any)) != 0 {
			t.Errorf("expected 0 modified")
		}
	})

	t.Run("ignore_fields funciona", func(t *testing.T) {
		before := []map[string]any{
			{"id": "1", "name": "Alice", "updated_at": "2024-01-01"},
		}
		after := []map[string]any{
			{"id": "1", "name": "Alice", "updated_at": "2024-06-01"},
		}
		// Default ignores updated_at
		result := DiffEntities(before, after, "id", nil)
		if result["unchanged"].(int) != 1 {
			t.Errorf("expected 1 unchanged (updated_at ignored), got %v", result["unchanged"])
		}
		modified := result["modified"].([]map[string]any)
		if len(modified) != 0 {
			t.Errorf("expected 0 modified when updated_at is ignored, got %d", len(modified))
		}
	})

	t.Run("lista vacia vs lista con datos", func(t *testing.T) {
		before := []map[string]any{}
		after := []map[string]any{
			{"id": "1", "name": "Alice"},
		}
		result := DiffEntities(before, after, "id", nil)
		added := result["added"].([]map[string]any)
		if len(added) != 1 {
			t.Errorf("expected 1 added, got %d", len(added))
		}
		if result["unchanged"].(int) != 0 {
			t.Errorf("expected 0 unchanged")
		}
	})

	t.Run("summary format correcto", func(t *testing.T) {
		before := []map[string]any{
			{"id": "1", "name": "Alice"},
			{"id": "3", "name": "Carol"},
		}
		after := []map[string]any{
			{"id": "1", "name": "Alice Changed"},
			{"id": "2", "name": "Bob"},
		}
		result := DiffEntities(before, after, "id", nil)
		summary := result["summary"].(string)
		expected := "1 added, 1 removed, 1 modified, 0 unchanged"
		if summary != expected {
			t.Errorf("expected summary %q, got %q", expected, summary)
		}
	})
}
