import PDFDocument from "pdfkit";
import fs from "node:fs";
import path from "node:path";

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

export type MaterialContractFinancialMode = "gratuite" | "gratuite_avec_caution" | "location_payante";
export type MaterialContractStatus = "a_generer" | "generee" | "signee" | "refusee" | "annulee";

type ContractRequestLike = {
  id: number;
  titre: string;
  status: string;
  formData?: string | null;
};

type ContractAssociationLike = {
  nomAssociation?: string | null;
  adresse?: string | null;
  codePostal?: string | null;
  ville?: string | null;
  telephone?: string | null;
  emailContact?: string | null;
  nomRepresentant?: string | null;
} | null | undefined;

type ContractDecision = {
  financialMode: MaterialContractFinancialMode;
  depositRequired: boolean;
  depositAmountCents: number;
  rentalAmountCents: number;
  pricingNotes?: string | null;
  contractStatus: MaterialContractStatus;
  contractGeneratedAt?: string | Date | null;
  contractValidatedByUserId?: number | null;
};

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("[MaterialConventionPdf] 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(cents: number | null | undefined) {
  return new Intl.NumberFormat("fr-FR", { style: "currency", currency: "EUR" }).format((cents || 0) / 100);
}

function getFinancialModeLabel(mode: MaterialContractFinancialMode) {
  switch (mode) {
    case "gratuite":
      return "Mise à disposition gratuite";
    case "gratuite_avec_caution":
      return "Mise à disposition gratuite avec caution";
    case "location_payante":
      return "Location payante";
    default:
      return mode;
  }
}

