/**
 * Routes d'administration
 * /admin/*, /config/*
 */
import type { FastifyInstance } from "fastify";
import type { RouteContext } from "./types.js";
import { fetchAdminOverview } from "../server/admin-service.js";
import {
  fetchAdminConfig,
  fetchAppConfig,
  setAppConfigValue,
} from "../server/data-fetchers.js";

export const registerAdminRoutes = async (
  app: FastifyInstance,
  ctx: RouteContext,
): Promise<void> => {
  const { db, requireAdmin } = ctx;

  app.post(
    "/admin/init-maintenance-config",
    { preHandler: requireAdmin },
    async (req, reply) => {
      const [existing] = await db.execute(
        "SELECT config_key FROM app_config WHERE config_key IN ('maintenance_mode', 'maintenance_message')",
      );
      if (Array.isArray(existing) && existing.length >= 2) {
        return { status: "already_exists", count: existing.length };
      }

      await db.execute(
        "INSERT INTO app_config (config_key, config_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE config_value = config_value",
        ["maintenance_mode", "false"],
      );
      await db.execute(
        "INSERT INTO app_config (config_key, config_value) VALUES (?, ?) ON DUPLICATE KEY UPDATE config_value = config_value",
        ["maintenance_message", "Mise à jour en cours. Veuillez patienter..."],
      );

      return { status: "created" };
    },
  );

  app.get(
    "/admin/overview",
    { preHandler: requireAdmin },
    async (_request, reply) => {
      const overview = await fetchAdminOverview(db);
      return reply.send(overview);
    },
  );

  app.get("/config/public", async (_request, reply) => {
    const config = await fetchAppConfig(db);
    if (!ctx.config.ads.enabled) {
      config.adsUiEnabled = false;
    }
    return reply.send(config);
  });

  app.get(
    "/admin/config",
    { preHandler: requireAdmin },
    async (_request, reply) => {
      const config = await fetchAdminConfig(db);
      return reply.send(config);
    },
  );

  app.put(
    "/admin/config",
    {
      preHandler: requireAdmin,
      schema: {
        body: {
          type: "object",
          required: [],
          additionalProperties: false,
          properties: {
            musicSrc: {
              anyOf: [{ type: "string", maxLength: 255 }, { type: "null" }],
            },
            publicTheme: {
              anyOf: [{ type: "string", maxLength: 40 }, { type: "null" }],
            },
            publicThemeForce: {
              anyOf: [{ type: "boolean" }, { type: "null" }],
            },
            ballSkin: {
              anyOf: [{ type: "string", maxLength: 60 }, { type: "null" }],
            },
            challengePackEnabled: {
              anyOf: [{ type: "boolean" }, { type: "null" }],
            },
            launchDate: {
              anyOf: [{ type: "string", maxLength: 40 }, { type: "null" }],
            },
            maintenanceMode: {
              anyOf: [{ type: "boolean" }, { type: "null" }],
            },
            maintenanceMessage: {
              anyOf: [{ type: "string", maxLength: 500 }, { type: "null" }],
            },
            maintenanceEnd: {
              anyOf: [{ type: "string", maxLength: 40 }, { type: "null" }],
            },
            announcementEnabled: {
              anyOf: [{ type: "boolean" }, { type: "null" }],
            },
            announcementMessage: {
              anyOf: [{ type: "string", maxLength: 500 }, { type: "null" }],
            },
            announcementSpeed: {
              anyOf: [
                { type: "number", minimum: 20, maximum: 200 },
                { type: "null" },
              ],
            },
            adsUiEnabled: {
              anyOf: [{ type: "boolean" }, { type: "null" }],
            },
          },
        },
      },
    },
    async (request, reply) => {
      const body = request.body as
        | {
            musicSrc?: string | null;
            publicTheme?: string | null;
            publicThemeForce?: boolean | null;
            ballSkin?: string | null;
            challengePackEnabled?: boolean | null;
            launchDate?: string | null;
            maintenanceMode?: boolean | null;
            maintenanceMessage?: string | null;
            maintenanceEnd?: string | null;
            announcementEnabled?: boolean | null;
            announcementMessage?: string | null;
            announcementSpeed?: number | null;
            adsUiEnabled?: boolean | null;
          }
        | undefined;
      if (!body) {
        reply.code(400);
        return { error: "Payload invalide" };
      }
      if (body.musicSrc !== undefined) {
        await setAppConfigValue(db, "ui_music_src", body.musicSrc ?? null);
      }
      if (body.publicTheme !== undefined) {
        await setAppConfigValue(db, "public_theme", body.publicTheme ?? null);
      }
      if (body.publicThemeForce !== undefined) {
        await setAppConfigValue(
          db,
          "public_theme_force",
          body.publicThemeForce ? "1" : "0",
        );
      }
      if (body.ballSkin !== undefined) {
        await setAppConfigValue(db, "ball_skin", body.ballSkin ?? null);
      }
      if (body.challengePackEnabled !== undefined) {
        await setAppConfigValue(
          db,
          "challenge_pack_enabled",
          body.challengePackEnabled ? "1" : "0",
        );
      }
      if (body.launchDate !== undefined) {
        await setAppConfigValue(db, "launch_date", body.launchDate ?? null);
      }
      if (body.maintenanceMode !== undefined) {
        await setAppConfigValue(
          db,
          "maintenance_mode",
          body.maintenanceMode ? "1" : "0",
        );
      }
      if (body.maintenanceMessage !== undefined) {
        await setAppConfigValue(
          db,
          "maintenance_message",
          body.maintenanceMessage ?? null,
        );
      }
      if (body.maintenanceEnd !== undefined) {
        await setAppConfigValue(
          db,
          "maintenance_end",
          body.maintenanceEnd ?? null,
        );
      }
      if (body.announcementEnabled !== undefined) {
        await setAppConfigValue(
          db,
          "announcement_enabled",
          body.announcementEnabled ? "1" : "0",
        );
      }
      if (body.announcementMessage !== undefined) {
        await setAppConfigValue(
          db,
          "announcement_message",
          body.announcementMessage ?? null,
        );
      }
      if (body.announcementSpeed !== undefined) {
        const speed =
          typeof body.announcementSpeed === "number" &&
          Number.isFinite(body.announcementSpeed)
            ? Math.max(20, Math.min(200, Math.round(body.announcementSpeed)))
            : 72;
        await setAppConfigValue(db, "announcement_speed", String(speed));
      }
      if (body.adsUiEnabled !== undefined) {
        await setAppConfigValue(
          db,
          "ads_ui_enabled",
          body.adsUiEnabled ? "1" : "0",
        );
      }
      const config = await fetchAdminConfig(db);
      return reply.send(config);
    },
  );

  app.get(
    "/admin/dashboard",
    { preHandler: requireAdmin },
    async (_request, reply) => {
      const overview = await fetchAdminOverview(db);
      const html = `<!doctype html>
<html lang="fr">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <title>RollerLogic Admin</title>
    <style>
      :root {
        color-scheme: light;
        font-family: "Segoe UI", system-ui, sans-serif;
        background: #f4f6fb;
        color: #0f172a;
      }
      body {
        margin: 0;
        padding: 32px 20px 60px;
      }
      header {
        max-width: 960px;
        margin: 0 auto 24px;
        display: flex;
        justify-content: space-between;
        align-items: center;
        gap: 16px;
      }
      header h1 {
        font-size: 24px;
        margin: 0;
      }
      header small {
        color: #64748b;
      }
      .grid {
        max-width: 960px;
        margin: 0 auto;
        display: grid;
        grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
        gap: 16px;
      }
      .card {
        background: #ffffff;
        border-radius: 16px;
        padding: 16px;
        box-shadow: 0 12px 30px rgba(15, 23, 42, 0.08);
      }
      .card h3 {
        margin: 0 0 8px;
        font-size: 14px;
        color: #64748b;
        text-transform: uppercase;
        letter-spacing: 0.04em;
      }
      .card strong {
        font-size: 24px;
      }
      .actions {
        max-width: 960px;
        margin: 28px auto 0;
        display: flex;
        gap: 12px;
        flex-wrap: wrap;
      }
      .actions a {
        text-decoration: none;
        background: #0ea5e9;
        color: #fff;
        padding: 10px 14px;
        border-radius: 10px;
        font-weight: 600;
      }
    </style>
  </head>
  <body>
    <header>
      <div>
        <h1>RollerLogic Admin</h1>
        <small>Tableau de bord global</small>
      </div>
      <div>
        <small>Sessions actives : ${overview.activeSessions}</small>
      </div>
    </header>
    <section class="grid">
      <article class="card"><h3>Utilisateurs</h3><strong>${overview.users}</strong></article>
      <article class="card"><h3>Wallets</h3><strong>${overview.wallets}</strong></article>
      <article class="card"><h3>Progress rows</h3><strong>${overview.progressRows}</strong></article>
      <article class="card"><h3>Audit total</h3><strong>${overview.auditTotal}</strong></article>
      <article class="card"><h3>Audit 24h</h3><strong>${overview.auditLast24h}</strong></article>
      <article class="card"><h3>Sessions actives</h3><strong>${overview.activeSessions}</strong></article>
    </section>
    <section class="actions">
      <a href="/admin/overview" target="_blank" rel="noreferrer">Voir JSON</a>
    </section>
  </body>
</html>`;

      reply.type("text/html").send(html);
    },
  );
};
