import PDFDocument from 'pdfkit';
import fs from 'node:fs';
import path from 'node:path';
import { SALLE_FREQUENCY_LABELS, SALLE_USAGE_TYPE_LABELS } from '@shared/sallePricing';

interface ReservationPDFData {
  titre: string;
  status: string;
  createdAt: string | Date;
  dateSubmission?: string | Date | null;
  dateTraitement?: string | Date | null;
  commentaireAdmin?: string | null;
  formData: {
    nomAssociation?: string;
    adresseAssociation?: string;
    communeSiege?: string;
    representantLegal?: string;
    telephoneAssociation?: string;
    emailAssociation?: string;
    sallesSelectionnees?: string[];
    motifReservation?: string;
    dateReservation?: string;
    dateFinReservation?: string;
    heureDebut?: string;
    heureFin?: string;
    useDetailedSchedule?: boolean;
    horairesParJour?: Array<{
      date?: string;
      heureDebut?: string;
      heureFin?: string;
    }>;
    typeUsage?: 'conventionne' | 'occasionnel';
    frequence?: 'demi_journee' | 'journee' | 'mensuel';
    nombreParticipants?: string;
    besoinsComplementaires?: string;
    materielNecessaire?: string;
    observations?: string;
    salleWorkflow?: {
      pricing?: {
        totalAmountCents?: number;
      };
      directorSignedAt?: string;
      directorSignedByName?: string;
    };
    cadreDSU?: {
      dateReception?: string;
      avisDSU?: string;
      conditionsParticulieres?: string;
      cautionRequise?: boolean;
      montantCaution?: string;
      assuranceRequise?: boolean;
      horairesImposes?: string;
      responsableDSU?: string;
      dateDecision?: string;
      observationsDSU?: string;
      materielEvent?: {
        financialDecision?: {
          financialMode?: 'gratuite' | 'gratuite_avec_caution' | 'location_payante';
          depositRequired?: boolean;
          depositAmountCents?: number;
          rentalAmountCents?: number;
          pricingNotes?: string;
          contractStatus?: 'a_generer' | 'generee' | 'signee' | 'refusee' | 'annulee';
        };
      };
    };
  };
}

interface MaterialEventPDFData {
  titre: string;
  status: string;
  createdAt: string | Date;
  dateSubmission?: string | Date | null;
  dateTraitement?: string | Date | null;
  commentaireAdmin?: string | null;
  formData: {
    nomAssociation?: string;
    adresseAssociation?: string;
    communeSiege?: string;
    representantLegal?: string;
    telephoneAssociation?: string;
    emailAssociation?: string;
    commune?: string;
    direction?: string;
    service?: string;
    demandeurNomPrenom?: string;
    dateDemande?: string;
    dateManifestation?: string;
    dateDebutManifestation?: string;
    dateFinManifestation?: string;
    motifDemande?: string;
    datePriseEnCharge?: string;
    dateRestitution?: string;
    autreMaterielPrecisions?: string;
    materielsDemandes?: Record<string, boolean>;
    quantitesDemandees?: Record<string, string>;
    cadreDSU?: {
      dateReception?: string;
      cautionRequise?: boolean;
      montantCaution?: string;
      responsableDSU?: string;
      dateDecision?: string;
      observationsDSU?: string;
      materielEvent?: {
        itemsAccordes?: Record<string, boolean>;
        quantitesAccordees?: Record<string, string>;
        autresPrecisions?: string;
        financialDecision?: {
          financialMode?: 'gratuite' | 'gratuite_avec_caution' | 'location_payante';
          depositRequired?: boolean;
          depositAmountCents?: number;
          rentalAmountCents?: number;
          pricingNotes?: string;
          contractStatus?: 'a_generer' | 'generee' | 'signee' | 'refusee' | 'annulee';
          contractGeneratedAt?: string | Date | null;
        };
      };
    };
  };
}

const statusLabels: Record<string, string> = {
  brouillon: 'Brouillon',
  soumise: 'Soumise',
  en_cours_traitement: 'En cours de traitement',
  information_complementaire: 'Information complémentaire requise',
  validee: 'Validée',
  refusee: 'Refusée',
};

const avisDSULabels: Record<string, string> = {
  favorable: 'Favorable',
  defavorable: 'Défavorable',
  favorable_avec_reserves: 'Favorable avec réserves',
};

const materialEventLabels: Record<string, string> = {
  tente3x3: 'Tente 3x3',
  chapiteau5x5: 'Chapiteau 5x5',
  podium: 'Podium',
  autres: 'Autres',
};

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

