package sn.ladoum.bergerie.pdf;

import com.lowagie.text.*;
import com.lowagie.text.pdf.ColumnText;
import com.lowagie.text.pdf.PdfContentByte;
import com.lowagie.text.pdf.PdfPCell;
import com.lowagie.text.pdf.PdfPTable;
import com.lowagie.text.pdf.PdfPageEventHelper;
import com.lowagie.text.pdf.PdfWriter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.io.ClassPathResource;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import sn.ladoum.bergerie.entity.Mouton;
import sn.ladoum.bergerie.entity.Utilisateur;
import sn.ladoum.bergerie.exception.ResourceNotFoundException;
import sn.ladoum.bergerie.repository.MoutonRepository;
import sn.ladoum.bergerie.repository.UtilisateurRepository;
import sn.ladoum.bergerie.service.MoutonService;

import java.awt.Color;
import java.io.ByteArrayOutputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.Locale;

@Service
@RequiredArgsConstructor
@Slf4j
public class ExtraitNaissanceService {

    private static final DateTimeFormatter DATE_FMT = DateTimeFormatter.ofPattern("d MMMM yyyy", Locale.FRENCH);
    private static final DateTimeFormatter DATE_COURT = DateTimeFormatter.ofPattern("dd/MM/yyyy");

    private static final Color VERT       = new Color(45, 82, 52);
    private static final Color VERT_CLAIR = new Color(241, 247, 242);
    private static final Color OR         = new Color(198, 144, 32);
    private static final Color OR_CLAIR   = new Color(252, 249, 237);
    private static final Color BEIGE      = new Color(250, 247, 240);
    private static final Color TEXTE      = new Color(30, 35, 31);
    private static final Color GRIS       = new Color(120, 120, 120);
    private static final Color GRIS_CLAIR = new Color(220, 220, 220);

    private final MoutonRepository moutonRepository;
    private final UtilisateurRepository utilisateurRepository;
    private final MoutonService moutonService;

    @Value("${app.storage.location}")
    private String storageLocation;

    @Value("${app.storage.public-base-url}")
    private String publicBaseUrl;

    private Utilisateur currentUser() {
        Authentication auth = SecurityContextHolder.getContext().getAuthentication();
        if (auth == null || !auth.isAuthenticated()) return null;
        String email = auth.getName();
        if (email == null || "anonymousUser".equals(email)) return null;
        return utilisateurRepository.findByEmail(email).orElse(null);
    }

    @Transactional(readOnly = true)
    public byte[] genererExtrait(Long moutonId) {
        Mouton mouton = moutonRepository.findById(moutonId)
                .orElseThrow(() -> ResourceNotFoundException.of("Mouton", moutonId));
        moutonService.checkAccess(mouton);

        // Éleveur : celui du mouton, sinon l'utilisateur connecté
        Utilisateur eleveur = mouton.getEleveur();
        if (eleveur == null) {
            eleveur = currentUser();
        }
        // Initialisation explicite des associations LAZY avant la construction du PDF
        if (eleveur != null) eleveur.getNom();
        if (mouton.getPere() != null) mouton.getPere().getNom();
        if (mouton.getMere() != null) mouton.getMere().getNom();

        String nomBergerie = resoudreNomBergerie(eleveur);

        try (ByteArrayOutputStream out = new ByteArrayOutputStream()) {
            Document doc = new Document(PageSize.A4, 36, 36, 36, 50);
            PdfWriter writer = PdfWriter.getInstance(doc, out);
            writer.setPageEvent(new CadrePageEvent(nomBergerie));
            doc.open();

            doc.add(bandeauLadoumTrack());
            doc.add(banniere(eleveur, nomBergerie));
            doc.add(espaceVertical(12));
            doc.add(titre());
            doc.add(espaceVertical(10));
            doc.add(identiteBadges(mouton));
            doc.add(espaceVertical(12));
            doc.add(photoEtCaracteristiques(mouton));
            doc.add(espaceVertical(12));
            doc.add(lignee(mouton));
            doc.add(espaceVertical(12));
            doc.add(proprietaire(eleveur));
            doc.add(espaceVertical(16));
            doc.add(signatureEtDate(nomBergerie));

            doc.close();
            return out.toByteArray();
        } catch (Exception e) {
            log.error("Erreur génération PDF pour mouton #{}", moutonId, e);
            throw new IllegalStateException("Erreur génération PDF: " + e.getMessage(), e);
        }
    }

