import { describe, expect, it } from "vitest";
import {
  AMBIENT_PLACEMENTS,
  CHARACTER_CATALOGUE,
  LEVEL1_NPC_ROOM_IDS,
  PLAYER_CHARACTER_ID,
} from "../characters.js";
import { ROOM_CATALOGUE } from "./index.js";

/**
 * Level 1 contract: every non-player cast member has a dedicated room inside
 * the precinct building, and every placement points at a real catalogue room.
 */
describe("Ashgrove Precinct Level 1", () => {
  it("catalogues a room for every ambient NPC", () => {
    const ambientIds = [...CHARACTER_CATALOGUE.keys()].filter(
      (id) => id !== PLAYER_CHARACTER_ID,
    );
    expect(ambientIds.length).toBeGreaterThanOrEqual(6);

    for (const id of ambientIds) {
      const roomId = LEVEL1_NPC_ROOM_IDS.get(id);
      expect(roomId, `${id} needs a Level-1 room`).toBeDefined();
      expect(ROOM_CATALOGUE.has(roomId!), `${id} room ${roomId} missing`).toBe(true);
    }
  });

  it("places each ambient NPC in a unique room", () => {
    const rooms = AMBIENT_PLACEMENTS.map((p) => p.roomId);
    expect(new Set(rooms).size).toBe(rooms.length);
  });

  it("wires door targets only to known rooms with valid spawns", () => {
    for (const room of ROOM_CATALOGUE.values()) {
      for (const interactable of room.interactables) {
        if (interactable.action.kind !== "door") continue;
        const { targetRoomId, spawnPointId } = interactable.action;
        expect(ROOM_CATALOGUE.has(targetRoomId), `${room.id} → ${targetRoomId}`).toBe(true);
        const dest = ROOM_CATALOGUE.get(targetRoomId)!;
        const hasSpawn = dest.spawnPoints.some((point) => point.id === spawnPointId);
        expect(
          hasSpawn,
          `${room.id} door ${interactable.id} spawn ${spawnPointId} missing on ${targetRoomId}`,
        ).toBe(true);
      }
    }
  });

  it("gives every ambient placement a matching examine interactable", () => {
    for (const placement of AMBIENT_PLACEMENTS) {
      expect(placement.examine).toBeDefined();
      const room = ROOM_CATALOGUE.get(placement.roomId);
      expect(room).toBeDefined();
      const talk = room!.interactables.find((entry) => entry.id === placement.examine!.id);
      expect(talk, `${placement.characterId} examine ${placement.examine!.id}`).toBeDefined();
      expect(talk!.action.kind).toBe("examine");
    }
  });
});
