package game

import (
	"strings"
	"testing"

	"github.com/google/uuid"

	"scrabble/backend/internal/engine"
)

func TestWriteGCG(t *testing.T) {
	g := Game{
		ID:          uuid.MustParse("00000000-0000-7000-8000-000000000001"),
		Variant:     engine.VariantEnglish,
		DictVersion: "v1",
		Players:     2,
	}
	moves := []HistoryMove{
		{
			Seq: 0, Seat: 0, Action: "play", Score: 10, RunningTotal: 10,
			Dir: "H", MainRow: 7, MainCol: 7,
			Tiles: []engine.TileRecord{{Row: 7, Col: 7, Letter: "c"}, {Row: 7, Col: 8, Letter: "a"}, {Row: 7, Col: 9, Letter: "t"}},
			Words: []string{"cat"}, Rack: []string{"c", "a", "t", "s", "e", "r", "?"},
		},
		{
			Seq: 1, Seat: 1, Action: "play", Score: 2, RunningTotal: 2,
			Dir: "V", MainRow: 7, MainCol: 8,
			Tiles: []engine.TileRecord{{Row: 8, Col: 8, Letter: "s", Blank: true}},
			Words: []string{"as"}, Rack: []string{"a", "s", "?", "e"},
		},
		{Seq: 2, Seat: 0, Action: "pass", RunningTotal: 10, Rack: []string{"x", "y", "z"}},
		{Seq: 3, Seat: 1, Action: "exchange", RunningTotal: 2, Exchanged: []string{"q", "u"}, Rack: []string{"q", "u", "i"}},
		{Seq: 4, Seat: 0, Action: "resign", RunningTotal: 10, Rack: []string{"a", "b"}},
		{Seq: 5, Seat: 1, Action: "timeout", RunningTotal: 2, Rack: []string{"c"}},
	}

	out := writeGCG(g, []string{"Alice", "Bob"}, moves)
	wantLines := []string{
		"#character-encoding UTF-8",
		"#player1 p1 Alice",
		"#player2 p2 Bob",
		"#lexicon scrabble_en/v1",
		"#title game 00000000-0000-7000-8000-000000000001",
		">p1: CATSER? 8H CAT +10 10",
		">p2: AS?E I8 .s +2 2",
		">p1: XYZ - +0 10",
		">p2: QUI -QU +0 2",
		"#note p1 resigned (rack AB)",
		"#note p2 timed out (rack C)",
	}
	lines := strings.Split(strings.TrimRight(out, "\n"), "\n")
	got := make(map[string]bool, len(lines))
	for _, l := range lines {
		got[l] = true
	}
	for _, want := range wantLines {
		if !got[want] {
			t.Errorf("GCG missing line %q\n--- full output ---\n%s", want, out)
		}
	}
}

func TestWriteGCGAbortedNote(t *testing.T) {
	g := Game{
		ID:          uuid.MustParse("00000000-0000-7000-8000-000000000002"),
		Variant:     engine.VariantErudit,
		DictVersion: "v1",
		Players:     2,
		Status:      StatusFinished,
		EndReason:   "aborted",
	}
	out := writeGCG(g, []string{"Alice", "Bob"}, nil)
	if !strings.Contains(out, "#note [organizer]") {
		t.Errorf("aborted game GCG missing the organizer note:\n%s", out)
	}
}

func TestGCGTilesUppercasesCyrillic(t *testing.T) {
	if got := gcgTiles([]string{"к", "о", "т", "?"}); got != "КОТ?" {
		t.Errorf("gcgTiles = %q, want КОТ?", got)
	}
}

func TestGCGPos(t *testing.T) {
	across := gcgPos(HistoryMove{Dir: "H", MainRow: 7, MainCol: 6})
	if across != "8G" {
		t.Errorf("across pos = %q, want 8G", across)
	}
	down := gcgPos(HistoryMove{Dir: "V", MainRow: 6, MainCol: 7})
	if down != "H7" {
		t.Errorf("down pos = %q, want H7", down)
	}
}