    private String resoudreNomBergerie(Utilisateur e) {
        if (e != null && e.getNomBergerie() != null && !e.getNomBergerie().isBlank()) {
            return e.getNomBergerie();
        }
        return "Bergerie";
    }

    @Transactional(readOnly = true)
    public String nomFichier(Long moutonId) {
        Mouton m = moutonRepository.findById(moutonId)
                .orElseThrow(() -> ResourceNotFoundException.of("Mouton", moutonId));
        moutonService.checkAccess(m);
        return "extrait-naissance-" + m.getNom().replaceAll("\\s+", "-") + "-" + m.getId() + ".pdf";
    }

    // ------------------------------------------------------------ Bannière

    /** Petit bandeau haut de page avec le logo Ladoum Track SN et la tagline plateforme. */
    private PdfPTable bandeauLadoumTrack() {
        PdfPTable t = new PdfPTable(3);
        t.setWidthPercentage(100);
        setWidths(t, 0.4f, 4f, 2f);

        // Logo Ladoum Track SN (classpath)
        PdfPCell logoCell = new PdfPCell();
        logoCell.setBorder(Rectangle.NO_BORDER);
        logoCell.setPadding(4);
        logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        logoCell.setHorizontalAlignment(Element.ALIGN_CENTER);
        Image logo = chargerLogoLadoumTrack(28f);
        if (logo != null) {
            Paragraph p = new Paragraph();
            p.setAlignment(Element.ALIGN_CENTER);
            p.add(new Chunk(logo, 0, 0, true));
            logoCell.addElement(p);
        }
        t.addCell(logoCell);

        // Nom + tagline
        PdfPCell nomCell = new PdfPCell();
        nomCell.setBorder(Rectangle.NO_BORDER);
        nomCell.setPadding(4);
        nomCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        Paragraph pNom = new Paragraph("Ladoum Track SN",
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 11, VERT));
        Paragraph pTag = new Paragraph("Suivre · Tracer · Valoriser",
                FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 8, GRIS));
        nomCell.addElement(pNom);
        nomCell.addElement(pTag);
        t.addCell(nomCell);

        // Mention "Plateforme officielle"
        PdfPCell mentionCell = new PdfPCell();
        mentionCell.setBorder(Rectangle.NO_BORDER);
        mentionCell.setPadding(4);
        mentionCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        mentionCell.setHorizontalAlignment(Element.ALIGN_RIGHT);
        Paragraph pM = new Paragraph("Plateforme officielle",
                FontFactory.getFont(FontFactory.HELVETICA, 8, GRIS));
        pM.setAlignment(Element.ALIGN_RIGHT);
        Paragraph pM2 = new Paragraph("de traçabilité Ladoum",
                FontFactory.getFont(FontFactory.HELVETICA, 8, GRIS));
        pM2.setAlignment(Element.ALIGN_RIGHT);
        mentionCell.addElement(pM);
        mentionCell.addElement(pM2);
        t.addCell(mentionCell);

        // Liseré fin vert sous le bandeau
        PdfPCell sep = new PdfPCell(new Phrase(" "));
        sep.setColspan(3);
        sep.setBackgroundColor(VERT);
        sep.setFixedHeight(2);
        sep.setBorder(Rectangle.NO_BORDER);
        t.addCell(sep);

        return t;
    }

    /** Charge le logo Ladoum Track SN depuis le classpath (src/main/resources/logos). */
    private Image chargerLogoLadoumTrack(float maxH) {
        try {
            ClassPathResource res = new ClassPathResource("logos/ladoum-track-icon.png");
            if (!res.exists()) return null;
            try (java.io.InputStream in = res.getInputStream()) {
                byte[] bytes = in.readAllBytes();
                Image img = Image.getInstance(bytes);
                img.scaleToFit(maxH, maxH);
                return img;
            }
        } catch (Exception e) {
            log.warn("Impossible de charger le logo Ladoum Track SN : {}", e.getMessage());
            return null;
        }
    }

    private PdfPTable banniere(Utilisateur eleveur, String nomBergerie) {
        PdfPTable t = new PdfPTable(2);
        t.setWidthPercentage(100);
        setWidths(t, 1f, 4f);

        // Logo
        PdfPCell logoCell = new PdfPCell();
        logoCell.setBackgroundColor(VERT);
        logoCell.setBorder(Rectangle.NO_BORDER);
        logoCell.setPadding(20);
        logoCell.setVerticalAlignment(Element.ALIGN_MIDDLE);
        logoCell.setHorizontalAlignment(Element.ALIGN_CENTER);

        Image logo = chargerImage(eleveur != null ? eleveur.getLogo() : null, 70f, 70f);
        if (logo != null) {
            Paragraph p = new Paragraph();
            p.setAlignment(Element.ALIGN_CENTER);
            p.add(new Chunk(logo, 0, 0, true));
            logoCell.addElement(p);
        } else {
            Font f = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 36, OR);
            Paragraph p = new Paragraph("L", f);
            p.setAlignment(Element.ALIGN_CENTER);
            logoCell.addElement(p);
        }
        t.addCell(logoCell);

        // Bloc texte
        PdfPCell texte = new PdfPCell();
        texte.setBackgroundColor(VERT);
        texte.setBorder(Rectangle.NO_BORDER);
        texte.setPadding(20);
        texte.setVerticalAlignment(Element.ALIGN_MIDDLE);

        Paragraph pNom = new Paragraph(nomBergerie,
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 22, Color.WHITE));
        texte.addElement(pNom);

        Paragraph pTag = new Paragraph("Filière Ladoum  •  République du Sénégal",
                FontFactory.getFont(FontFactory.HELVETICA, 10, new Color(220, 235, 222)));
        pTag.setSpacingBefore(2);
        texte.addElement(pTag);

        if (eleveur != null) {
            String contact = contactLigne(eleveur);
            if (!contact.isEmpty()) {
                Paragraph pContact = new Paragraph(contact,
                        FontFactory.getFont(FontFactory.HELVETICA, 9, new Color(220, 235, 222)));
                pContact.setSpacingBefore(8);
                texte.addElement(pContact);
            }
        }
        t.addCell(texte);

        // Liseré or
        PdfPCell liseré = new PdfPCell(new Phrase(" "));
        liseré.setColspan(2);
        liseré.setBackgroundColor(OR);
        liseré.setFixedHeight(4);
        liseré.setBorder(Rectangle.NO_BORDER);
        t.addCell(liseré);

        return t;
    }

    private String contactLigne(Utilisateur e) {
        StringBuilder sb = new StringBuilder();
        if (e.getAdresse() != null && !e.getAdresse().isBlank()) sb.append(e.getAdresse());
        if (e.getTelephone() != null && !e.getTelephone().isBlank()) {
            if (sb.length() > 0) sb.append("  •  ");
            sb.append("Tél : ").append(e.getTelephone());
        }
        return sb.toString();
    }

    // ------------------------------------------------------------ Titre

    private PdfPTable titre() {
        PdfPTable t = new PdfPTable(1);
        t.setWidthPercentage(100);

        PdfPCell c = new PdfPCell();
        c.setBorder(Rectangle.NO_BORDER);
        c.setHorizontalAlignment(Element.ALIGN_CENTER);

        Paragraph p1 = new Paragraph("EXTRAIT DE NAISSANCE",
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 26, VERT));
        p1.setAlignment(Element.ALIGN_CENTER);
        c.addElement(p1);

        Paragraph p2 = new Paragraph("Document officiel d'enregistrement zootechnique",
                FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 10, GRIS));
        p2.setAlignment(Element.ALIGN_CENTER);
        p2.setSpacingBefore(4);
        c.addElement(p2);

        t.addCell(c);
        return t;
    }

    // ------------------------------------------------------------ Identité (badges)

    private PdfPTable identiteBadges(Mouton m) {
        PdfPTable t = new PdfPTable(2);
        t.setWidthPercentage(100);
        setWidths(t, 2.5f, 1f);

        PdfPCell nom = new PdfPCell();
        nom.setBackgroundColor(VERT_CLAIR);
        nom.setBorder(Rectangle.NO_BORDER);
        nom.setPadding(16);
        nom.addElement(new Paragraph("NOM DU SUJET",
                FontFactory.getFont(FontFactory.HELVETICA, 9, GRIS)));
        Paragraph pNom = new Paragraph(safe(m.getNom()),
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 22, VERT));
        pNom.setSpacingBefore(2);
        nom.addElement(pNom);
        t.addCell(nom);

        PdfPCell id = new PdfPCell();
        id.setBackgroundColor(OR_CLAIR);
        id.setBorder(Rectangle.NO_BORDER);
        id.setPadding(16);
        Paragraph pLab = new Paragraph("N° D'IDENTIFICATION",
                FontFactory.getFont(FontFactory.HELVETICA, 9, new Color(140, 100, 25)));
        pLab.setAlignment(Element.ALIGN_CENTER);
        id.addElement(pLab);
        String numero = (m.getNumeroIdentification() != null && !m.getNumeroIdentification().isBlank())
                ? m.getNumeroIdentification()
                : "#" + m.getId();
        Paragraph pId = new Paragraph(numero,
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 20, OR));
        pId.setAlignment(Element.ALIGN_CENTER);
        pId.setSpacingBefore(2);
        id.addElement(pId);
        t.addCell(id);

        return t;
    }

    // ------------------------------------------------------------ Photo + caractéristiques

    private PdfPTable photoEtCaracteristiques(Mouton m) {
        PdfPTable t = new PdfPTable(2);
        t.setWidthPercentage(100);
        setWidths(t, 1f, 1.6f);

        // Photo
        PdfPCell photo = new PdfPCell();
        photo.setBorder(Rectangle.BOX);
        photo.setBorderColor(VERT_CLAIR);
        photo.setBorderWidth(1.5f);
        photo.setBackgroundColor(VERT_CLAIR);
        photo.setPadding(10);
        photo.setMinimumHeight(220);
        photo.setHorizontalAlignment(Element.ALIGN_CENTER);
        photo.setVerticalAlignment(Element.ALIGN_MIDDLE);

        Image img = chargerImage(m.getPhoto(), 180f, 200f);
        if (img != null) {
            Paragraph p = new Paragraph();
            p.setAlignment(Element.ALIGN_CENTER);
            p.add(new Chunk(img, 0, 0, true));
            photo.addElement(p);
        } else {
            Paragraph p = new Paragraph("Photographie non fournie",
                    FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 10, GRIS));
            p.setAlignment(Element.ALIGN_CENTER);
            photo.addElement(p);
        }
        t.addCell(photo);

        // Caractéristiques
        PdfPCell infos = new PdfPCell();
        infos.setBorder(Rectangle.NO_BORDER);
        infos.setPaddingLeft(14);
        infos.setPaddingRight(0);
        infos.setPaddingTop(0);
        infos.setPaddingBottom(0);

        Paragraph titre = new Paragraph("CARACTÉRISTIQUES",
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 11, VERT));
        titre.setSpacingAfter(6);
        infos.addElement(titre);

        PdfPTable det = new PdfPTable(2);
        det.setWidthPercentage(100);
        setWidths(det, 1f, 1.6f);
        det.getDefaultCell().setBorder(Rectangle.NO_BORDER);

        ajouterLigne(det, "Sexe", sexeLisible(m));
        ajouterLigne(det, "Date de naissance",
                m.getDateNaissance() != null ? m.getDateNaissance().format(DATE_FMT) : "—");
        ajouterLigne(det, "Date d'entrée système",
                m.getDateEntreeSysteme() != null ? m.getDateEntreeSysteme().format(DATE_FMT) : "—");
        ajouterLigne(det, "Race", m.getRace() != null ? m.getRace() : "Ladoum");
        ajouterLigne(det, "Couleur", safe(m.getCouleur()));
        ajouterLigne(det, "Statut", statutLisible(m));
        if (m.getCaracteristiques() != null && !m.getCaracteristiques().isBlank()) {
            ajouterLigne(det, "Particularités", m.getCaracteristiques());
        }

        infos.addElement(det);
        t.addCell(infos);

        return t;
    }

    // ------------------------------------------------------------ Lignée

    private PdfPTable lignee(Mouton m) {
        PdfPTable t = new PdfPTable(1);
        t.setWidthPercentage(100);

        PdfPCell wrap = new PdfPCell();
        wrap.setBackgroundColor(BEIGE);
        wrap.setBorder(Rectangle.LEFT);
        wrap.setBorderColor(OR);
        wrap.setBorderWidthLeft(3f);
        wrap.setPadding(14);

        wrap.addElement(new Paragraph("LIGNÉE",
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 11, VERT)));

        PdfPTable duo = new PdfPTable(2);
        duo.setWidthPercentage(100);
        setWidths(duo, 1f, 1f);
        duo.setSpacingBefore(8);
        duo.getDefaultCell().setBorder(Rectangle.NO_BORDER);

        Font fLab = FontFactory.getFont(FontFactory.HELVETICA, 9, GRIS);
        Font fVal = FontFactory.getFont(FontFactory.HELVETICA_BOLD, 12, TEXTE);

        PdfPCell pereCell = new PdfPCell();
        pereCell.setBorder(Rectangle.NO_BORDER);
        pereCell.setPaddingRight(10);
        pereCell.addElement(new Paragraph("PÈRE", fLab));
        pereCell.addElement(new Paragraph(
                m.getPere() != null ? m.getPere().getNom() + "  (#" + m.getPere().getId() + ")" : "Inconnu",
                fVal));
        duo.addCell(pereCell);

        PdfPCell mereCell = new PdfPCell();
        mereCell.setBorder(Rectangle.NO_BORDER);
        mereCell.addElement(new Paragraph("MÈRE", fLab));
        mereCell.addElement(new Paragraph(
                m.getMere() != null ? m.getMere().getNom() + "  (#" + m.getMere().getId() + ")" : "Inconnue",
                fVal));
        duo.addCell(mereCell);

        wrap.addElement(duo);
        t.addCell(wrap);
        return t;
    }

    // ------------------------------------------------------------ Propriétaire

    private PdfPTable proprietaire(Utilisateur e) {
        PdfPTable t = new PdfPTable(1);
        t.setWidthPercentage(100);

        PdfPCell wrap = new PdfPCell();
        wrap.setBackgroundColor(VERT_CLAIR);
        wrap.setBorder(Rectangle.NO_BORDER);
        wrap.setPadding(14);

        wrap.addElement(new Paragraph("PROPRIÉTAIRE / ÉLEVEUR",
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 11, VERT)));

        if (e == null) {
            Paragraph p = new Paragraph("Aucun éleveur associé.",
                    FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 10, GRIS));
            p.setSpacingBefore(6);
            wrap.addElement(p);
        } else {
            PdfPTable det = new PdfPTable(2);
            det.setWidthPercentage(100);
            setWidths(det, 1f, 2f);
            det.setSpacingBefore(8);
            det.getDefaultCell().setBorder(Rectangle.NO_BORDER);

            ajouterLigne(det, "Propriétaire", safe(e.getNom()));
            ajouterLigne(det, "Bergerie",     safe(e.getNomBergerie()));
            ajouterLigne(det, "Téléphone",    safe(e.getTelephone()));
            ajouterLigne(det, "Adresse",      safe(e.getAdresse()));
            ajouterLigne(det, "Email",        safe(e.getEmail()));

            wrap.addElement(det);
        }

        t.addCell(wrap);
        return t;
    }

    // ------------------------------------------------------------ Signature / date

    private PdfPTable signatureEtDate(String nomBergerie) {
        PdfPTable t = new PdfPTable(2);
        t.setWidthPercentage(100);
        setWidths(t, 1f, 1f);

        PdfPCell g = new PdfPCell();
        g.setBorder(Rectangle.TOP);
        g.setBorderColor(GRIS_CLAIR);
        g.setBorderWidthTop(1f);
        g.setPaddingTop(16);
        g.addElement(new Paragraph("DÉLIVRÉ LE",
                FontFactory.getFont(FontFactory.HELVETICA, 9, GRIS)));
        g.addElement(new Paragraph(LocalDate.now().format(DATE_FMT),
                FontFactory.getFont(FontFactory.HELVETICA_BOLD, 11, TEXTE)));
        Paragraph mention = new Paragraph(
                "Document généré électroniquement par " + nomBergerie + ".",
                FontFactory.getFont(FontFactory.HELVETICA_OBLIQUE, 9, GRIS));
        mention.setSpacingBefore(6);
        g.addElement(mention);
        t.addCell(g);

        PdfPCell d = new PdfPCell();
        d.setBorder(Rectangle.TOP);
        d.setBorderColor(GRIS_CLAIR);
        d.setBorderWidthTop(1f);
        d.setPaddingTop(16);
        d.setHorizontalAlignment(Element.ALIGN_RIGHT);

        Paragraph lab = new Paragraph("CACHET ET SIGNATURE",
                FontFactory.getFont(FontFactory.HELVETICA, 9, GRIS));
        lab.setAlignment(Element.ALIGN_RIGHT);
        d.addElement(lab);

        PdfPTable seal = new PdfPTable(1);
        seal.setWidthPercentage(50);
        seal.setHorizontalAlignment(Element.ALIGN_RIGHT);
        seal.setSpacingBefore(6);
        PdfPCell ring = new PdfPCell(new Phrase(" "));
        ring.setFixedHeight(56);
        ring.setBorder(Rectangle.BOX);
        ring.setBorderColor(OR);
        ring.setBorderWidth(1.5f);
        seal.addCell(ring);
        d.addElement(seal);

        t.addCell(d);
        return t;
    }

    // ------------------------------------------------------------ Helpers

    private Paragraph espaceVertical(float hauteur) {
        Paragraph p = new Paragraph(" ");
        p.setLeading(hauteur);
        p.setSpacingAfter(0);
        return p;
    }

    private void ajouterLigne(PdfPTable t, String label, String valeur) {
        PdfPCell l = new PdfPCell(new Phrase(label.toUpperCase(),
                FontFactory.getFont(FontFactory.HELVETICA, 9, GRIS)));
        l.setBorder(Rectangle.NO_BORDER);
        l.setPaddingTop(3); l.setPaddingBottom(3);
        t.addCell(l);

        PdfPCell v = new PdfPCell(new Phrase(valeur != null ? valeur : "—",
                FontFactory.getFont(FontFactory.HELVETICA, 11, TEXTE)));
        v.setBorder(Rectangle.NO_BORDER);
        v.setPaddingTop(3); v.setPaddingBottom(3);
        t.addCell(v);
    }

    private void setWidths(PdfPTable t, float... widths) {
        try { t.setWidths(widths); } catch (DocumentException ignored) {}
    }

    private String safe(String s) { return s == null || s.isBlank() ? "—" : s; }

    private String sexeLisible(Mouton m) {
        if (m.getSexe() == null) return "—";
        return switch (m.getSexe()) {
            case MALE -> "Mâle";
            case FEMELLE -> "Femelle";
        };
    }

    private String statutLisible(Mouton m) {
        if (m.getStatut() == null) return "—";
        return switch (m.getStatut()) {
            case VIVANT -> "Vivant";
            case VENDU -> "Vendu";
            case MORT -> "Décédé";
        };
    }

    private Image chargerImage(String publicUrl, float maxW, float maxH) {
        Path p = resolveImagePath(publicUrl);
        if (p == null || !Files.exists(p)) return null;
        try {
            Image img = Image.getInstance(p.toString());
            img.scaleToFit(maxW, maxH);
            return img;
        } catch (Exception e) {
            log.warn("Impossible de charger l'image {}: {}", p, e.getMessage());
            return null;
        }
    }

    private Path resolveImagePath(String publicUrl) {
        if (publicUrl == null) return null;
        if (!publicUrl.startsWith(publicBaseUrl + "/")) return null;
        String relative = publicUrl.substring(publicBaseUrl.length() + 1);
        return Paths.get(storageLocation).toAbsolutePath().normalize().resolve(relative);
    }

    // ------------------------------------------------------------ Cadre décoratif + pied

    private static class CadrePageEvent extends PdfPageEventHelper {
        private final String nomBergerie;

        CadrePageEvent(String nomBergerie) {
            this.nomBergerie = nomBergerie;
        }

        @Override
        public void onEndPage(PdfWriter writer, Document document) {
            PdfContentByte cb = writer.getDirectContent();
            Rectangle p = document.getPageSize();

            cb.saveState();
            cb.setColorStroke(OR);
            cb.setLineWidth(0.6f);
            cb.rectangle(20, 20, p.getWidth() - 40, p.getHeight() - 40);
            cb.stroke();
            cb.restoreState();

            Phrase pied = new Phrase(
                    nomBergerie + "  •  via Ladoum Track SN  •  Édité le " + LocalDate.now().format(DATE_COURT)
                            + "  •  Page " + writer.getPageNumber(),
                    FontFactory.getFont(FontFactory.HELVETICA, 8, GRIS));
            ColumnText.showTextAligned(cb, Element.ALIGN_CENTER, pied, p.getWidth() / 2, 28, 0);
        }
    }
}