function formatDateFr(dateStr: string | Date | null | undefined): string {
  if (!dateStr) return '-';
  try {
    const d = new Date(dateStr);
    return d.toLocaleDateString('fr-FR', {
      day: 'numeric',
      month: 'long',
      year: 'numeric',
    });
  } catch {
    return String(dateStr);
  }
}

function formatCurrency(cents: number | null | undefined): string {
  if (cents === null || cents === undefined || !Number.isFinite(cents)) return '-';
  return new Intl.NumberFormat('fr-FR', { style: 'currency', currency: 'EUR' }).format(cents / 100);
}

function getFinancialModeLabel(mode: string | null | undefined): string {
  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 '-';
  }
}

function getContractStatusLabel(status: string | null | undefined): string {
  switch (status) {
    case 'a_generer':
      return 'À générer';
    case 'generee':
      return 'Générée';
    case 'signee':
      return 'Signée';
    case 'refusee':
      return 'Refusée';
    case 'annulee':
      return 'Annulée';
    default:
      return '-';
  }
}

function formatMaterialEventPeriod(formData: {
  dateManifestation?: string;
  dateDebutManifestation?: string;
  dateFinManifestation?: string;
}): string {
  const start = formData.dateDebutManifestation || formData.dateManifestation;
  const end = formData.dateFinManifestation || formData.dateManifestation;

  if (!start && !end) return '-';
  if (start && end && start !== end) {
    return `${formatDateFr(start)} au ${formatDateFr(end)}`;
  }
  return formatDateFr(start || end);
}

function drawCcdsLogo(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('[PDF] Impossible de charger le logo CCDS:', error);
  }
}

// Color definitions (RGB)
const COLORS = {
  primary: [0, 0, 102] as [number, number, number],       // oklch(0.25 0.05 265) approx
  primaryLight: [230, 230, 245] as [number, number, number],
  text: [30, 30, 30] as [number, number, number],
  muted: [120, 120, 120] as [number, number, number],
  border: [200, 200, 200] as [number, number, number],
  white: [255, 255, 255] as [number, number, number],
  green: [34, 139, 34] as [number, number, number],
  red: [220, 20, 60] as [number, number, number],
  amber: [200, 150, 0] as [number, number, number],
  blueBg: [235, 245, 255] as [number, number, number],
  blueBorder: [180, 210, 240] as [number, number, number],
  blueText: [50, 80, 140] as [number, number, number],
};

