import PDFDocument from "pdfkit";
import fs from "node:fs";
import path from "node:path";
import { getMaterialEventLabel, materialEventItems, sanitizeMaterialEventQuantityMap, type MaterialEventItemKey } from "@shared/materialEvent";

const CCDS_LOGO_PATH = path.resolve(process.cwd(), "client/src/assets/ccds.png");

function drawLogo(doc: PDFKit.PDFDocument, x: number, y: number, width: number, height: number) {
  if (!fs.existsSync(CCDS_LOGO_PATH)) return;
  try {
    doc.image(CCDS_LOGO_PATH, x, y, { fit: [width, height], align: "center", valign: "center" });
  } catch (error) {
    console.warn("[MaterialReturnLitigationPdf] Impossible de charger le logo CCDS:", error);
  }
}

function formatDateFr(date: string | Date | null | undefined) {
  if (!date) return "-";
  try {
    return new Date(date).toLocaleDateString("fr-FR", {
      day: "2-digit",
      month: "2-digit",
      year: "numeric",
    });
  } catch {
    return String(date);
  }
}

function formatCurrency(amountCents: number | null | undefined) {
  if (!Number.isFinite(amountCents as number)) return "-";
  return new Intl.NumberFormat("fr-FR", {
    style: "currency",
    currency: "EUR",
  }).format((amountCents || 0) / 100);
}

export async function generateMaterialReturnLitigationLetterPdf(input: {
  request: {
    id: number;
    titre: string;
    formData?: string | null;
  };
  association?: {
    nomAssociation?: string | null;
    emailContact?: string | null;
    telephone?: string | null;
    ville?: string | null;
  } | null;
  followup: {
    restitutionDate?: string | Date | null;
    discrepancyCategories?: string[];
    discrepancyDetails?: string | null;
  };
  arbitration: {
    blockedItems: Record<MaterialEventItemKey, number>;
    decision: "partial_retention" | "full_retention" | "dismissed";
    amountCents: number;
    notes?: string | null;
  };
}) {
  const formData = (() => {
    try {
      return input.request.formData ? JSON.parse(input.request.formData) : {};
    } catch {
      return {};
    }
  })();

  const blockedItems = sanitizeMaterialEventQuantityMap(input.arbitration.blockedItems);
  const blockedRows = materialEventItems
    .map((item) => ({ ...item, quantity: blockedItems[item.key] || 0 }))
    .filter((item) => item.quantity > 0);

  const decisionLabel =
    input.arbitration.decision === "full_retention"
      ? "Encaissement total de la caution"
      : input.arbitration.decision === "partial_retention"
        ? "Retenue partielle sur caution"
        : "Classement sans suite";

  const pdfBuffer = await new Promise<Buffer>((resolve, reject) => {
    try {
      const doc = new PDFDocument({
        size: "A4",
        margins: { top: 38, bottom: 42, left: 46, right: 46 },
        info: {
          Title: `Courrier de litige - Demande ${input.request.id}`,
          Author: "Communauté de Communes Des Savanes",
          Subject: "Notification de litige sur restitution de matériel",
        },
      });

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

      const pageWidth = doc.page.width - doc.page.margins.left - doc.page.margins.right;
      let y = doc.page.margins.top;

      drawLogo(doc, doc.page.margins.left, y, 74, 74);
      doc.font("Helvetica-Bold").fontSize(16).fillColor("#0f172a").text(
        "Notification de litige et arbitrage matériel",
        doc.page.margins.left + 92,
        y + 14,
        { width: pageWidth - 92 }
      );
      doc.font("Helvetica").fontSize(10).fillColor("#475569").text(
        "Communauté de Communes Des Savanes - Direction des Services aux Usagers",
        doc.page.margins.left + 92,
        y + 40,
        { width: pageWidth - 92 }
      );
      y += 96;

      const lines = [
        ["Association", input.association?.nomAssociation || "-"],
        ["Demande", input.request.titre || `Dossier #${input.request.id}`],
        ["Commune", formData.commune || input.association?.ville || "-"],
        ["Date de restitution", formatDateFr(input.followup.restitutionDate)],
        ["Décision d'arbitrage", decisionLabel],
        ["Montant retenu", formatCurrency(input.arbitration.amountCents)],
      ] as const;

      lines.forEach(([label, value]) => {
        doc.font("Helvetica-Bold").fontSize(10).fillColor("#0f172a").text(`${label} :`, doc.page.margins.left, y, {
          width: 170,
        });
        doc.font("Helvetica").fontSize(10).fillColor("#0f172a").text(String(value || "-"), doc.page.margins.left + 170, y, {
          width: pageWidth - 170,
        });
        y += 18;
      });

      y += 8;
      doc.roundedRect(doc.page.margins.left, y, pageWidth, 88, 10).fillAndStroke("#fff7ed", "#fdba74");
      doc.font("Helvetica-Bold").fontSize(11).fillColor("#9a3412").text("Constat de terrain", doc.page.margins.left + 14, y + 12);
      doc.font("Helvetica").fontSize(10).fillColor("#7c2d12").text(
        [
          input.followup.discrepancyCategories?.length
            ? `Réserves : ${input.followup.discrepancyCategories.join(", ")}.`
            : null,
          input.followup.discrepancyDetails?.trim() || null,
        ].filter(Boolean).join(" "),
        doc.page.margins.left + 14,
        y + 32,
        { width: pageWidth - 28 }
      );
      y += 108;

      doc.font("Helvetica-Bold").fontSize(11).fillColor("#0f172a").text("Matériel provisoirement bloqué", doc.page.margins.left, y);
      y += 18;

      if (blockedRows.length === 0) {
        doc.font("Helvetica").fontSize(10).fillColor("#475569").text(
          "Aucun équipement n'est maintenu en indisponibilité après arbitrage.",
          doc.page.margins.left,
          y,
          { width: pageWidth }
        );
        y += 22;
      } else {
        blockedRows.forEach((item) => {
          doc.font("Helvetica").fontSize(10).fillColor("#0f172a").text(
            `- ${getMaterialEventLabel(item.key)} : ${item.quantity}`,
            doc.page.margins.left + 8,
            y,
            { width: pageWidth - 8 }
          );
          y += 16;
        });
      }

      if (input.arbitration.notes?.trim()) {
        y += 12;
        doc.font("Helvetica-Bold").fontSize(11).fillColor("#0f172a").text("Observations administratives", doc.page.margins.left, y);
        y += 18;
        doc.font("Helvetica").fontSize(10).fillColor("#334155").text(input.arbitration.notes.trim(), doc.page.margins.left, y, {
          width: pageWidth,
        });
        y = doc.y + 10;
      }

      doc.font("Helvetica").fontSize(9).fillColor("#64748b").text(
        `Document généré automatiquement pour le dossier #${input.request.id}.`,
        doc.page.margins.left,
        Math.max(y + 28, doc.page.height - doc.page.margins.bottom - 18),
        { width: pageWidth, align: "center" }
      );

      doc.end();
    } catch (error) {
      reject(error);
    }
  });

  return {
    buffer: pdfBuffer,
    fileName: `Courrier_Litige_${input.request.id}.pdf`,
  };
}
