import assert from "node:assert/strict";
import { createRequire } from "node:module";
import { fileURLToPath } from "node:url";
import path from "node:path";
import { readFileSync } from "node:fs";
import test from "node:test";
import { LegacyGameCoordinator } from "../src/games/LegacyGameCoordinator.ts";
import type { BotConfig } from "../src/config.ts";
import type { ChannelStatus, EngineEvent } from "../src/types.ts";

const require = createRequire(import.meta.url);
const here = path.dirname(fileURLToPath(import.meta.url));
const legacyRoot = path.resolve(here, "../../../legacy/games-original");

const games = [
  ["quiz", "quiz-engine.js", "QuizEngine", "quiz-start"],
  ["motus", "motus-engine.js", "MotusEngine", "motus-state"],
  ["whoami", "whoami-engine.js", "WhoamiEngine", "whoami-start"],
  ["petitbac", "petitbac-engine.js", "PetitbacEngine", "petitbac-start"],
] as const;

for (const [slug, file, exportName, openingEvent] of games) {
  test(`${slug} démarre avec ses données et émet son premier événement`, () => {
    const module = require(path.join(legacyRoot, "src", file)) as Record<string, new (broadcast: (event: Record<string, unknown>) => void, chat: () => void) => { start(config: Record<string, unknown>, user: string): { ok: boolean }; stop(): unknown }>;
    const Engine = module[exportName];
    assert.ok(Engine, `Moteur historique manquant : ${exportName}`);
    const events: Record<string, unknown>[] = [];
    const engine = new Engine((event) => events.push(event), () => undefined);
    const config = JSON.parse(readFileSync(path.join(legacyRoot, `config.${slug}.json`), "utf8")) as Record<string, unknown>;
    const started = engine.start({ ...config, cooldown: 0, gameCooldown: 0 }, "Test FilyX");
    engine.stop();

    assert.equal(started.ok, true);
    assert.ok(events.some((event) => event.type === openingEvent));
  });
}

test("Petit Bac reste arrêté durant l’animation de tirage", () => {
  const module = require(path.join(legacyRoot, "src", "petitbac-engine.js")) as Record<string, new (broadcast: () => void, chat: () => void) => { start(config: Record<string, unknown>, user: string): { ok: boolean }; stop(): unknown; letterDrawTimer: NodeJS.Timeout | null; startDelayTimer: NodeJS.Timeout | null }>;
  const Engine = module.PetitbacEngine;
  assert.ok(Engine, "Moteur historique manquant : PetitbacEngine");
  const engine = new Engine(() => undefined, () => undefined);
  const config = JSON.parse(readFileSync(path.join(legacyRoot, "config.petitbac.json"), "utf8")) as Record<string, unknown>;
  assert.equal(engine.start(config, "Test FilyX").ok, true);
  assert.notEqual(engine.letterDrawTimer, null);
  engine.stop();
  assert.equal(engine.letterDrawTimer, null);
  assert.equal(engine.startDelayTimer, null);
});

test("une même session ne redémarre pas si l'API change le type d'un identifiant", async () => {
  const events: EngineEvent[] = [];
  const leases: string[] = [];
  const coordinator = new LegacyGameCoordinator(
    { legacyRoot: path.dirname(legacyRoot) } as BotConfig,
    (event) => events.push(event),
    async (_channelId, sessionId, action) => {
      leases.push(`${action}:${sessionId}`);
      return true;
    }
  );
  const channel = {
    channel_id: 1,
    streamer_id: 1,
    kick_channel_id: "1",
    kick_user_id: "1",
    kick_chatroom_id: "1",
    slug: "test",
    display_name: "Test",
    live_status: "online",
    moderator_status: "moderator"
  } as ChannelStatus;
  await coordinator.sync(channel, { game_session_id: 987, game: "motus", state: "starting" });
  await coordinator.sync(
    { ...channel, channel_id: "1" as unknown as number },
    { game_session_id: "987" as unknown as number, game: "motus", state: "playing" }
  );
  coordinator.stop();

  assert.equal(events.filter((event) => event.type === "game.session.started").length, 1);
  assert.deepEqual(leases, ["claim:987", "renew:987"]);
});

test("une réponse panel momentanément vide ne redémarre pas la partie", async () => {
  const events: EngineEvent[] = [];
  const coordinator = new LegacyGameCoordinator(
    { legacyRoot: path.dirname(legacyRoot) } as BotConfig,
    (event) => events.push(event),
    async () => true
  );
  const channel = {
    channel_id: 9,
    streamer_id: 1,
    kick_channel_id: "9",
    kick_user_id: "9",
    kick_chatroom_id: "9",
    slug: "test",
    display_name: "Test",
    live_status: "online",
    moderator_status: "moderator"
  } as ChannelStatus;
  const game = { game_session_id: 654, game: "whoami", state: "starting" } as const;
  await coordinator.sync(channel, game);
  await coordinator.sync(channel, null);
  await coordinator.sync(channel, { ...game, state: "playing" });
  coordinator.stop();

  assert.equal(events.filter((event) => event.type === "game.session.started").length, 1);
});
