import assert from "node:assert/strict";
import { build } from "esbuild";

const { parseScreenshotExtractionText } = await loadParser();

const lsuPlayers = [
  player("Houston Anderson", "Houston", "Anderson", "QB", "LSU"),
  player("Corey Cooley", "Corey", "Cooley", "HB", "LSU"),
  player("Ryelan Morris", "Ryelan", "Morris", "HB", "LSU"),
  player("David Gabriel Georges", "David Gabriel", "Georges", "HB", "LSU"),
  player("Julian Reese II", "Julian", "Reese II", "WR", "LSU"),
  player("DeJoshua Dunlap", "DeJoshua", "Dunlap", "WR", "LSU"),
  player("Zachary Powell", "Zachary", "Powell", "WR", "LSU"),
  player("Jack Bassler", "Jack", "Bassler", "TE", "LSU"),
  player("Anthony Tinsley", "Anthony", "Tinsley", "P", "LSU"),
  player("Gavin Melton", "Gavin", "Melton", "K", "LSU"),
  player("Aiden Hall", "Aiden", "Hall", "SS", "LSU")
];

const aubPlayers = [
  player("Steve Boone", "Steve", "Boone", "QB", "AUB", "Auburn"),
  player("Javontez Price", "Javontez", "Price", "HB", "AUB", "Auburn")
];

const aubLsuScore = {
  gameRow: 874,
  awayTeamShortName: "AUB",
  awayTeamDisplayName: "Auburn",
  awayScore: 0,
  homeTeamShortName: "LSU",
  homeTeamDisplayName: "LSU",
  homeScore: 66
};

const tests = [
  ["parses clipped passing touchdown glyphs", testPassingGlyphs],
  ["cleans rushing stat row names and values", testRushingRows],
  ["cleans receiving stat row names", testReceivingRows],
  ["parses highlight rows against target game context", testHighlightRows],
  ["does not infer teams outside target game", testHighlightTeamConstraint]
];

for (const [name, fn] of tests) {
  fn();
  console.log(`ok - ${name}`);
}

console.log(`${tests.length} screenshot parser tests passed.`);

async function loadParser() {
  const result = await build({
    entryPoints: ["packages/shared/src/screenshotTextParser.ts"],
    bundle: true,
    write: false,
    format: "esm",
    platform: "node",
    logLevel: "silent"
  });
  const source = result.outputFiles[0].text;
  return import(`data:text/javascript;base64,${Buffer.from(source).toString("base64")}`);
}

function testPassingGlyphs() {
  const rows = parseScreenshotExtractionText(
    "passing_stats",
    "LSU H.Anderson 255.2 21 34 508 61 i] 0 14.8",
    { playerCandidates: lsuPlayers }
  );

  assert.equal(rows.length, 1);
  assert.equal(rows[0].player, "Houston Anderson");
  assert.equal(rows[0].playerOcr, "H.Anderson");
  assert.equal(rows[0].touchdowns, 1);
  assert.equal(rows[0].interceptions, 0);
  assert.equal(rows[0].average, 14.8);
}

function testRushingRows() {
  const rows = parseScreenshotExtractionText(
    "rushing_stats",
    [
      "LSU C.Cooley 17 169 9.9 1 0 4 32 1 8",
      "LSU R.Morris 7 48 [X:] [1] 0 1 29 1 31",
      "LSU H.Anderson 6 -9 15 [1 0 1 5 0 5",
      "LSU D.Georges 6 19 31 0 1 1 1 0 8",
      "LSU J.Reeselll 1 1 1.0 [1 0 [1 [1 0 1"
    ].join("\n"),
    { playerCandidates: lsuPlayers }
  );

  assert.deepEqual(
    rows.map((row) => row.player),
    [
      "Corey Cooley",
      "Ryelan Morris",
      "Houston Anderson",
      "David Gabriel Georges",
      "Julian Reese II"
    ]
  );
  assert.equal(rows[1].average, null);
  assert.equal(rows[1].touchdowns, 1);
  assert.equal(rows[4].playerOcr, "J.Reeselll");
  assert.equal(rows[4].touchdowns, 1);
}

