import { NextResponse } from "next/server";

import {
  employeeScopeFromAccess,
  requirePermission,
} from "@/lib/authorization";
import {
  renderDocumentDocx,
  type WordDocumentKind,
} from "@/services/documents-docx.service";
import {
  buildAttestationEmploiPdfDraft,
  buildAttestationImpotsPdfDraft,
  buildAttestationMutuellePdfDraft,
  buildAttestationProlongationMutuellePdfDraft,
  buildAttestationRetraitePdfDraft,
  buildAutorisationPrefecturePdfDraft,
  DocumentGenerationError,
} from "@/services/impressions.service";
import {
  additionalDocumentPdfSchemas,
  attestationImpotsPdfSchema,
  attestationRetraitePdfSchema,
} from "@/validators/impressions";

export const runtime = "nodejs";

type RouteContext = { params: Promise<{ document: string }> };

const wordDocumentSchemas = {
  "attestation-impots": attestationImpotsPdfSchema,
  "attestation-retraite": attestationRetraitePdfSchema,
  ...additionalDocumentPdfSchemas,
} as const;

function isWordDocument(value: string): value is WordDocumentKind {
  return value in wordDocumentSchemas;
}

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 (!isWordDocument(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 = wordDocumentSchemas[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 {
    switch (document) {
      case "attestation-impots":
        await buildAttestationImpotsPdfDraft(cos, signataireId, scope);
        break;
      case "attestation-retraite":
        await buildAttestationRetraitePdfDraft(cos, signataireId, scope);
        break;
      case "attestation-emploi":
        await buildAttestationEmploiPdfDraft(cos, signataireId, scope);
        break;
      case "attestation-mutuelle":
        await buildAttestationMutuellePdfDraft(cos, signataireId, scope);
        break;
      case "attestation-prolongation-mutuelle":
        await buildAttestationProlongationMutuellePdfDraft(
          cos,
          signataireId,
          scope,
        );
        break;
      case "autorisation-prefecture":
        await buildAutorisationPrefecturePdfDraft(cos, signataireId, scope);
        break;
    }

    const word = renderDocumentDocx(
      document,
      data as Parameters<typeof renderDocumentDocx>[1],
    );

    return new NextResponse(new Uint8Array(word), {
      status: 200,
      headers: {
        "Content-Type":
          "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
        "Content-Disposition": `attachment; filename="${document}-${cos}.docx"`,
        "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 Word ${document}`, error);
    return NextResponse.json(
      { message: "Word generation failed" },
      { status: 500 },
    );
  }
}
