import { NextResponse } from "next/server";

import {
  employeeScopeFromAccess,
  requirePermission,
} from "@/lib/authorization";
import {
  renderAttestationEmploiPdf,
  renderAttestationMutuellePdf,
  renderAttestationProlongationMutuellePdf,
  renderAutorisationPrefecturePdf,
} from "@/services/additional-documents-pdf.service";
import {
  buildAttestationEmploiPdfDraft,
  buildAttestationMutuellePdfDraft,
  buildAttestationProlongationMutuellePdfDraft,
  buildAutorisationPrefecturePdfDraft,
  DocumentGenerationError,
  type AttestationEmploiPdfData,
  type AttestationMutuellePdfData,
  type AttestationProlongationMutuellePdfData,
  type AutorisationPrefecturePdfData,
} from "@/services/impressions.service";
import { additionalDocumentPdfSchemas } from "@/validators/impressions";

export const runtime = "nodejs";

type RouteContext = { params: Promise<{ document: string }> };
type AdditionalDocument = keyof typeof additionalDocumentPdfSchemas;

function isAdditionalDocument(value: string): value is AdditionalDocument {
  return value in additionalDocumentPdfSchemas;
}

export async function POST(request: Request, { params }: RouteContext) {
  const auth = await requirePermission(request, "impressions", "read");
  if (!auth.ok) return auth.response;

  const { document } = await params;
  if (!isAdditionalDocument(document)) {
    return NextResponse.json({ message: "Unknown document" }, { status: 404 });
  }

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

  const parsed = additionalDocumentPdfSchemas[document].safeParse(body);
  if (!parsed.success) {
    return NextResponse.json(
      { message: "Invalid document data", issues: parsed.error.issues },
      { status: 422 },
    );
  }

  const { cos, signataireId, data } = parsed.data;
  const scope = employeeScopeFromAccess(auth.access);

  try {
    let pdf: Buffer;
    switch (document) {
      case "attestation-emploi":
        await buildAttestationEmploiPdfDraft(cos, signataireId, scope);
        pdf = await renderAttestationEmploiPdf(data as AttestationEmploiPdfData);
        break;
      case "attestation-mutuelle":
        await buildAttestationMutuellePdfDraft(cos, signataireId, scope);
        pdf = await renderAttestationMutuellePdf(data as AttestationMutuellePdfData);
        break;
      case "attestation-prolongation-mutuelle":
        await buildAttestationProlongationMutuellePdfDraft(cos, signataireId, scope);
        pdf = await renderAttestationProlongationMutuellePdf(
          data as AttestationProlongationMutuellePdfData,
        );
        break;
      case "autorisation-prefecture":
        await buildAutorisationPrefecturePdfDraft(cos, signataireId, scope);
        pdf = await renderAutorisationPrefecturePdf(
          data as AutorisationPrefecturePdfData,
        );
        break;
    }

    return new NextResponse(new Uint8Array(pdf), {
      status: 200,
      headers: {
        "Content-Type": "application/pdf",
        "Content-Disposition": `inline; filename="${document}-${cos}.pdf"`,
        "Cache-Control": "private, no-store",
      },
    });
  } catch (error: unknown) {
    if (error instanceof DocumentGenerationError) {
      const status = error.code === "CONTRACT_NOT_FOUND" ? 409 : 404;
      return NextResponse.json({ message: error.code }, { status });
    }

    console.error(`Erreur lors de la génération PDF ${document}`, error);
    return NextResponse.json({ message: "PDF generation failed" }, { status: 500 });
  }
}
