/**
 * Routes des niveaux
 * /levels/*
 */
import type { FastifyInstance } from "fastify";
import type { RouteContext } from "./types.js";
import { LEVELS_PER_DIFFICULTY as CATALOG_LEVELS } from "../level-generator.js";
import { DIFFICULTIES, type DifficultyKey } from "../server/constants.js";
import { getDayOfYear } from "../server/crypto-utils.js";
import { parseLevelPayload } from "../server/parsers.js";

const difficultySchema = {
  type: "string",
  enum: DIFFICULTIES,
} as const;

export const registerLevelsRoutes = async (
  app: FastifyInstance,
  ctx: RouteContext,
): Promise<void> => {
  const { db } = ctx;

  // GET /levels/:difficulty/:index - Récupérer un niveau
  app.get(
    "/levels/:difficulty/:index",
    {
      schema: {
        params: {
          type: "object",
          required: ["difficulty", "index"],
          additionalProperties: false,
          properties: {
            difficulty: difficultySchema,
            index: { type: "integer", minimum: 0, maximum: CATALOG_LEVELS - 1 },
          },
        },
      },
    },
    async (request, reply) => {
      const params = request.params as {
        difficulty: DifficultyKey;
        index: number;
      };
      const difficulty = params.difficulty;
      const index = Number(params.index);
      if (!DIFFICULTIES.includes(difficulty) || !Number.isFinite(index)) {
        reply.code(400);
        return { error: "Parametres invalides" };
      }
      const [rows] = await db.execute(
        "SELECT payload FROM levels_catalog WHERE difficulty = ? AND level_index = ? LIMIT 1",
        [difficulty, index],
      );
      const row = Array.isArray(rows)
        ? (rows[0] as { payload?: unknown })
        : undefined;
      const payload = parseLevelPayload(row?.payload);
      if (!payload) {
        reply.code(404);
        return { error: "Niveau introuvable" };
      }
      return { level: payload };
    },
  );

  // GET /levels/daily/:dateKey - Récupérer le niveau quotidien
  app.get(
    "/levels/daily/:dateKey",
    {
      schema: {
        params: {
          type: "object",
          required: ["dateKey"],
          additionalProperties: false,
          properties: {
            dateKey: { type: "string", minLength: 8, maxLength: 16 },
          },
        },
      },
    },
    async (request, reply) => {
      const params = request.params as { dateKey: string };
      const dateKey = params.dateKey.trim();
      if (!dateKey) {
        reply.code(400);
        return { error: "Date invalide" };
      }
      const parsed = new Date(dateKey);
      if (Number.isNaN(parsed.getTime())) {
        reply.code(400);
        return { error: "Date invalide" };
      }
      const dailyIndex = getDayOfYear(parsed) % CATALOG_LEVELS;
      const [rows] = await db.execute(
        "SELECT payload FROM levels_catalog WHERE difficulty = 'medium' AND level_index = ? LIMIT 1",
        [dailyIndex],
      );
      const row = Array.isArray(rows)
        ? (rows[0] as { payload?: unknown })
        : undefined;
      const payload = parseLevelPayload(row?.payload);
      if (!payload) {
        reply.code(404);
        return { error: "Niveau introuvable" };
      }
      const level = { ...payload, name: `Defi ${dateKey}` } as Record<
        string,
        unknown
      >;
      delete level.moveLimit;
      delete level.timeLimit;
      return { level };
    },
  );
};
