import { describe, it, expect, vi, beforeEach } from "vitest";
import fastify from "fastify";
import { registerLevelsRoutes } from "../levels-routes.js";
import { makeCtx, makeDb } from "./helpers.js";

describe("levels-routes", () => {
  beforeEach(() => {
    vi.clearAllMocks();
  });

  describe("GET /levels/:difficulty/:index", () => {
    it("retourne un niveau quand trouvé en BDD", async () => {
      const levelData = {
        id: 1,
        name: "Easy 0",
        difficulty: "easy",
        tiles: [[]],
      };
      const db = makeDb(async () => [[{ payload: JSON.stringify(levelData) }]]);
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx({ db }));

      const res = await app.inject({ method: "GET", url: "/levels/easy/0" });
      expect(res.statusCode).toBe(200);
      const body = JSON.parse(res.body);
      expect(body.level).toEqual(levelData);
    });

    it("retourne 404 si le niveau n'existe pas en BDD", async () => {
      const db = makeDb(async () => [[]]);
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx({ db }));

      const res = await app.inject({ method: "GET", url: "/levels/easy/0" });
      expect(res.statusCode).toBe(404);
    });

    it("refuse une difficulté invalide", async () => {
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx());

      const res = await app.inject({
        method: "GET",
        url: "/levels/impossible/0",
      });
      expect(res.statusCode).toBe(400);
    });

    it("refuse un index négatif", async () => {
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx());

      const res = await app.inject({ method: "GET", url: "/levels/easy/-1" });
      expect(res.statusCode).toBe(400);
    });

    it("refuse un index supérieur à 239", async () => {
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx());

      const res = await app.inject({ method: "GET", url: "/levels/easy/240" });
      expect(res.statusCode).toBe(400);
    });
  });

  describe("GET /levels/daily/:dateKey", () => {
    it("retourne le niveau quotidien pour une date valide", async () => {
      const levelData = { id: 42, name: "Medium", tiles: [[]] };
      const db = makeDb(async () => [[{ payload: JSON.stringify(levelData) }]]);
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx({ db }));

      const res = await app.inject({
        method: "GET",
        url: "/levels/daily/2025-06-15",
      });
      expect(res.statusCode).toBe(200);
      const body = JSON.parse(res.body);
      expect(body.level.name).toBe("Defi 2025-06-15");
      // moveLimit et timeLimit supprimés
      expect(body.level.moveLimit).toBeUndefined();
      expect(body.level.timeLimit).toBeUndefined();
    });

    it("retourne 404 si le niveau quotidien n'existe pas en BDD", async () => {
      const db = makeDb(async () => [[]]);
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx({ db }));

      const res = await app.inject({
        method: "GET",
        url: "/levels/daily/2025-06-15",
      });
      expect(res.statusCode).toBe(404);
    });

    it("retourne 400 pour une date invalide", async () => {
      const app = fastify();
      await registerLevelsRoutes(app, makeCtx());

      const res = await app.inject({
        method: "GET",
        url: "/levels/daily/not-a-date",
      });
      expect(res.statusCode).toBe(400);
    });
  });
});