function testReceivingRows() {
  const rows = parseScreenshotExtractionText(
    "receiving_stats",
    [
      "LSU J.Reesell 9 283 31.4 4 185 20.5 2 78",
      "LSU D.Dunlap 6 108 18.0 1 20 3.3 0 30",
      "LSU 1.Powell 4 84 21.0 2 38 9.5 0 36",
      "LSU J.Bassler 2 33 16.5 0 19 9.5 0 7"
    ].join("\n"),
    { playerCandidates: lsuPlayers }
  );

  assert.deepEqual(
    rows.map((row) => row.player),
    ["Julian Reese II", "DeJoshua Dunlap", "Zachary Powell", "Jack Bassler"]
  );
  assert.equal(rows[0].touchdowns, 4);
  assert.equal(rows[0].drops, 2);
  assert.equal(rows[2].playerOcr, "1.Powell");
}

function testHighlightRows() {
  const rows = parseScreenshotExtractionText("highlight_list", highlightOcrText(), {
    gameScoreCandidates: [aubLsuScore],
    playerCandidates: [...aubPlayers, ...lsuPlayers]
  });

  assert.equal(rows.length, 8);
  assert.deepEqual(
    rows.map((row) => row.sequence),
    [1, 2, 3, 4, 5, 6, 7, 8]
  );
  assert.deepEqual(
    rows.map((row) => row.period),
    [null, null, null, null, null, null, null, null]
  );
  assert.deepEqual(
    rows.map((row) => row.team),
    ["AUB", "AUB", "LSU", "LSU", "LSU", "LSU", "LSU", "LSU"]
  );
  assert.deepEqual(
    rows.map((row) => row.score),
    Array.from({ length: 8 }, () => "AUB 0 - LSU 66")
  );
  assert.match(String(rows[6].summary), /Julian Reese II/);
}

function testHighlightTeamConstraint() {
  const rows = parseScreenshotExtractionText(
    "highlight_list",
    "N/A 2nd & 10 on AUB 25. Steve Boone pass to Javontez Price for 5 yards.",
    {
      gameScoreCandidates: [aubLsuScore],
      playerCandidates: [
        player("Steve Boone", "Steve", "Boone", "QB", "WVU", "West Virginia"),
        player("Javontez Price", "Javontez", "Price", "HB", "WVU", "West Virginia")
      ]
    }
  );

  assert.equal(rows.length, 1);
  assert.equal(rows[0].team, null);
  assert.equal(rows[0].score, "AUB 0 - LSU 66");
}

function highlightOcrText() {
  return `[Score Banner]
7
2
2
2
1
2
]
Total
7
<
7
0
0
0
0
n=l
N
0
X
N
24
28
N
AUB
1 1 66
LSU
X
N

[Highlight Rows]
RATING HIGHLIGHT
on Ee ef

N/A 2nd & 10 on AUB 25. Steve Boone pass to Javontez Price for 5 yards.
N/A 1st & 10 on AUB 25. Steve Boone pass knocked away by Aiden Hall.
N/A Kickoff on LSU 35. 68 yard kick by Anthony Tinsley for a touchback.
N/A PAT on AUB 3. Extra point good by Gavin Melton.
N/A 2nd & 6 on LSU 49. 31 yard rush by Ryelan Morris.
N/A 1st & 10 on LSU 45. 4 yard rush by Ryelan Morris.
N/A 3rd & 6 on LSU 29. Houston Anderson pass to Julian Reese Il for 16 yards.
N/A 2nd & 8 on LSU 27. 2 yard rush by Corey Cooley.`;
}

function player(
  displayName,
  firstName,
  lastName,
  position,
  teamShortName,
  teamDisplayName = teamShortName
) {
  return {
    displayName,
    firstName,
    lastName,
    position,
    teamShortName,
    teamDisplayName
  };
}
