import path from "node:path";

import PDFDocument from "pdfkit";

import type { AttestationImpotsPdfData } from "@/services/impressions.service";

function formatLongFrenchDate(value: string) {
  const [year, month, day] = value.split("-").map(Number);

  if (!year || !month || !day) return value;

  const formatted = new Intl.DateTimeFormat("fr-FR", {
    timeZone: "Europe/Paris",
    day: "numeric",
    month: "long",
    year: "numeric",
  }).format(new Date(Date.UTC(year, month - 1, day, 12)));

  return day === 1 ? formatted.replace(/^1 /, "1er ") : formatted;
}

function qualitePoste(poste: string) {
  const firstLetter = poste
    .trim()
    .normalize("NFD")
    .replace(/[\u0300-\u036f]/g, "")
    .charAt(0)
    .toLowerCase();

  return "aeiouyh".includes(firstLetter) ? `d'${poste}` : `de ${poste}`;
}

function employmentSentence(data: AttestationImpotsPdfData) {
  const startDate = formatLongFrenchDate(data.dateEmbauche);

  if (data.estToujoursDansEffectifs) {
    return `${data.titreNomPrenom} ${data.domicilie} ${data.adresseLigne} travaille au sein de notre société en ${data.typeContrat} depuis le ${startDate} en qualité ${qualitePoste(data.poste)} et est toujours dans nos effectifs à ce jour.`;
  }

  const end = data.dateFinContrat
    ? ` jusqu'au ${formatLongFrenchDate(data.dateFinContrat)}`
    : "";

  return `${data.titreNomPrenom} ${data.domicilie} ${data.adresseLigne} a travaillé au sein de notre société en ${data.typeContrat} du ${startDate}${end} en qualité ${qualitePoste(data.poste)}.`;
}

export async function renderAttestationImpotsPdf(
  data: AttestationImpotsPdfData,
): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    const chunks: Buffer[] = [];
    const regularFontPath = path.join(
      process.cwd(),
      "public",
      "fonts",
      "DejaVuSans.ttf",
    );
    const boldFontPath = path.join(
      process.cwd(),
      "public",
      "fonts",
      "DejaVuSans-Bold.ttf",
    );
    const document = new PDFDocument({
      size: "A4",
      margins: { top: 0, right: 0, bottom: 0, left: 0 },
      // PDFKit otherwise loads its bundled Helvetica.afm during construction.
      // Next.js rewrites that internal path when bundling an API route, which
      // makes the real route fail although direct unit tests still pass.
      font: regularFontPath,
      info: {
        Title: `Attestation impôts - ${data.titreNomPrenom}`,
        Author: "RH Connect",
        Subject: "Attestation d'emploi",
      },
      compress: true,
    });

    document.on("data", (chunk: Buffer) => chunks.push(chunk));
    document.on("end", () => resolve(Buffer.concat(chunks)));
    document.on("error", reject);

    const pageWidth = document.page.width;
    const margin = 72;
    const contentWidth = pageWidth - margin * 2;

    document.registerFont("DocumentRegular", regularFontPath);
    document.registerFont("DocumentBold", boldFontPath);

    document
      .lineWidth(0.75)
      .rect(margin, 218, contentWidth, 24)
      .stroke("#111111");
    document
      .font("DocumentBold")
      .fontSize(15)
      .fillColor("#111111")
      .text("ATTESTATION", margin, 222, {
        width: contentWidth,
        align: "center",
      });

    const introduction = `Je ${data.formuleSoussignataire}, ${data.signataireNom} - ${data.signataireFonction} de la ${data.entreprise}, atteste par la présente que ${employmentSentence(data)}`;

    document
      .font("DocumentRegular")
      .fontSize(11.5)
      .fillColor("#111111")
      .text(introduction, margin + 4, 314, {
        width: contentWidth - 8,
        align: "justify",
        lineGap: 2.5,
      });

    document.text(
      "Aucun repas n'est fourni par la société ni supplément familial versé sur la fiche de paie.",
      margin + 4,
      document.y + 24,
      {
        width: contentWidth - 8,
        align: "left",
        lineGap: 2.5,
      },
    );

    const closingY = Math.max(document.y + 40, 486);
    document.text(
      "Pour faire et valoir ce que de droit.",
      108,
      closingY,
      {
        width: 300,
        align: "left",
      },
    );

    const signatureWidth = 225;
    const signatureX = pageWidth - margin - signatureWidth;
    const signatureDateY = Math.max(552, document.y + 62);
    document.text(
      `Fait à ${data.lieuDocument},\nLe ${formatLongFrenchDate(data.dateDocument)}.`,
      signatureX,
      signatureDateY,
      {
        width: signatureWidth,
        align: "right",
        lineGap: 2,
      },
    );
    document.text(
      `${data.signataireNom}\n${data.signataireFonction}`,
      signatureX - 40,
      signatureDateY + 70,
      {
        width: signatureWidth + 40,
        align: "right",
        lineGap: 2,
      },
    );

    document.end();
  });
}
