import { NextResponse } from "next/server";

import {
  employeeScopeFromAccess,
  requirePermission,
} from "@/lib/authorization";
import { getEmployeByCos } from "@/services/employes.service";
import {
  extractEmployeePayslip,
  PayslipError,
} from "@/services/fiches-paie.service";
import { payslipSelectionSchema } from "@/validators/fiches-paie";

export const runtime = "nodejs";
export const dynamic = "force-dynamic";

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

export async function GET(request: Request, { params }: RouteContext) {
  const auth = await requirePermission(request, "fiches_paie", "read");

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

  const { cos: rawCos } = await params;
  const cos = Number(rawCos);

  if (!Number.isInteger(cos)) {
    return NextResponse.json(
      { message: "Paramètre COS invalide." },
      { status: 400 },
    );
  }

  const url = new URL(request.url);
  const selection = payslipSelectionSchema.safeParse({
    etablissement: url.searchParams.get("etablissement"),
    annee: url.searchParams.get("annee"),
    mois: url.searchParams.get("mois"),
  });

  if (!selection.success) {
    return NextResponse.json(
      {
        message: "Période de paie invalide.",
        issues: selection.error.flatten(),
      },
      { status: 400 },
    );
  }

  const employe = await getEmployeByCos(
    cos,
    employeeScopeFromAccess(auth.access),
  );

  if (!employe) {
    return NextResponse.json(
      { message: "Salarié introuvable ou non autorisé." },
      { status: 404 },
    );
  }

  if (employe.Matricule === null) {
    return NextResponse.json(
      { message: "Aucun matricule n'est renseigné pour ce salarié." },
      { status: 422 },
    );
  }

  const allowedEstablishments = auth.access.allEstablishments
    ? undefined
    : auth.access.establishments.map((item) => item.name);

  try {
    const result = await extractEmployeePayslip({
      establishment: selection.data.etablissement,
      year: selection.data.annee,
      month: selection.data.mois,
      matricule: employe.Matricule,
      allowedEstablishments,
    });

    const month = String(selection.data.mois).padStart(2, "0");

    return new NextResponse(result.bytes, {
      status: 200,
      headers: {
        "Content-Type": "application/pdf",
        "Content-Disposition": `inline; filename="fiche-paie-${selection.data.annee}-${month}.pdf"`,
        "Content-Length": String(result.bytes.byteLength),
        "Cache-Control": "no-store, private",
        Pragma: "no-cache",
        "X-Content-Type-Options": "nosniff",
        "X-Payslip-Page-Count": String(result.pageCount),
      },
    });
  } catch (error) {
    if (error instanceof PayslipError) {
      return NextResponse.json(
        { message: error.message, code: error.code },
        { status: error.status },
      );
    }

    return NextResponse.json(
      { message: "Impossible d'extraire cette fiche de paie." },
      { status: 500 },
    );
  }
}
