import { describe, it, expect } from "vitest";
import {
  DIFFICULTIES,
  LEVELS_PER_DIFFICULTY,
  REWARD_POINTS,
  AID_PACKS,
  TOKEN_TTL,
  REFRESH_TTL,
  REFRESH_COOKIE_NAME,
  MAX_FAILED_LOGINS,
  LOCK_TIME_MS,
  RESET_TOKEN_TTL_MS,
} from "../constants.js";

describe("constants", () => {
  describe("DIFFICULTIES", () => {
    it("contient les 4 difficultés dans l'ordre", () => {
      expect(DIFFICULTIES).toEqual(["easy", "medium", "hard", "expert"]);
    });

    it("est un tuple readonly (as const)", () => {
      // `as const` en TS ne gèle pas au runtime, mais on vérifie sa structure
      expect(Array.isArray(DIFFICULTIES)).toBe(true);
      expect(DIFFICULTIES).toHaveLength(4);
    });
  });

  describe("LEVELS_PER_DIFFICULTY", () => {
    it("vaut 240", () => {
      expect(LEVELS_PER_DIFFICULTY).toBe(240);
    });
  });

  describe("REWARD_POINTS", () => {
    it("a une entrée pour chaque difficulté", () => {
      for (const key of DIFFICULTIES) {
        expect(REWARD_POINTS[key]).toBeGreaterThan(0);
      }
    });

    it("les points augmentent avec la difficulté", () => {
      expect(REWARD_POINTS.easy).toBeLessThan(REWARD_POINTS.medium);
      expect(REWARD_POINTS.medium).toBeLessThan(REWARD_POINTS.hard);
      expect(REWARD_POINTS.hard).toBeLessThan(REWARD_POINTS.expert);
    });

    it("valeurs exactes : 8, 12, 16, 22", () => {
      expect(REWARD_POINTS.easy).toBe(8);
      expect(REWARD_POINTS.medium).toBe(12);
      expect(REWARD_POINTS.hard).toBe(16);
      expect(REWARD_POINTS.expert).toBe(22);
    });
  });

  describe("AID_PACKS", () => {
    it("contient 4 packs", () => {
      expect(AID_PACKS).toHaveLength(4);
    });

    it("chaque pack a id, cost et inventory", () => {
      for (const pack of AID_PACKS) {
        expect(pack.id).toBeTruthy();
        expect(pack.cost).toBeGreaterThan(0);
        expect(pack.inventory).toBeDefined();
        expect(typeof pack.inventory.hints).toBe("number");
        expect(typeof pack.inventory.undos).toBe("number");
        expect(typeof pack.inventory.replays).toBe("number");
      }
    });

    it("les IDs sont uniques", () => {
      const ids = AID_PACKS.map((p) => p.id);
      expect(new Set(ids).size).toBe(ids.length);
    });

    it("les coûts sont croissants", () => {
      for (let i = 1; i < AID_PACKS.length; i++) {
        expect(AID_PACKS[i].cost).toBeGreaterThan(AID_PACKS[i - 1].cost);
      }
    });
  });

  describe("valeurs de sécurité", () => {
    it("TOKEN_TTL est défini", () => {
      expect(TOKEN_TTL).toBe("2h");
    });

    it("REFRESH_TTL est défini", () => {
      expect(REFRESH_TTL).toBe("7d");
    });

    it("REFRESH_COOKIE_NAME est défini", () => {
      expect(REFRESH_COOKIE_NAME).toBe("rl_refresh");
    });

    it("MAX_FAILED_LOGINS = 5", () => {
      expect(MAX_FAILED_LOGINS).toBe(5);
    });

    it("LOCK_TIME_MS = 15 minutes", () => {
      expect(LOCK_TIME_MS).toBe(15 * 60 * 1000);
    });

    it("RESET_TOKEN_TTL_MS = 1 heure", () => {
      expect(RESET_TOKEN_TTL_MS).toBe(60 * 60 * 1000);
    });
  });
});