export async function generateMaterialConventionPdf(input: {
  request: ContractRequestLike;
  association?: ContractAssociationLike;
  decision: ContractDecision;
}) {
  const formData = (() => {
    try {
      return input.request.formData ? JSON.parse(input.request.formData) : {};
    } catch {
      return {};
    }
  })();

  const requestedRows = Object.entries(formData.cadreDSU?.materielEvent?.itemsAccordes || {})
    .filter(([, granted]) => Boolean(granted))
    .map(([key]) => ({
      key,
      label:
        key === "tente3x3"
          ? "Tente 3x3"
          : key === "chapiteau5x5"
            ? "Chapiteau 5x5"
            : key === "podium"
              ? "Podium"
              : "Autres",
      quantity: formData.cadreDSU?.materielEvent?.quantitesAccordees?.[key] || "-",
      extra: key === "autres" ? formData.cadreDSU?.materielEvent?.autresPrecisions || "" : "",
    }));

  const manifestationStart = formData.dateDebutManifestation || formData.dateManifestation;
  const manifestationEnd = formData.dateFinManifestation || formData.dateManifestation;

  const pdfBuffer = await new Promise<Buffer>((resolve, reject) => {
    try {
      const doc = new PDFDocument({
        size: "A4",
        margins: { top: 38, bottom: 42, left: 42, right: 42 },
        info: {
          Title: `Convention matériel CCDS - dossier ${input.request.id}`,
          Author: "Communauté de Communes Des Savanes",
          Subject: "Convention de mise à disposition / location du matériel événementiel",
        },
      });

      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;

      doc.lineWidth(2).strokeColor("#efb100").moveTo(doc.page.margins.left, y).lineTo(doc.page.margins.left + pageWidth, y).stroke();
      y += 16;
      drawLogo(doc, doc.page.margins.left + (pageWidth - 84) / 2, y, 84, 84);
      y += 92;

      doc.font("Helvetica").fontSize(9).fillColor("#64748b").text("COMMUNAUTÉ DE COMMUNES DES SAVANES", doc.page.margins.left, y, {
        width: pageWidth,
        align: "center",
      });
      y += 18;
      doc.font("Helvetica-Bold").fontSize(17).fillColor("#0f172a").text(
        "CONVENTION DE MISE À DISPOSITION / LOCATION",
        doc.page.margins.left,
        y,
        { width: pageWidth, align: "center" }
      );
      y += 20;
      doc.font("Helvetica-Bold").fontSize(14).text("DU MATÉRIEL ÉVÉNEMENTIEL DE LA CCDS", doc.page.margins.left, y, {
        width: pageWidth,
        align: "center",
      });
      y += 28;

      doc.roundedRect(doc.page.margins.left, y, pageWidth, 42, 8).fillAndStroke("#eef5ff", "#bfd2ef");
      doc.font("Helvetica-Bold").fontSize(10).fillColor("#0f2d63").text(
        "Document généré à partir de la décision administrative et de l'annexe de référence CCDS",
        doc.page.margins.left + 14,
        y + 9,
        { width: pageWidth - 28, align: "center" }
      );
      doc.font("Helvetica").fontSize(9).fillColor("#334155").text(
        `Dossier #${input.request.id} — statut contrat : ${input.decision.contractStatus}`,
        doc.page.margins.left + 14,
        y + 23,
        { width: pageWidth - 28, align: "center" }
      );
      y += 56;

      const infoRows: Array<[string, string]> = [
        ["Association", input.association?.nomAssociation || formData.nomAssociation || "-"],
        ["Représentant", input.association?.nomRepresentant || formData.demandeurNomPrenom || "-"],
        ["Adresse", [input.association?.adresse, input.association?.codePostal, input.association?.ville].filter(Boolean).join(" ") || "-"],
        ["Téléphone", input.association?.telephone || formData.telephoneAssociation || "-"],
        ["Email", input.association?.emailContact || formData.emailAssociation || "-"],
        ["Commune / manifestation", formData.commune || "-"],
        [
          "Période d'utilisation",
          manifestationStart || manifestationEnd
            ? `${formatDateFr(manifestationStart)}${manifestationEnd ? ` au ${formatDateFr(manifestationEnd)}` : ""}`
            : "-",
        ],
        ["Prise en charge", formatDateFr(formData.datePriseEnCharge)],
        ["Restitution", formatDateFr(formData.dateRestitution)],
        ["Objet", formData.motifDemande || input.request.titre || "-"],
      ];

      for (const [label, value] of infoRows) {
        doc.font("Helvetica-Bold").fontSize(9).fillColor("#334155").text(`${label} :`, doc.page.margins.left, y, { width: 140 });
        doc.font("Helvetica").fontSize(10).fillColor("#0f172a").text(value, doc.page.margins.left + 145, y - 1, {
          width: pageWidth - 145,
        });
        y += 18;
      }

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

      const cols = [pageWidth * 0.56, pageWidth * 0.14, pageWidth * 0.30];
      let x = doc.page.margins.left;
      ["Équipement", "Qté", "Observation"].forEach((header, index) => {
        doc.rect(x, y, cols[index], 22).fillAndStroke("#dce8f8", "#bfd2ef");
        doc.font("Helvetica-Bold").fontSize(9).fillColor("#0f2d63").text(header, x + 6, y + 7, {
          width: cols[index] - 12,
          align: index === 0 ? "left" : "center",
        });
        x += cols[index];
      });
      y += 22;

      const rows = requestedRows.length > 0 ? requestedRows : [{ key: "none", label: "Aucun matériel accordé", quantity: "-", extra: "" }];
      rows.forEach((row) => {
        const rowHeight = row.extra ? 34 : 26;
        let rowX = doc.page.margins.left;
        [row.label, row.quantity, row.extra || "—"].forEach((value, index) => {
          doc.rect(rowX, y, cols[index], rowHeight).stroke("#cbd5e1");
          doc.font("Helvetica").fontSize(9).fillColor("#0f172a").text(String(value), rowX + 6, y + 7, {
            width: cols[index] - 12,
            align: index === 0 ? "left" : "center",
          });
          rowX += cols[index];
        });
        y += rowHeight;
      });

      y += 18;
      doc.roundedRect(doc.page.margins.left, y, pageWidth, 108, 8).fillAndStroke("#f8fafc", "#cbd5e1");
      doc.font("Helvetica-Bold").fontSize(11).fillColor("#0f172a").text("Conditions financières", doc.page.margins.left + 14, y + 12);
      doc.font("Helvetica").fontSize(10).fillColor("#334155")
        .text(`Régime retenu : ${getFinancialModeLabel(input.decision.financialMode)}`, doc.page.margins.left + 14, y + 34, {
          width: pageWidth - 28,
        })
        .text(`Montant de location : ${formatCurrency(input.decision.rentalAmountCents)}`, doc.page.margins.left + 14, y + 52, {
          width: pageWidth - 28,
        })
        .text(
          `Caution : ${input.decision.depositRequired ? formatCurrency(input.decision.depositAmountCents) : "Aucune caution exigée"}`,
          doc.page.margins.left + 14,
          y + 70,
          { width: pageWidth - 28 }
        );
      y += 122;

      if (input.decision.pricingNotes?.trim()) {
        doc.font("Helvetica-Bold").fontSize(11).fillColor("#0f172a").text("Clauses / réserves spécifiques", doc.page.margins.left, y);
        y += 16;
        doc.roundedRect(doc.page.margins.left, y, pageWidth, 70, 8).stroke("#cbd5e1");
        doc.font("Helvetica").fontSize(10).fillColor("#334155").text(input.decision.pricingNotes.trim(), doc.page.margins.left + 12, y + 12, {
          width: pageWidth - 24,
        });
        y += 84;
      }

      y += 6;
      doc.font("Helvetica").fontSize(9).fillColor("#475569").text(
        "Cette convention formalise les conditions administratives retenues par la CCDS pour la mise à disposition ou la location du matériel événementiel.",
        doc.page.margins.left,
        y,
        { width: pageWidth }
      );
      y += 34;

      const signatureWidth = (pageWidth - 20) / 2;
      doc.roundedRect(doc.page.margins.left, y, signatureWidth, 90, 8).stroke("#cbd5e1");
      doc.roundedRect(doc.page.margins.left + signatureWidth + 20, y, signatureWidth, 90, 8).stroke("#cbd5e1");
      doc.font("Helvetica-Bold").fontSize(10).fillColor("#0f172a")
        .text("Pour l'association", doc.page.margins.left + 12, y + 12, { width: signatureWidth - 24 })
        .text("Pour la CCDS / DSU", doc.page.margins.left + signatureWidth + 32, y + 12, { width: signatureWidth - 24 });
      doc.font("Helvetica").fontSize(9).fillColor("#64748b")
        .text("Nom, qualité, signature", doc.page.margins.left + 12, y + 32, { width: signatureWidth - 24 })
        .text("Nom, qualité, signature", doc.page.margins.left + signatureWidth + 32, y + 32, { width: signatureWidth - 24 });

      doc.font("Helvetica").fontSize(8).fillColor("#64748b").text(
        `Convention générée le ${formatDateFr(input.decision.contractGeneratedAt || new Date())}.`,
        doc.page.margins.left,
        doc.page.height - doc.page.margins.bottom - 12,
        { width: pageWidth, align: "center" }
      );

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

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