package core

import "testing"

func TestJoinByKey(t *testing.T) {
	t.Run("Inner join solo matches", func(t *testing.T) {
		left := []map[string]any{{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}}
		right := []map[string]any{{"id": 1, "dept": "eng"}, {"id": 3, "dept": "sales"}}
		result := JoinByKey(left, right, "id", "inner")
		if len(result) != 1 {
			t.Fatalf("got %d rows, want 1", len(result))
		}
		if result[0]["id"] != 1 || result[0]["name"] != "Alice" || result[0]["dept"] != "eng" {
			t.Errorf("unexpected row: %v", result[0])
		}
	})

	t.Run("Left join todos los left con nil para right sin match", func(t *testing.T) {
		left := []map[string]any{{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}}
		right := []map[string]any{{"id": 1, "dept": "eng"}}
		result := JoinByKey(left, right, "id", "left")
		if len(result) != 2 {
			t.Fatalf("got %d rows, want 2", len(result))
		}
		var alice, bob map[string]any
		for _, r := range result {
			if r["id"] == 1 {
				alice = r
			} else {
				bob = r
			}
		}
		if alice["dept"] != "eng" {
			t.Errorf("alice dept = %v, want eng", alice["dept"])
		}
		if bob["dept"] != nil {
			t.Errorf("bob dept = %v, want nil", bob["dept"])
		}
	})

	t.Run("Right join", func(t *testing.T) {
		left := []map[string]any{{"id": 1, "name": "Alice"}}
		right := []map[string]any{{"id": 1, "dept": "eng"}, {"id": 2, "dept": "sales"}}
		result := JoinByKey(left, right, "id", "right")
		if len(result) != 2 {
			t.Fatalf("got %d rows, want 2", len(result))
		}
		var eng, sales map[string]any
		for _, r := range result {
			if r["id"] == 1 {
				eng = r
			} else {
				sales = r
			}
		}
		if eng["name"] != "Alice" {
			t.Errorf("eng name = %v, want Alice", eng["name"])
		}
		if sales["name"] != nil {
			t.Errorf("sales name = %v, want nil", sales["name"])
		}
	})

	t.Run("Outer join", func(t *testing.T) {
		left := []map[string]any{{"id": 1, "name": "Alice"}, {"id": 2, "name": "Bob"}}
		right := []map[string]any{{"id": 1, "dept": "eng"}, {"id": 3, "dept": "sales"}}
		result := JoinByKey(left, right, "id", "outer")
		ids := map[any]bool{}
		for _, r := range result {
			ids[r["id"]] = true
		}
		if len(ids) != 3 || !ids[1] || !ids[2] || !ids[3] {
			t.Errorf("outer join ids = %v, want {1, 2, 3}", ids)
		}
	})

	t.Run("Campos duplicados con sufijo _right", func(t *testing.T) {
		left := []map[string]any{{"id": 1, "name": "Alice", "score": 90}}
		right := []map[string]any{{"id": 1, "score": 85, "dept": "eng"}}
		result := JoinByKey(left, right, "id", "inner")
		if len(result) != 1 {
			t.Fatalf("got %d rows, want 1", len(result))
		}
		if result[0]["score"] != 90 {
			t.Errorf("score = %v, want 90", result[0]["score"])
		}
		if result[0]["score_right"] != 85 {
			t.Errorf("score_right = %v, want 85", result[0]["score_right"])
		}
		if result[0]["dept"] != "eng" {
			t.Errorf("dept = %v, want eng", result[0]["dept"])
		}
	})

	t.Run("Key ausente en alguna fila", func(t *testing.T) {
		left := []map[string]any{{"id": 1, "name": "Alice"}, {"name": "Bob"}} // Bob sin id
		right := []map[string]any{{"id": 1, "dept": "eng"}}
		result := JoinByKey(left, right, "id", "inner")
		// Solo Alice matchea (Bob tiene key=nil, right no tiene nil)
		if len(result) != 1 {
			t.Fatalf("got %d rows, want 1", len(result))
		}
		if result[0]["name"] != "Alice" {
			t.Errorf("name = %v, want Alice", result[0]["name"])
		}
	})
}
