import { NextResponse } from "next/server";

import { requirePermission } from "@/lib/authorization";
import { getSectorEmailSettingById } from "@/services/sector-emails.service";
import { sendAnonymizedSectorTestMail } from "@/services/sector-mail-test.service";
import { sectorEmailsTestSchema } from "@/validators/sector-emails";

export const dynamic = "force-dynamic";

const DEFAULT_COOLDOWN_SECONDS = 60;
let lastTestMailSentAt = 0;
let testMailSending = false;

function getCooldownSeconds() {
  const value = Number(process.env.SECTOR_MAIL_TEST_COOLDOWN_SECONDS);

  if (!Number.isFinite(value) || value < 1) {
    return DEFAULT_COOLDOWN_SECONDS;
  }

  return Math.floor(value);
}

export async function POST(request: Request) {
  const auth = await requirePermission(request, "parametres", "write");

  if (!auth.ok) {
    return auth.response;
  }

  let body: unknown;

  try {
    body = await request.json();
  } catch {
    return NextResponse.json(
      { message: "Corps JSON invalide" },
      { status: 400 },
    );
  }

  const parsed = sectorEmailsTestSchema.safeParse(body);

  if (!parsed.success) {
    return NextResponse.json(
      {
        message: "Confirmation de test invalide",
        errors: parsed.error.flatten(),
      },
      { status: 400 },
    );
  }

  const sector = await getSectorEmailSettingById(parsed.data.sectorId);

  if (!sector) {
    return NextResponse.json(
      { message: "Secteur introuvable" },
      { status: 404 },
    );
  }

  const cooldownMilliseconds = getCooldownSeconds() * 1_000;
  const remainingMilliseconds =
    cooldownMilliseconds - (Date.now() - lastTestMailSentAt);

  if (lastTestMailSentAt > 0 && remainingMilliseconds > 0) {
    const retryAfter = Math.ceil(remainingMilliseconds / 1_000);

    return NextResponse.json(
      {
        message: `Un test vient d’être envoyé. Réessaie dans ${retryAfter} seconde(s).`,
      },
      {
        status: 429,
        headers: {
          "Retry-After": String(retryAfter),
        },
      },
    );
  }

  if (testMailSending) {
    return NextResponse.json(
      { message: "Un envoi de test est déjà en cours." },
      { status: 429 },
    );
  }

  testMailSending = true;

  try {
    const result = await sendAnonymizedSectorTestMail({
      sectorName: sector.name,
      recipients: sector.emails,
    });

    lastTestMailSentAt = Date.now();

    return NextResponse.json({
      message: `Mail fictif envoyé pour le secteur ${sector.name} à ${result.recipients.length} destinataire(s).`,
      item: result,
    });
  } catch (error) {
    const code = error instanceof Error ? error.message : "";

    if (code === "SECTOR_TEST_MAIL_DISABLED") {
      return NextResponse.json(
        {
          message:
            "Les tests par secteur sont désactivés dans la configuration du serveur.",
        },
        { status: 503 },
      );
    }

    if (code === "SECTOR_TEST_MAIL_NO_RECIPIENT") {
      return NextResponse.json(
        {
          message: "Ce secteur ne possède aucun destinataire enregistré.",
        },
        { status: 400 },
      );
    }

    if (code === "SECTOR_TEST_MAIL_EMPTY_ALLOWLIST") {
      return NextResponse.json(
        {
          message:
            "La liste blanche des destinataires de test n’est pas configurée.",
        },
        { status: 503 },
      );
    }

    if (code.startsWith("SECTOR_TEST_MAIL_RECIPIENT_NOT_ALLOWED:")) {
      const recipient = code.slice(
        "SECTOR_TEST_MAIL_RECIPIENT_NOT_ALLOWED:".length,
      );

      return NextResponse.json(
        {
          message: `Envoi bloqué : ${recipient} n’est pas dans la liste blanche de test.`,
        },
        { status: 403 },
      );
    }

    if (code === "SECTOR_TEST_MAIL_INVALID_SMTP_CONFIGURATION") {
      return NextResponse.json(
        {
          message: "La configuration SMTP de test est absente ou invalide.",
        },
        { status: 503 },
      );
    }

    console.error("Échec de l’envoi du mail fictif par secteur :", error);

    return NextResponse.json(
      {
        message:
          "Échec de l’envoi du mail fictif. Consulte les journaux du backend.",
      },
      { status: 502 },
    );
  } finally {
    testMailSending = false;
  }
}
