import { describe, it, expect, beforeEach } from "vitest";
import { gameEventBus } from "../gameEvents";

function listenOnce(eventName) {
  return new Promise((resolve) => {
    gameEventBus.addEventListener(eventName, (e) => resolve(e), { once: true });
  });
}

describe("gameEventBus", () => {
  describe("executeCode", () => {
    it("dispatches executeCode event with code and workspace in detail", async () => {
      const p = listenOnce("executeCode");
      gameEventBus.executeCode("console.log(1)", { blocks: [] });
      const e = await p;
      expect(e.detail).toEqual({ code: "console.log(1)", workspace: { blocks: [] } });
    });

    it("dispatches executeCode with undefined workspace when omitted", async () => {
      const p = listenOnce("executeCode");
      gameEventBus.executeCode("x = 1");
      const e = await p;
      expect(e.detail.code).toBe("x = 1");
      expect(e.detail.workspace).toBeUndefined();
    });
  });

  describe("resetGame", () => {
    it("dispatches resetGame event", async () => {
      const p = listenOnce("resetGame");
      gameEventBus.resetGame();
      const e = await p;
      expect(e.type).toBe("resetGame");
    });
  });

  describe("pauseGame", () => {
    it("dispatches pauseGame event", async () => {
      const p = listenOnce("pauseGame");
      gameEventBus.pauseGame();
      const e = await p;
      expect(e.type).toBe("pauseGame");
    });
  });

  describe("gameSuccess", () => {
    it("dispatches gameSuccess event", async () => {
      const p = listenOnce("gameSuccess");
      gameEventBus.gameSuccess();
      const e = await p;
      expect(e.type).toBe("gameSuccess");
    });
  });

  describe("gameFailure", () => {
    it("dispatches gameFailure with reason in detail", async () => {
      const p = listenOnce("gameFailure");
      gameEventBus.gameFailure("colisão detectada");
      const e = await p;
      expect(e.detail).toEqual({ reason: "colisão detectada" });
    });

    it("dispatches gameFailure with undefined reason when omitted", async () => {
      const p = listenOnce("gameFailure");
      gameEventBus.gameFailure();
      const e = await p;
      expect(e.detail).toEqual({ reason: undefined });
    });
  });

  describe("gameReady", () => {
    it("dispatches gameReady event", async () => {
      const p = listenOnce("gameReady");
      gameEventBus.gameReady();
      const e = await p;
      expect(e.type).toBe("gameReady");
    });
  });

  describe("stopExecution", () => {
    it("dispatches stopExecution event", async () => {
      const p = listenOnce("stopExecution");
      gameEventBus.stopExecution();
      const e = await p;
      expect(e.type).toBe("stopExecution");
    });
  });

  it("is an EventTarget", () => {
    expect(gameEventBus).toBeInstanceOf(EventTarget);
  });
});