export function generateReservationPDF(data: ReservationPDFData): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    try {
      const doc = new PDFDocument({
        size: 'A4',
        margins: { top: 40, bottom: 40, left: 50, right: 50 },
        info: {
          Title: `Formulaire de Réservation - ${data.formData.nomAssociation || 'Association'}`,
          Author: 'Communauté de Communes Des Savanes',
          Subject: 'Réservation de local - Maison de la Jeunesse des Savanes',
        },
      });

      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;
      const dateDebut = formatDateFr(data.formData.dateReservation);
      const dateFin = data.formData.dateFinReservation && data.formData.dateFinReservation !== data.formData.dateReservation
        ? formatDateFr(data.formData.dateFinReservation)
        : dateDebut;
      const dailySlots = Array.isArray(data.formData.horairesParJour)
        ? data.formData.horairesParJour.filter((slot) => slot?.date)
        : [];
      const creneau = data.formData.heureDebut || data.formData.heureFin
        ? `${data.formData.heureDebut || '?'} — ${data.formData.heureFin || '?'}`
        : '-';

      doc.save();
      doc.lineWidth(2)
        .strokeColor('#f0c94b')
        .moveTo(doc.page.margins.left, y)
        .lineTo(doc.page.margins.left + pageWidth, y)
        .stroke();
      doc.restore();

      y += 16;
      drawCcdsLogo(doc, doc.page.margins.left + (pageWidth - 90) / 2, y, 90, 90);
      y += 96;
      doc.fillColor(COLORS.muted)
        .fontSize(9)
        .font('Helvetica')
        .text('COMMUNAUTÉ DE COMMUNES DES SAVANES', doc.page.margins.left, y, {
          width: pageWidth,
          align: 'center',
        });
      y += 18;
      doc.fillColor(COLORS.text)
        .fontSize(18)
        .font('Helvetica-Bold')
        .text('FORMULAIRE ADMINISTRATIF DE RÉSERVATION', doc.page.margins.left, y, {
          width: pageWidth,
          align: 'center',
        });
      y += 20;
      doc.text('D\'UN LOCAL - MAISON DE LA JEUNESSE DES SAVANES', doc.page.margins.left, y, {
        width: pageWidth,
        align: 'center',
      });
      y += 26;

      doc.save();
      doc.roundedRect(doc.page.margins.left + 18, y, pageWidth - 36, 34, 4)
        .fill('#d9eefc')
        .stroke('#f0c94b');
      doc.fillColor(COLORS.primary).fontSize(10).font('Helvetica-Bold')
        .text('Réservation à transmettre à la Direction des Services aux Usagers', doc.page.margins.left + 28, y + 7, {
          width: pageWidth - 56,
          align: 'center',
        });
      doc.fontSize(9).font('Helvetica')
        .text('Merci de compléter les informations demandées avant instruction', doc.page.margins.left + 28, y + 19, {
          width: pageWidth - 56,
          align: 'center',
        });
      doc.restore();
      y += 50;

      // Statut de la demande
      const statusLabel = statusLabels[data.status] || data.status;
      doc.fillColor(COLORS.muted)
        .fontSize(8)
        .font('Helvetica')
        .text(`Statut : ${statusLabel}  |  Créée le : ${formatDateFr(data.createdAt)}`, doc.page.margins.left, y, {
          width: pageWidth,
          align: 'right',
        });
      y += 18;

      // ==========================================
      // SECTION 1 : INFORMATIONS DE L'ASSOCIATION
      // ==========================================
      y = drawSectionTitle(doc, 'INFORMATIONS DE L\'ASSOCIATION', y, pageWidth);

      const assoRows = [
        ['Nom de l\'association', data.formData.nomAssociation || '-'],
        ['Adresse', data.formData.adresseAssociation || '-'],
        ['Commune du siège', data.formData.communeSiege || '-'],
        ['Représentant légal', data.formData.representantLegal || '-'],
        ['Téléphone', data.formData.telephoneAssociation || '-'],
        ['Email', data.formData.emailAssociation || '-'],
      ];
      y = drawTable(doc, assoRows, y, pageWidth);
      y += 15;

      // ==========================================
      // SECTION 2 : LOCAL(AUX) SOLLICITÉ(S)
      // ==========================================
      y = drawSectionTitle(doc, 'LOCAL(AUX) SOLLICITÉ(S)', y, pageWidth);

      const salles = data.formData.sallesSelectionnees?.join(', ') || '-';
      doc.fillColor(COLORS.text)
        .fontSize(10)
        .font('Helvetica')
        .text(salles, doc.page.margins.left + 5, y, { width: pageWidth - 10 });
      y += doc.heightOfString(salles, { width: pageWidth - 10 }) + 15;

      y = checkPageBreak(doc, y, 200);
      y = drawSectionTitle(doc, 'DÉTAILS DE LA RÉSERVATION', y, pageWidth);
      y = drawTable(doc, [['Motif de la réservation', data.formData.motifReservation || '-']], y, pageWidth);
      y += 8;

      const hasDetailedSchedule = Boolean(data.formData.useDetailedSchedule && dailySlots.length > 0);
      const scheduleBoxHeight = hasDetailedSchedule ? 70 + (dailySlots.length * 18) : 70;
      y = checkPageBreak(doc, y, scheduleBoxHeight + 18);
      doc.save();
      doc.roundedRect(doc.page.margins.left, y, pageWidth, scheduleBoxHeight, 4)
        .fill('#f8fafc')
        .stroke(COLORS.border);
      doc.fillColor(COLORS.primary).fontSize(10).font('Helvetica-Bold')
        .text('PÉRIODE ET CRÉNEAU SOLLICITÉS', doc.page.margins.left + 14, y + 10, { width: pageWidth - 28 });
      doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
        .text('Du', doc.page.margins.left + 14, y + 34);
      doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
        .text(dateDebut, doc.page.margins.left + 34, y + 33);
      doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
        .text('Au', doc.page.margins.left + pageWidth / 2, y + 34);
      doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
        .text(dateFin, doc.page.margins.left + pageWidth / 2 + 20, y + 33, {
          width: pageWidth / 2 - 34,
        });
      if (hasDetailedSchedule) {
        doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
          .text('Organisation', doc.page.margins.left + 14, y + 52);
        doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
          .text(`Horaires détaillés sur ${dailySlots.length} jour(s)`, doc.page.margins.left + 72, y + 51, {
            width: pageWidth - 86,
          });

        let slotY = y + 68;
        dailySlots.forEach((slot) => {
          doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
            .text(formatDateFr(slot.date || ''), doc.page.margins.left + 28, slotY);
          doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
            .text(`${slot.heureDebut || '?'} — ${slot.heureFin || '?'}`, doc.page.margins.left + 160, slotY, {
              width: pageWidth - 190,
            });
          slotY += 16;
        });
      } else {
        doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
          .text('Créneau', doc.page.margins.left + 14, y + 52);
        doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
          .text(creneau, doc.page.margins.left + 72, y + 51, {
            width: pageWidth - 86,
          });
      }
      doc.restore();
      y += scheduleBoxHeight + 12;

      const detailRows = [
        ['Nombre prévisionnel de participants', data.formData.nombreParticipants ? `${data.formData.nombreParticipants} personnes` : '-'],
        ['Type d’usage', data.formData.typeUsage ? SALLE_USAGE_TYPE_LABELS[data.formData.typeUsage] : '-'],
        ['Fréquence', data.formData.frequence ? SALLE_FREQUENCY_LABELS[data.formData.frequence] : '-'],
        ['Besoins complémentaires', data.formData.besoinsComplementaires || '-'],
        ['Matériel nécessaire', data.formData.materielNecessaire || '-'],
        ['Observations complémentaires', data.formData.observations || '-'],
        ['Montant estimatif / validé', typeof data.formData.salleWorkflow?.pricing?.totalAmountCents === 'number' ? formatCurrency(data.formData.salleWorkflow.pricing.totalAmountCents) : '-'],
      ];
      y = drawTable(doc, detailRows, y, pageWidth);
      y += 18;

      // ==========================================
      // SECTION 4 : CADRE RÉSERVÉ À LA DSU
      // ==========================================
      y = checkPageBreak(doc, y, 250);
      y = drawSectionTitle(doc, 'CADRE RÉSERVÉ À LA DIRECTION DES SERVICES AUX USAGERS (DSU)', y, pageWidth);

      const dsu = data.formData.cadreDSU;
      if (dsu) {
        const financialDecision = dsu.materielEvent?.financialDecision;
        // Avis DSU avec couleur
        if (dsu.avisDSU) {
          const avisLabel = avisDSULabels[dsu.avisDSU] || dsu.avisDSU;
          const avisColor = dsu.avisDSU === 'favorable' ? COLORS.green
            : dsu.avisDSU === 'defavorable' ? COLORS.red
            : COLORS.amber;
          
          doc.fillColor(COLORS.muted)
            .fontSize(9)
            .font('Helvetica')
            .text('Avis de la DSU : ', doc.page.margins.left + 5, y, { continued: true });
          doc.fillColor(avisColor)
            .font('Helvetica-Bold')
            .text(avisLabel);
          y += 18;
        }

        const dsuRows = [
          ['Date de réception', dsu.dateReception ? formatDateFr(dsu.dateReception) : '-'],
          ['Date de la décision', dsu.dateDecision ? formatDateFr(dsu.dateDecision) : '-'],
          ['Responsable DSU', dsu.responsableDSU || '-'],
        ];
        y = drawTable(doc, dsuRows, y, pageWidth);
        y += 10;

        // Conditions particulières
        const conditions: string[] = [];
        if (dsu.cautionRequise) {
          conditions.push(`Caution requise${dsu.montantCaution ? ` : ${dsu.montantCaution} €` : ''}`);
        }
        if (dsu.assuranceRequise) {
          conditions.push('Attestation d\'assurance requise');
        }
        if (dsu.horairesImposes) {
          conditions.push(`Horaires imposés : ${dsu.horairesImposes}`);
        }
        if (dsu.conditionsParticulieres) {
          conditions.push(dsu.conditionsParticulieres);
        }

        if (conditions.length > 0) {
          y = checkPageBreak(doc, y, 80);
          doc.fillColor(COLORS.primary)
            .fontSize(9)
            .font('Helvetica-Bold')
            .text('Conditions particulières :', doc.page.margins.left + 5, y);
          y += 14;

          for (const condition of conditions) {
            y = checkPageBreak(doc, y, 20);
            doc.fillColor(COLORS.text)
              .fontSize(9)
              .font('Helvetica')
              .text(`• ${condition}`, doc.page.margins.left + 15, y, { width: pageWidth - 25 });
            y += doc.heightOfString(`• ${condition}`, { width: pageWidth - 25 }) + 4;
          }
          y += 5;
        }

        if (financialDecision?.financialMode) {
          y = checkPageBreak(doc, y, 96);
          doc.fillColor(COLORS.primary)
            .fontSize(9)
            .font('Helvetica-Bold')
            .text('Conditions financières / location :', doc.page.margins.left + 5, y);
          y += 14;

          const financialRows = [
            ['Mode financier', getFinancialModeLabel(financialDecision.financialMode)],
            ['Caution / dépôt', financialDecision.depositRequired ? formatCurrency(financialDecision.depositAmountCents ?? 0) : 'Aucune'],
            ['Montant de location', financialDecision.financialMode === 'location_payante' ? formatCurrency(financialDecision.rentalAmountCents ?? 0) : 'Non applicable'],
            ['Statut de la convention', getContractStatusLabel(financialDecision.contractStatus)],
          ];
          y = drawTable(doc, financialRows, y, pageWidth);
          y += 8;

          if (financialDecision.pricingNotes) {
            y = checkPageBreak(doc, y, 50);
            doc.fillColor(COLORS.primary)
              .fontSize(9)
              .font('Helvetica-Bold')
              .text('Clauses spécifiques :', doc.page.margins.left + 5, y);
            y += 14;
            doc.fillColor(COLORS.text)
              .fontSize(9)
              .font('Helvetica')
              .text(financialDecision.pricingNotes, doc.page.margins.left + 15, y, { width: pageWidth - 25 });
            y += doc.heightOfString(financialDecision.pricingNotes, { width: pageWidth - 25 }) + 10;
          }
        }

        // Observations DSU
        if (dsu.observationsDSU) {
          y = checkPageBreak(doc, y, 50);
          doc.fillColor(COLORS.primary)
            .fontSize(9)
            .font('Helvetica-Bold')
            .text('Observations de la DSU :', doc.page.margins.left + 5, y);
          y += 14;
          doc.fillColor(COLORS.text)
            .fontSize(9)
            .font('Helvetica')
            .text(dsu.observationsDSU, doc.page.margins.left + 15, y, { width: pageWidth - 25 });
          y += doc.heightOfString(dsu.observationsDSU, { width: pageWidth - 25 }) + 10;
        }
      } else {
        // Cadre vide avec lignes pointillées
        const emptyRows = [
          ['Date de réception', ''],
          ['Avis', ''],
          ['Conditions particulières', ''],
          ['Responsable DSU', ''],
          ['Date de la décision', ''],
          ['Observations', ''],
        ];
        y = drawTable(doc, emptyRows, y, pageWidth, true);
      }

      y += 18;
      y = checkPageBreak(doc, y, 80);
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .moveTo(doc.page.margins.left + 10, y + 28)
        .lineTo(doc.page.margins.left + pageWidth / 2 - 20, y + 28)
        .stroke();
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .moveTo(doc.page.margins.left + pageWidth / 2 + 20, y + 28)
        .lineTo(doc.page.margins.left + pageWidth - 10, y + 28)
        .stroke();
      doc.fillColor(COLORS.text).fontSize(9).font('Helvetica')
        .text('Signature du représentant de l\'association', doc.page.margins.left + 10, y + 34, {
          width: pageWidth / 2 - 30,
          align: 'center',
        })
        .text('Visa de la DSU', doc.page.margins.left + pageWidth / 2 + 20, y + 34, {
          width: pageWidth / 2 - 30,
          align: 'center',
        });

      const directorSignedAt = data.formData.salleWorkflow?.directorSignedAt;
      const directorSignedByName = data.formData.salleWorkflow?.directorSignedByName;
      if (directorSignedAt) {
        doc.fillColor(COLORS.blueText).fontSize(8).font('Helvetica-Bold')
          .text('Validé électroniquement', doc.page.margins.left + pageWidth / 2 + 20, y + 49, {
            width: pageWidth / 2 - 30,
            align: 'center',
          });
        doc.fillColor(COLORS.text).fontSize(8).font('Helvetica')
          .text(
            `${formatDateFr(directorSignedAt)}${directorSignedByName ? ` · ${directorSignedByName}` : ''}`,
            doc.page.margins.left + pageWidth / 2 + 20,
            y + 61,
            {
              width: pageWidth / 2 - 30,
              align: 'center',
            }
          );
      }

      // ==========================================
      // COMMENTAIRE ADMIN (si présent)
      // ==========================================
      if (data.commentaireAdmin) {
        y = checkPageBreak(doc, y, 60);
        y += 10;
        doc.fillColor(COLORS.primary)
          .fontSize(9)
          .font('Helvetica-Bold')
          .text('Commentaire de l\'administration :', doc.page.margins.left + 5, y);
        y += 14;
        doc.fillColor(COLORS.text)
          .fontSize(9)
          .font('Helvetica')
          .text(data.commentaireAdmin, doc.page.margins.left + 15, y, { width: pageWidth - 25 });
        y += doc.heightOfString(data.commentaireAdmin, { width: pageWidth - 25 }) + 10;
      }

      // ==========================================
      // PIED DE PAGE
      // ==========================================
      const footerY = doc.page.height - doc.page.margins.bottom - 30;
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .moveTo(doc.page.margins.left, footerY)
        .lineTo(doc.page.margins.left + pageWidth, footerY)
        .stroke();

      doc.fillColor(COLORS.muted)
        .fontSize(7)
        .font('Helvetica')
        .text(
          `Document généré le ${formatDateFr(new Date())} — Communauté de Communes Des Savanes — Direction des Services aux Usagers`,
          doc.page.margins.left,
          footerY + 8,
          { width: pageWidth, align: 'center' }
        );

      if (directorSignedAt) {
        doc.text(
          `Visa Direction enregistré le ${formatDateFr(directorSignedAt)}${directorSignedByName ? ` par ${directorSignedByName}` : ''}`,
          doc.page.margins.left,
          footerY + 18,
          { width: pageWidth, align: 'center' }
        );
      }

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

export function generateMaterialEventPDF(data: MaterialEventPDFData): Promise<Buffer> {
  return new Promise((resolve, reject) => {
    try {
      const doc = new PDFDocument({
        size: 'A4',
        margins: { top: 40, bottom: 40, left: 50, right: 50 },
        info: {
          Title: `Demande matériel - ${data.formData.nomAssociation || data.formData.commune || 'Association'}`,
          Author: 'Communauté de Communes Des Savanes',
          Subject: 'Demande de mise à disposition 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;
      const manifestationStart = data.formData.dateDebutManifestation || data.formData.dateManifestation;
      const manifestationEnd = data.formData.dateFinManifestation || data.formData.dateManifestation;

      doc.save();
      doc.lineWidth(2)
        .strokeColor('#f0c94b')
        .moveTo(doc.page.margins.left, y)
        .lineTo(doc.page.margins.left + pageWidth, y)
        .stroke();
      doc.restore();

      y += 16;
      drawCcdsLogo(doc, doc.page.margins.left + (pageWidth - 90) / 2, y, 90, 90);
      y += 96;
      doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
        .text('COMMUNAUTÉ DE COMMUNES DES SAVANES', doc.page.margins.left, y, { width: pageWidth, align: 'center' });
      y += 18;
      doc.fillColor(COLORS.text).fontSize(18).font('Helvetica-Bold')
        .text('FICHE DE DEMANDE DE MISE À DISPOSITION', doc.page.margins.left, y, { width: pageWidth, align: 'center' });
      y += 20;
      doc.text('DU MATÉRIEL ÉVÉNEMENTIEL', doc.page.margins.left, y, { width: pageWidth, align: 'center' });
      y += 26;

      doc.save();
      doc.roundedRect(doc.page.margins.left + 18, y, pageWidth - 36, 34, 4)
        .fill('#d9eefc')
        .stroke('#f0c94b');
      doc.fillColor(COLORS.primary).fontSize(10).font('Helvetica-Bold')
        .text('Fiche à remplir obligatoirement (1 mois avant la manifestation)', doc.page.margins.left + 28, y + 7, {
          width: pageWidth - 56,
          align: 'center',
        });
      doc.fontSize(9).font('Helvetica')
        .text('À transmettre à la Direction des Services aux Usagers', doc.page.margins.left + 28, y + 19, {
          width: pageWidth - 56,
          align: 'center',
        });
      doc.restore();
      y += 50;

      const statusLabel = statusLabels[data.status] || data.status;
      doc.fillColor(COLORS.muted).fontSize(8).font('Helvetica')
        .text(`Statut : ${statusLabel}  |  Créée le : ${formatDateFr(data.createdAt)}`, doc.page.margins.left, y, {
          width: pageWidth,
          align: 'right',
        });
      y += 18;

      y = drawSectionTitle(doc, 'INFORMATIONS DU DEMANDEUR', y, pageWidth);
      y = drawTable(doc, [
        ['Association', data.formData.nomAssociation || '-'],
        ['Commune', data.formData.commune || data.formData.communeSiege || '-'],
        ['Direction', data.formData.direction || '-'],
        ['Service', data.formData.service || '-'],
        ['Nom et prénom du demandeur', data.formData.demandeurNomPrenom || '-'],
        ['Téléphone', data.formData.telephoneAssociation || '-'],
        ['Email', data.formData.emailAssociation || '-'],
      ], y, pageWidth);
      y += 15;

      y = drawSectionTitle(doc, 'MATÉRIEL DEMANDÉ', y, pageWidth);
      const requestedRows = Object.entries(materialEventLabels)
        .filter(([key]) => data.formData.materielsDemandes?.[key])
        .map(([key, label]) => [
          label,
          `${data.formData.quantitesDemandees?.[key] || '-'}${key === 'autres' && data.formData.autreMaterielPrecisions ? ` — ${data.formData.autreMaterielPrecisions}` : ''}`,
        ]);
      y = drawTable(doc, requestedRows.length > 0 ? requestedRows : [['Aucun matériel demandé', '-']], y, pageWidth);
      y += 15;

      y = drawSectionTitle(doc, 'DÉTAILS DE LA DEMANDE', y, pageWidth);
      y = drawTable(doc, [['Date de la demande', formatDateFr(data.formData.dateDemande)]], y, pageWidth);
      y += 8;

      y = checkPageBreak(doc, y, 88);
      doc.save();
      doc.roundedRect(doc.page.margins.left, y, pageWidth, 70, 4)
        .fill('#f8fafc')
        .stroke(COLORS.border);
      doc.fillColor(COLORS.primary).fontSize(10).font('Helvetica-Bold')
        .text('PÉRIODE DE LA MANIFESTATION', doc.page.margins.left + 14, y + 10, { width: pageWidth - 28 });
      doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
        .text('Du', doc.page.margins.left + 14, y + 34);
      doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
        .text(formatDateFr(manifestationStart), doc.page.margins.left + 34, y + 33);
      doc.fillColor(COLORS.muted).fontSize(9).font('Helvetica')
        .text('Au', doc.page.margins.left + pageWidth / 2, y + 34);
      doc.fillColor(COLORS.text).fontSize(10).font('Helvetica-Bold')
        .text(formatDateFr(manifestationEnd), doc.page.margins.left + pageWidth / 2 + 20, y + 33, {
          width: pageWidth / 2 - 34,
        });
      doc.restore();
      y += 82;

      y = drawTable(doc, [
        ['Date prévisionnelle de prise en charge du matériel', formatDateFr(data.formData.datePriseEnCharge)],
        ['Date prévisionnelle de restitution', formatDateFr(data.formData.dateRestitution)],
        ['Motif de la demande', data.formData.motifDemande || '-'],
      ], y, pageWidth);
      y += 18;

      y = checkPageBreak(doc, y, 220);
      y = drawSectionTitle(doc, 'CADRE RÉSERVÉ À LA DSU', y, pageWidth);
      const dsu = data.formData.cadreDSU;
      if (dsu) {
        y = drawTable(doc, [
          ['Date de réception', formatDateFr(dsu.dateReception)],
          ['Date de la décision', formatDateFr(dsu.dateDecision)],
          ['Responsable DSU', dsu.responsableDSU || '-'],
        ], y, pageWidth);
        y += 10;

        const grantedRows = Object.entries(materialEventLabels).map(([key, label]) => {
          const granted = dsu.materielEvent?.itemsAccordes?.[key];
          const qty = dsu.materielEvent?.quantitesAccordees?.[key];
          const extra = key === 'autres' ? dsu.materielEvent?.autresPrecisions : '';
          return [label, granted ? `${qty || '-'} accordé(s)${extra ? ` — ${extra}` : ''}` : (data.status === 'refusee' ? 'Refusé' : 'Non renseigné')];
        });
        y = drawTable(doc, grantedRows, y, pageWidth);

        const financialDecision = dsu.materielEvent?.financialDecision;
        if (financialDecision?.financialMode) {
          y += 12;
          y = checkPageBreak(doc, y, 120);
          doc.fillColor(COLORS.primary).fontSize(9).font('Helvetica-Bold')
            .text('Conditions financières / convention :', doc.page.margins.left + 5, y);
          y += 14;

          const financialRows = [
            ['Mode financier', getFinancialModeLabel(financialDecision.financialMode)],
            ['Caution / dépôt de garantie', financialDecision.depositRequired ? formatCurrency(financialDecision.depositAmountCents ?? 0) : 'Aucune'],
            ['Montant de location', financialDecision.financialMode === 'location_payante' ? formatCurrency(financialDecision.rentalAmountCents ?? 0) : 'Non applicable'],
            ['Statut de la convention', getContractStatusLabel(financialDecision.contractStatus)],
            ['Convention générée le', formatDateFr(financialDecision.contractGeneratedAt)],
          ];
          y = drawTable(doc, financialRows, y, pageWidth);

          if (financialDecision.pricingNotes) {
            y += 10;
            doc.fillColor(COLORS.primary).fontSize(9).font('Helvetica-Bold')
              .text('Clauses spécifiques :', doc.page.margins.left + 5, y);
            y += 14;
            doc.fillColor(COLORS.text).fontSize(9).font('Helvetica')
              .text(financialDecision.pricingNotes, doc.page.margins.left + 5, y, { width: pageWidth - 10 });
            y += doc.heightOfString(financialDecision.pricingNotes, { width: pageWidth - 10 }) + 6;
          }
        }

        if (dsu.observationsDSU) {
          y += 12;
          doc.fillColor(COLORS.primary).fontSize(9).font('Helvetica-Bold')
            .text('Observations de la DSU :', doc.page.margins.left + 5, y);
          y += 14;
          doc.fillColor(COLORS.text).fontSize(9).font('Helvetica')
            .text(dsu.observationsDSU, doc.page.margins.left + 5, y, { width: pageWidth - 10 });
        }
      } else {
        doc.fillColor(COLORS.muted).fontSize(10).font('Helvetica-Oblique')
          .text('Cadre DSU non encore renseigné.', doc.page.margins.left + 5, y);
      }

      y += 18;
      y = checkPageBreak(doc, y, 80);
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .moveTo(doc.page.margins.left + 10, y + 28)
        .lineTo(doc.page.margins.left + pageWidth / 2 - 20, y + 28)
        .stroke();
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .moveTo(doc.page.margins.left + pageWidth / 2 + 20, y + 28)
        .lineTo(doc.page.margins.left + pageWidth - 10, y + 28)
        .stroke();
      doc.fillColor(COLORS.text).fontSize(9).font('Helvetica')
        .text('Signature du DGS de la commune', doc.page.margins.left + 10, y + 34, {
          width: pageWidth / 2 - 30,
          align: 'center',
        })
        .text('Signature de la DSU', doc.page.margins.left + pageWidth / 2 + 20, y + 34, {
          width: pageWidth / 2 - 30,
          align: 'center',
        });

      const footerY = doc.page.height - doc.page.margins.bottom - 30;
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .moveTo(doc.page.margins.left, footerY)
        .lineTo(doc.page.margins.left + pageWidth, footerY)
        .stroke();

      doc.fillColor(COLORS.muted)
        .fontSize(7)
        .font('Helvetica')
        .text(
          `Document généré le ${formatDateFr(new Date())} — Communauté de Communes Des Savanes — Direction des Services aux Usagers`,
          doc.page.margins.left,
          footerY + 8,
          { width: pageWidth, align: 'center' }
        );

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

// ==========================================
// HELPER FUNCTIONS
// ==========================================

function drawSectionTitle(doc: PDFKit.PDFDocument, title: string, y: number, pageWidth: number): number {
  const leftMargin = (doc as any).page.margins.left;
  
  // Background bar
  doc.save();
  doc.rect(leftMargin - 5, y, pageWidth + 10, 20)
    .fill(COLORS.primaryLight);
  
  doc.fillColor(COLORS.primary)
    .fontSize(9)
    .font('Helvetica-Bold')
    .text(title, leftMargin + 5, y + 5, { width: pageWidth });
  
  doc.restore();
  return y + 28;
}

function drawTable(doc: PDFKit.PDFDocument, rows: string[][], y: number, pageWidth: number, emptyStyle: boolean = false): number {
  const leftMargin = (doc as any).page.margins.left;
  const labelWidth = pageWidth * 0.4;
  const valueWidth = pageWidth * 0.6;
  const rowPadding = 5;

  for (const [label, value] of rows) {
    y = checkPageBreak(doc, y, 20);
    
    // Label
    doc.fillColor(COLORS.muted)
      .fontSize(9)
      .font('Helvetica')
      .text(label + ' :', leftMargin + rowPadding, y, {
        width: labelWidth - rowPadding * 2,
      });

    // Value
    if (emptyStyle && !value) {
      // Draw dotted line for empty fields
      doc.strokeColor(COLORS.border)
        .lineWidth(0.5)
        .dash(3, { space: 2 })
        .moveTo(leftMargin + labelWidth + 5, y + 10)
        .lineTo(leftMargin + pageWidth - 5, y + 10)
        .stroke()
        .undash();
    } else {
      doc.fillColor(COLORS.text)
        .fontSize(9)
        .font('Helvetica-Bold')
        .text(value || '-', leftMargin + labelWidth, y, {
          width: valueWidth - rowPadding,
          align: 'right',
        });
    }

    // Calculate the height used
    const labelH = doc.heightOfString(label + ' :', { width: labelWidth - rowPadding * 2 });
    const valueH = value ? doc.heightOfString(value, { width: valueWidth - rowPadding }) : 12;
    const rowHeight = Math.max(labelH, valueH) + 4;

    y += rowHeight;

    // Separator line
    doc.strokeColor(COLORS.border)
      .lineWidth(0.3)
      .dash(1, { space: 2 })
      .moveTo(leftMargin + 5, y)
      .lineTo(leftMargin + pageWidth - 5, y)
      .stroke()
      .undash();
    
    y += 4;
  }

  return y;
}

function checkPageBreak(doc: PDFKit.PDFDocument, y: number, requiredSpace: number): number {
  const pageBottom = doc.page.height - doc.page.margins.bottom - 40;
  if (y + requiredSpace > pageBottom) {
    doc.addPage();
    return doc.page.margins.top;
  }
  return y;
}
