<?php

namespace App\Service\Pdf;

use App\Entity\Devis;
use App\Entity\Product;
use App\Repository\ProductRepository;
use Doctrine\ORM\EntityManagerInterface;
use Fpdf\Fpdf;
use Symfony\Component\HttpKernel\KernelInterface;

class DevisPdfService extends Fpdf
{
    private Devis $devis;
    private string $logo;
    private bool $isExtraPage = false;
    private bool $isIntegrateDocusealFields;
    private ProductRepository $productRepository;

    public function __construct( KernelInterface $kernel, Devis $devis, ProductRepository $productRepository, bool $isIntegrateDocusealFields = false, $orientation = 'P', $unit = 'mm', $size = 'A4')
    {
        parent::__construct($orientation, $unit, $size);
        $this->devis = $devis;
        $this->isIntegrateDocusealFields = $isIntegrateDocusealFields; // Stockage
        $this->logo = $kernel->getProjectDir()."/public/provider/images/favicon.png";

        $this->AliasNbPages();
        $this->SetAutoPageBreak(true, 35);
        $this->productRepository = $productRepository;
    }

    /**
     * Convertit l'UTF-8 en Windows-1252 pour FPDF et gère l'Euro
     */
    private function clean(?string $text): string
    {
        if (!$text) return '';
        $text = iconv('UTF-8', 'windows-1252//TRANSLIT//IGNORE', $text);
        return str_replace('€', chr(128), $text);
    }

    /**
     * Helper pour afficher le symbole Euro proprement
     */
    private function euro(): string
    {
        return ' ' . chr(128);
    }

    public function Header()
    {
        // On n'affiche le header standard que sur les pages de devis (pas CGV/Signature)
        if ($this->page > 0 && !$this->isExtraPage) {
            $this->SetY(10);
            if (file_exists($this->logo)) {
                $this->Image($this->logo, 10, 10, 12);
                $this->SetX(25);
            }

            $this->SetFont('Arial', 'B', 14);
            $this->SetTextColor(0, 0, 0);
            $this->Cell(0, 7, $this->clean('Lilian SEGARD - Ludikevent'), 0, 1, 'L');

            $this->SetX(25);
            $this->SetFont('Arial', '', 8);
            $this->SetTextColor(80, 80, 80);
            $this->Cell(0, 4, $this->clean('SIRET : 930 488 408 00012 | RCS : 930 488 408'), 0, 1, 'L');
            $this->SetX(25);
            $this->Cell(0, 4, $this->clean('6 Rue du Château – 02800 Danizy – France'), 0, 1, 'L');
            $this->SetX(25);
            $this->Cell(0, 4, $this->clean('Tél. : 06 14 17 24 47'), 0, 1, 'L');
            $this->SetX(25);
            $this->Cell(0, 4, $this->clean('contact@ludikevent.fr | www.ludikevent.fr'), 0, 1, 'L');

            $this->SetY(40);
            $this->SetFont('Arial', 'B', 16);
            $this->SetTextColor(37, 99, 235);
            $this->Cell(0, 10, $this->clean('DEVIS N° ' . $this->devis->getNum()), 0, 1, 'L');

            $this->SetDrawColor(37, 99, 235);
            $this->SetLineWidth(0.5);
            $this->Line(10, $this->GetY(), 200, $this->GetY());
        }
    }

    public function generate(): string
    {
        $this->AddPage();

        // Vérification de l'activation de la TVA
        $tvaEnabled = isset($_ENV['TVA_ENABLED']) && $_ENV['TVA_ENABLED'] === "true";
        $tvaRate = $tvaEnabled ? 0.20 : 0;
        $tvaLabel = $tvaEnabled ? '20%' : '0%';

        // --- BLOC CLIENT ---
        $customer = $this->devis->getCustomer();
        $this->SetY(55);
        $this->SetFont('Arial', 'B', 9);
        $this->SetTextColor(100, 100, 100);
        $this->Cell(0, 5, $this->clean('CLIENT'), 0, 1, 'R');
        $this->SetTextColor(0, 0, 0);
        $this->SetFont('Arial', 'B', 12);
        $this->Cell(0, 7, $this->clean($customer->getName()), 0, 1, 'R');

        if ($customer->getEmail()) {
            $this->SetFont('Arial', '', 10);
            $this->SetTextColor(37, 99, 235);
            $this->Cell(0, 5, $this->clean($customer->getEmail()), 0, 1, 'R');
        }

        $yAddress = $this->GetY() + 5;
        $this->renderAddressBlock('ADRESSE DE FACTURATION', $this->devis->getBillAddress(), 'L', 10, $yAddress);
        $this->renderAddressBlock('ADRESSE DE PRESTATION', $this->devis->getAddressShip(), 'R', 110, $yAddress);

        // --- BLOC DATES DE L'ÉVÉNEMENT ---
        $this->SetY($yAddress + 25);
        $this->SetDrawColor(230, 230, 230);
        $this->SetFillColor(250, 250, 250);
        $this->Rect(10, $this->GetY(), 190, 12, 2, 'DF');

        $this->SetY($this->GetY() + 3.5);
        $this->SetFont('Arial', 'B', 9);
        $this->SetTextColor(80, 80, 80);
        $this->Cell(45, 5, $this->clean('DATES DE PRESTATION :'), 0, 0, 'L');

        $this->SetFont('Arial', '', 10);
        $this->SetTextColor(0, 0, 0);

        $dateStart = $this->devis->getStartAt() ? $this->devis->getStartAt()->format('d/m/Y à H:i') : 'N/C';
        $dateEnd = $this->devis->getEndAt() ? $this->devis->getEndAt()->format('d/m/Y à H:i') : 'N/C';
        $this->Cell(0, 5, $this->clean("Du $dateStart au $dateEnd"), 0, 1, 'L');

        $this->SetY($this->GetY() + 8);

        // --- TABLEAU DES PRODUITS ---
        $formule = $this->devis->getFormule();
        if ($formule) {
            $this->SetFont('Arial', 'B', 10);
            $this->SetTextColor(37, 99, 235);
            $this->Cell(0, 6, $this->clean("Formule appliquée : " . $formule->getName()), 0, 1, 'L');
            $this->Ln(2);
        }

        $this->SetFont('Arial', 'B', 8);
        $this->SetFillColor(245, 247, 250);
        $this->Cell(70, 10, $this->clean('Désignation'), 1, 0, 'L', true);
        $this->Cell(15, 10, $this->clean('Jours'), 1, 0, 'C', true);
        $this->Cell(25, 10, $this->clean('Tarif J1'), 1, 0, 'R', true);
        $this->Cell(25, 10, $this->clean('Tarif Sup'), 1, 0, 'R', true);
        $this->Cell(15, 10, $this->clean('TVA'), 1, 0, 'C', true);
        $this->Cell(40, 10, $this->clean('Total HT'), 1, 1, 'R', true);

        $this->SetFont('Arial', '', 9);
        $this->SetTextColor(0, 0, 0);

        $totalCaution = 0;
        $totalHT = 0;
        $isFormuleLineAdded = false;

        foreach ($this->devis->getDevisLines() as $line) {
            $p = $this->productRepository->findOneBy(['name'=>$line->getProduct()]);
            if($p instanceof Product && !$formule) {
                $totalCaution += $p->getCaution();
            }

            $price1Day = $line->getPriceHt();
            $priceSupHT = $line->getPriceHtSup() ?? 0;

            // Si une formule est présente, on force les prix à 0 pour afficher "Inclus"
            // et on ajoute la ligne de la formule (géré plus bas)
            if ($formule) {
                $price1Day = 0;
                $priceSupHT = 0;
            }

            $nbDays = $line->getDay();

            $lineTotalHT = $price1Day + (max(0, $nbDays - 1) * $priceSupHT);
            $totalHT += $lineTotalHT;

            $productName = $line->getProduct();
            $ref = ($p instanceof Product) ? $p->getRef() : "";

            $currentY = $this->GetY();

            // Gestion de l'affichage de la ligne Formule si les prix sont à 0
            if ($formule && !$isFormuleLineAdded && $price1Day == 0 && $priceSupHT == 0) {
                $fPrice = $formule->getPrice1j() ?? 0;
                if ($nbDays >= 2 && $formule->getPrice2j()) $fPrice = $formule->getPrice2j();
                if ($nbDays >= 5 && $formule->getPrice5j()) $fPrice = $formule->getPrice5j();
                
                $totalHT += $fPrice;
                $totalCaution += $formule->getCaution() ?? 0;
                
                $this->SetXY(10, $currentY+2.5);
                $this->SetFont('Arial', 'B', 8);
                $this->Cell(70, 5, $this->clean("Formule : " . $formule->getName()), 0, 0, 'L');

                $this->SetXY(80, $currentY);
                $this->SetFont('Arial', '', 8);
                $this->Cell(15, 10, $nbDays, 'LRB', 0, 'C');
                $this->Cell(25, 10, number_format($fPrice, 2, ',', ' ') . $this->euro(), 'RB', 0, 'R');
                $this->Cell(25, 10, "-", 'RB', 0, 'R');
                $this->Cell(15, 10, $tvaLabel, 'RB', 0, 'C');
                $this->Cell(40, 10, number_format($fPrice, 2, ',', ' ') . $this->euro(), 'RB', 1, 'R');

                $this->Line(10, $currentY, 10, $currentY + 10);
                $this->Line(10, $currentY + 10, 80, $currentY + 10);
                
                $isFormuleLineAdded = true;
                $currentY = $this->GetY(); // Update Y for the next line (the actual product line)
                if ($this->GetY() > 250) { $this->AddPage(); $currentY = $this->GetY(); }
            }

            // Ligne Produit
            $this->SetXY(10, $currentY+2.5);
            $this->SetFont('Arial', 'B', 8);
            $this->Cell(70, 5, $this->clean($productName . ($ref ? ' (Ref: ' . $ref . ')' : '')), 0, 0, 'L');

            $this->SetXY(80, $currentY);
            $this->SetFont('Arial', '', 8);
            $this->Cell(15, 10, $nbDays, 'LRB', 0, 'C');
            $this->Cell(25, 10, ($price1Day == 0 ? "Inclus" : number_format($price1Day, 2, ',', ' ') . $this->euro()), 'RB', 0, 'R');
            $this->Cell(25, 10, ($price1Day == 0 ? "-" : number_format($priceSupHT, 2, ',', ' ') . $this->euro()), 'RB', 0, 'R');
            $this->Cell(15, 10, $tvaLabel, 'RB', 0, 'C');
            $this->Cell(40, 10, ($lineTotalHT == 0 && $price1Day == 0 ? "Inclus" : number_format($lineTotalHT, 2, ',', ' ') . $this->euro()), 'RB', 1, 'R');

            $this->Line(10, $currentY, 10, $currentY + 10);
            $this->Line(10, $currentY + 10, 80, $currentY + 10);

            if ($this->GetY() > 250) { $this->AddPage(); }
        }

        // --- TABLEAU DES OPTIONS ---
        if (count($this->devis->getDevisOptions()) > 0) {
            $this->Ln(5);
            $this->SetFont('Arial', 'B', 8);
            $this->SetFillColor(230, 235, 245);
            $this->Cell(135, 8, $this->clean('Options & Services additionnels'), 1, 0, 'L', true);
            $this->Cell(15, 8, $this->clean('TVA'), 1, 0, 'C', true);
            $this->Cell(40, 8, $this->clean('i'), 1, 1, 'R', true);

            $this->SetFont('Arial', '', 9);
            foreach ($this->devis->getDevisOptions() as $devisOption) {
                $priceHT = $devisOption->getPriceHt();
                $optionName = $devisOption->getOption();

                // Si une formule est présente, les options sont incluses (prix 0) sauf les frais de livraison
                if ($formule) {
                    $isDelivery = stripos($optionName, 'livraison') !== false || stripos($optionName, 'déplacement') !== false;
                    if (!$isDelivery) {
                        $priceHT = 0;
                    }
                }

                $totalHT += $priceHT;

                $this->Cell(135, 8, $this->clean($optionName." - ".$devisOption->getDetails()), 'LRB', 0, 'L');
                $this->Cell(15, 8, $tvaLabel, 'RB', 0, 'C');
                $this->Cell(40, 8, ($priceHT == 0 ? "Inclus" : number_format($priceHT, 2, ',', ' ') . $this->euro()), 'RB', 1, 'R');

                if ($this->GetY() > 260) { $this->AddPage(); }
            }
        }

        // --- CALCULS FINAUX ---
        
        // Gestion de la Promotion
        $promotion = $this->devis->getOrderSession()?->getPromotion();
        if ($promotion) {
             $percentage = $promotion['percentage'] ?? 0;
             $name = $promotion['name'] ?? 'Remise';
             $discountAmount = $totalHT * ($percentage / 100);
             
             // Affichage du Total HT Avant Remise
             $this->SetFont('Arial', '', 9);
             $this->Cell(130);
             $this->SetTextColor(100, 100, 100);
             $this->Cell(30, 8, $this->clean("Total HT Avant Remise"), 0, 0, 'L');
             $this->Cell(30, 8, number_format($totalHT, 2, ',', ' ') . $this->euro(), 0, 1, 'R');

             // Affichage de la ligne de promotion
             $this->Cell(130);
             $this->SetTextColor(37, 99, 235); // Bleu pour la promo
             $this->Cell(30, 8, $this->clean("Promotion : $name (-$percentage%)"), 0, 0, 'L');
             $this->Cell(30, 8, "- " . number_format($discountAmount, 2, ',', ' ') . $this->euro(), 0, 1, 'R');
             $this->SetTextColor(0, 0, 0); // Reset couleur

             $totalHT -= $discountAmount;
        }

        $amountTVA = $totalHT * $tvaRate;
        $totalTTC = $totalHT + $amountTVA;

        // --- BLOC TOTAUX ---
        $this->Ln(5);
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(130);
        
        $lblTotal = $promotion ? 'TOTAL HT REMISE' : 'TOTAL HT';
        
        $this->Cell(30, 8, $this->clean($lblTotal), 0, 0, 'L');
        $this->Cell(30, 8, number_format($totalHT, 2, ',', ' ') . $this->euro(), 0, 1, 'R');

        $this->Cell(130);
        $this->SetFont('Arial', '', 9);
        $this->Cell(30, 8, 'TVA ('.$tvaLabel.')', 0, 0, 'L');
        $this->Cell(30, 8, number_format($amountTVA, 2, ',', ' ') . $this->euro(), 0, 1, 'R');

        $this->Ln(2);
        $this->Cell(130);
        $this->SetFont('Arial', 'B', 11);
        $this->SetFillColor(37, 99, 235); $this->SetTextColor(255, 255, 255);
        $this->Cell(30, 10, ' TOTAL TTC', 0, 0, 'L', true);
        $this->Cell(30, 10, number_format($totalTTC, 2, ',', ' ') . $this->euro() . ' ', 0, 1, 'R', true);

        // --- CAUTION ---
        $this->Ln(2);
        $this->SetTextColor(80, 80, 80);
        $this->Cell(130);
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(30, 8, ' TOTAL CAUTION', 'B', 0, 'L');
        $this->Cell(30, 8, number_format($totalCaution, 2, ',', ' ') . $this->euro(), 'B', 1, 'R');

        $this->SetFont('Arial', 'I', 7);
        $this->Cell(130);
        $this->Cell(60, 4, $this->clean('(Caution non encaissée, voir CGV Article 6)'), 0, 1, 'R');

        // Mention légale auto-entrepreneur (uniquement si TVA désactivée)
        if (!$tvaEnabled) {
            $this->Ln(5);
            $this->SetTextColor(80, 80, 80);
            $this->SetFont('Arial', 'I', 8);
            $this->Cell(0, 5, $this->clean('TVA non applicable, art. 293 B du CGI'), 0, 1, 'R');
        }

        $this->addCGV();
        $this->addSignaturePage();

        return $this->Output('S');
    }

    private function addCGV(): void
    {
        $this->isExtraPage = true;
        $this->AddPage();
        $this->SetMargins(15, 15, 15);
        $this->SetAutoPageBreak(true, 20);
        $this->SetY(15);

        // --- ENTÊTE ---
        $this->SetFont('Arial', 'B', 12);
        $this->SetTextColor(37, 99, 235); // Bleu Ludikevent
        $this->Cell(0, 10, $this->clean('CONDITIONS GÉNÉRALES DE VENTE'), 0, 1, 'C');

        $this->SetFont('Arial', 'B', 10);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(0, 5, $this->clean('Lilian SEGARD - Ludikevent'), 0, 1, 'C');

        $this->SetFont('Arial', '', 8);
        $this->SetTextColor(80, 80, 80);
        $this->Cell(0, 4, $this->clean('SIRET : 930 488 408 00012 | 6 Rue du Château – 02800 Danizy – France'), 0, 1, 'C');
        $this->Cell(0, 4, $this->clean('Email : contact@ludikevent.fr | Téléphone : 06 14 17 24 47'), 0, 1, 'C');
        $this->Cell(0, 4, $this->clean('Assurance RC Pro : 17006220 0001'), 0, 1, 'C');
        $this->Ln(5);

        $this->SetFont('Arial', 'I', 9);
        $this->SetTextColor(0, 0, 0);
        $this->MultiCell(0, 5, $this->clean("Toute réservation implique l'acceptation sans réserve des présentes Conditions Générales de Vente."), 0, 'C');
        $this->Ln(5);

        // --- TEXTE INTÉGRAL ---
        $fullText = [
            "ARTICLE 1 – OBJET ET CHAMP D'APPLICATION" => "Les présentes Conditions Générales de Vente (ci-après \"CGV\") régissent les relations contractuelles entre Lilian SEGARD - Ludikevent (ci-après \"le Prestataire\") et toute personne physique ou morale (ci-après \"le Client\" ou \"le Locataire\") dans le cadre de :\n• La location de structures gonflables professionnelles appartenant à Lilian SEGARD - Ludikevent\n• La mise en relation avec des propriétaires privés pour du matériel récréatif destiné à des événements privés (anniversaires, baptêmes, etc.)\nDans le cas d'une mise en relation entre particuliers : Lilian SEGARD - Ludikevent intervient uniquement en qualité d'intermédiaire. Le contrat de location est conclu directement entre le propriétaire du matériel et le locataire. Lilian SEGARD - Ludikevent n'assume aucune responsabilité liée à l'état, la conformité ou l'utilisation dudit matériel.",

            "ARTICLE 2 – RÉSERVATION" => "La réservation devient ferme et définitive après réunion des trois conditions cumulatives suivantes :\n✓ Confirmation écrite par Lilian SEGARD - Ludikevent (email ou courrier)\n✓ Paiement effectif des arrhes de 25% du montant total\n✓ Acceptation expresse et signature des présentes CGV\nLes prestations sont proposées sous réserve de disponibilité du matériel aux dates demandées. Lilian SEGARD - Ludikevent se réserve le droit de refuser toute réservation si les conditions d'installation ou de sécurité ne sont pas réunies, sans que sa responsabilité ne puisse être engagée.",

            "ARTICLE 3 – TARIFS ET CONDITIONS DE PAIEMENT" => "Les tarifs sont exprimés en euros (€) toutes taxes comprises (TTC) et sont ceux en vigueur au jour de la réservation, conformément au devis ou contrat signé.\nModalités de paiement :\n• Arrhes de 25% à la réservation (non remboursables sauf cas de force majeure dûment justifié)\n• Solde dû au plus tard le jour de l'installation, AVANT le montage des structures\nEn cas de non-paiement du solde à la date prévue, Lilian SEGARD - Ludikevent se réserve le droit de ne pas procéder à la livraison ni à l'installation, sans que le Client puisse prétendre à un quelconque remboursement des arrhes versées. Des frais de livraison, d'installation et de déplacement peuvent s'appliquer selon la distance et les conditions d'accès au lieu de l'événement. Modes de paiement acceptés : virement bancaire, chèque (à établir à l'ordre de Lilian SEGARD - Ludikevent).",

            "ARTICLE 4 – DROIT DE RÉTRACTATION" => "Conformément à l'article L221-28 du Code de la consommation, le droit de rétractation de 14 jours ne s'applique pas aux prestations de services pleinement exécutées avant la fin du délai de rétractation et dont l'exécution a commencé après accord préalable exprès du consommateur et renoncement exprès à son droit de rétractation. En outre, aucun droit de rétractation n'est applicable pour une prestation de services dont la date d'exécution est fixée à une date déterminée ou à période déterminée (événement daté).",

            "ARTICLE 5 – CONDITIONS D'ANNULATION" => "5.1 – Annulation par le Client :\n• Annulation après versement des arrhes : les arrhes restent acquises au Prestataire à titre d'indemnité forfaitaire\n• Annulation moins de 15 jours calendaires avant la date de l'événement : arrhes non remboursables + facturation de 50% du solde restant dû\n• Annulation moins de 7 jours calendaires avant la date de l'événement : intégralité du montant reste due\n• Cas de force majeure dûment justifié (certificat médical, décès, catastrophe naturelle) : étude au cas par cas, possibilité de report de la prestation\n\n5.2 – Annulation par Lilian SEGARD - Ludikevent :\nEn cas d'impossibilité totale d'assurer la prestation pour cause de force majeure (conditions météorologiques extrêmes, défaillance matérielle majeure, cas fortuit), Lilian SEGARD - Ludikevent s'engage à : informer le Client dans les meilleurs délais, proposer une solution de report ou de remplacement dans la mesure du possible, procéder au remboursement intégral des sommes versées si aucune solution alternative n'est acceptable. La responsabilité de Lilian SEGARD - Ludikevent ne saurait être engagée au-delà du remboursement des sommes effectivement perçues.",

            "ARTICLE 6 – CAUTION DE GARANTIE" => "Une caution de garantie peut être exigée selon le type et la valeur du matériel loué :\n• Structures professionnelles Lilian SEGARD - Ludikevent | Selon devis | Restitution immédiate après état des lieux de fin de location et contrôle de conformité\n• Matériel mis en relation (propriétaires privés) | Selon convention propriétaire | Restitution selon accord entre parties\nLa caution peut être conservée totalement ou partiellement en cas de : dégradation du matériel, salissure importante nécessitant un nettoyage approfondi, perte d'éléments ou d'accessoires, non-respect des conditions d'utilisation ayant entraîné des dommages.",

            "ARTICLE 7 – LIVRAISON, INSTALLATION ET RÉCUPÉRATION" => "7.1 – Structures professionnelles Lilian SEGARD - Ludikevent :\nInstallation : L'installation est réalisée exclusivement par le personnel qualifié de Lilian SEGARD - Ludikevent. Le Client doit fournir un terrain plat, propre, dégagé, avec une alimentation électrique 220V à moins de 50 mètres. L'accès doit être praticable pour les véhicules.\nRécupération : La récupération du matériel est effectuée par Lilian SEGARD - Ludikevent aux horaires convenus.\n7.2 – Matériel en mise en relation :\nLilian SEGARD - Ludikevent peut assurer l'installation et la récupération pour le compte du propriétaire privé. Le Client locataire reste tenu d'assurer une surveillance permanente et constante. Des frais de déplacement supplémentaires peuvent s'appliquer au-delà d'un rayon de 30 km depuis Danizy.",

            "ARTICLE 8 – ÉTATS DES LIEUX ET TRANSFERT DE RESPONSABILITÉ" => "8.1 – État des lieux d'installation : Un état des lieux contradictoire est OBLIGATOIREMENT réalisé. La signature par le Client vaut reconnaissance de conformité et TRANSFERT COMPLET DE LA RESPONSABILITÉ DU MATÉRIEL AU CLIENT. Le Client assume l'ENTIÈRE et EXCLUSIVE responsabilité du matériel, de son utilisation, de sa surveillance et des dommages qui pourraient en résulter.\n8.2 – État des lieux de fin de location : Un état des lieux contradictoire est réalisé lors de la récupération. Sa signature vaut RETOUR DE LA RESPONSABILITÉ À Lilian SEGARD - Ludikevent.\n8.3 – Absence de signature : En cas d'absence ou de refus de signature, l'état des lieux établi par Lilian SEGARD - Ludikevent fera foi. Le matériel sera réputé avoir été livré en parfait état et la responsabilité du Client reste pleine et entière durant toute la période de location.",

            "ARTICLE 9 – OBLIGATIONS ET RESPONSABILITÉS DU CLIENT" => "Le Client s'engage IMPÉRATIVEMENT à :\n9.1 – Surveillance obligatoire : Assurer une surveillance PERMANENTE, CONSTANTE et ACTIVE par un adulte majeur responsable.\n9.2 – Respect des consignes : Ébriété interdite, retrait des chaussures, bijoux, objets pointus, pas de nourriture ou boissons.\n9.3 – Conditions météorologiques : ARRÊTER IMMÉDIATEMENT l'utilisation en cas de vent > 40 km/h, pluie ou orage.\n9.4 – Intégrité du matériel : Ne JAMAIS déplacer, démonter ou modifier les structures, ni débrancher la soufflerie. Signaler toute anomalie immédiatement.",

            "ARTICLE 10 – EXCLUSION ET LIMITATION DE RESPONSABILITÉ" => "10.1 – Lilian SEGARD - Ludikevent garantit exclusivement la livraison d'un matériel conforme et une installation aux normes.\n10.2 – Durant la période de location, Lilian SEGARD - Ludikevent décline FORMELLEMENT et INTÉGRALEMENT toute responsabilité concernant : les dommages corporels (blessures, accidents) subis par les utilisateurs, les dommages matériels causés aux tiers, les conséquences d'une surveillance insuffisante ou du non-respect des consignes.\n10.3 – Le Client reconnaît être le SEUL responsable de la sécurité, assumer tous les risques et renoncer IRRÉVOCABLEMENT à tout recours contre Lilian SEGARD - Ludikevent.",

            "ARTICLE 11 – ASSURANCE OBLIGATOIRE DU CLIENT" => "Le Client doit OBLIGATOIREMENT disposer d'une assurance RC en cours de validité couvrant l'utilisation de structures gonflables. En l'absence d'assurance valide, Lilian SEGARD - Ludikevent se réserve le droit d'annuler la prestation sans remboursement possible.",

            "ARTICLE 12 – CONDITIONS MÉTÉOROLOGIQUES" => "La sécurité est prioritaire. Lilian SEGARD - Ludikevent peut refuser l'installation ou interrompre la prestation en cas de danger. Aucun remboursement ne pourra être réclamé si le matériel a déjà été installé conformément au contrat.",

            "ARTICLE 13 – DÉGRADATIONS, PERTES ET VOLS" => "Toute dégradation ou vol survenu durant la location sera INTÉGRALEMENT facturé au Client (réparation ou valeur de remplacement). Toute dégradation non signalée lors de l'état des lieux d'installation est irréfragablement imputable au Client.",

            "ARTICLE 14 – PROTECTION DES DONNÉES PERSONNELLES" => "Données collectées EXCLUSIVEMENT pour la gestion du contrat (RGPD). Droit d'accès et de rectification via contact@ludikevent.fr.",

            "ARTICLE 15 – RÉCLAMATIONS" => "Toute réclamation doit être adressée par écrit sous 8 jours à : Lilian SEGARD - Ludikevent, 6 Rue du Château, 02800 Danizy. Passé ce délai, aucune réclamation n'est recevable.",

            "ARTICLE 16 – MÉDIATION" => "Le Client consommateur peut recourir gratuitement à un médiateur de la consommation en vue de la résolution amiable du litige.",

            "ARTICLE 17 – DROIT APPLICABLE ET JURIDICTION COMPÉTENTE" => "Loi française. Compétence EXCLUSIVE aux tribunaux du ressort du siège de Lilian SEGARD - Ludikevent (Tribunal de Saint-Quentin).",

            "ARTICLE 18 – ACCEPTATION DES CONDITIONS GÉNÉRALES DE VENTE" => "Le fait de procéder à une réservation vaut ACCEPTATION PLEINE, ENTIÈRE et SANS RÉSERVE des présentes CGV. Le Client reconnaît en avoir pris connaissance et les avoir comprises."
        ];

        foreach ($fullText as $titre => $corps) {
            $this->SetFont('Arial', 'B', 9);
            $this->SetTextColor(37, 99, 235);
            $this->MultiCell(0, 5, $this->clean($titre), 0, 'L');

            $this->SetFont('Arial', '', 8.5);
            $this->SetTextColor(0, 0, 0);
            $this->MultiCell(0, 4, $this->clean($corps), 0, 'L');
            $this->Ln(3);
        }
    }

    private function addSignaturePage(): void
    {
        $this->isExtraPage = true;
        $this->AddPage();
        $this->SetY(30);

        // Titre
        $this->SetFont('Arial', 'B', 14);
        $this->SetTextColor(37, 99, 235);
        $this->Cell(0, 10, $this->clean("BON POUR ACCORD ET SIGNATURE"), 0, 1, 'C');

        $this->Ln(10);
        $this->SetFont('Arial', '', 10);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(0, 7, $this->clean("Fait à Danizy, le : " . date('d/m/Y')), 0, 1, 'L');
        $this->Ln(10);

        // --- SECTION DES CASES À COCHER ---
        $this->SetFont('Arial', '', 10);

        $checkPoints = [
            "J'accepte sans réserve les Conditions Générales de Vente ci-jointes." => "cgv",
            "Je reconnais avoir pris connaissance de l'obligation de disposer d'une assurance RC." => "assurance",
            "Je reconnais avoir pris connaissance des mesures de sécurité et de surveillance." => "securite",
            "Je reconnais avoir pris connaissance du paiement des arrhes de 25% pour validation (non remboursables)." => "arrhes"
        ];

        foreach ($checkPoints as $label => $role) {
            $currentY = $this->GetY();
            $this->Rect(15, $currentY + 1, 5, 5); // Le carré reste visible pour tout le monde
            $this->SetX(25);
            $this->MultiCell(0, 7, $this->clean($label), 0, 'L');

            // AJOUT CONDITIONNEL DOCUSEAL
            if ($this->isIntegrateDocusealFields) {
                $this->SetXY(15, $currentY + 1);
                $this->SetTextColor(0, 0, 0); // Blanc (invisible)
                $this->SetFont('Arial', '', 10);
                $this->Cell(5, 5, '{{type=checkbox;required=true;role=Client;name='.$role.';}}', 0, 0, 'C');

                $this->SetTextColor(0, 0, 0);
                $this->SetFont('Arial', '', 10);
            }

            $this->Ln(10);
        }

        $this->Ln(15);
        $ySign = $this->GetY();

        // --- BLOC PRESTATAIRE ---
        $this->SetXY(15, $ySign);
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(85, 8, $this->clean("Le Prestataire"), 0, 1, 'C');
        $this->SetX(15);
        $this->Cell(85, 45, "", 1, 0);

        $this->SetXY(17, $ySign + 12);

        // AJOUT CONDITIONNEL SIGNATURE PRESTATAIRE
        if ($this->isIntegrateDocusealFields) {
            $this->SetXY(22, $ySign + 9);
            $this->SetTextColor(0, 0, 0);
            $this->SetFont('Arial', '', 10);
            $this->Cell(85, 5, '{{Sign;type=signature;role=Ludikevent;height=120;width=236}}', 0, 0, 'C');
        }

        // --- BLOC CLIENT ---
        $this->SetTextColor(0, 0, 0);
        $this->SetXY(110, $ySign);
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(85, 8, $this->clean("Le Client (Lu et approuvé)"), 0, 1, 'C');
        $this->SetX(110);
        $this->Cell(85, 45, "", 1, 0);

        // AJOUT CONDITIONNEL SIGNATURE CLIENT
        if ($this->isIntegrateDocusealFields) {
            $this->SetXY(113, $ySign+9);
            $this->SetTextColor(0, 0, 0);
            $this->SetFont('Arial', '', 10);
            $this->Cell(85, 5, '{{Sign;type=signature;role=Client;height=120;width=236}}', 0, 0, 'C');
        }
    }

    private function renderAddressBlock(string $label, $address, string $align, int $x, int $y)
    {
        if (!$address) return;
        $this->SetXY($x, $y);
        $this->SetFont('Arial', 'B', 8); $this->SetTextColor(100, 100, 100);
        $this->Cell(90, 5, $this->clean($label), 0, 1, $align);
        $this->SetFont('Arial', '', 10); $this->SetTextColor(50, 50, 50);
        $lines = [$address->getAddress(), $address->getAddress2(), $address->getZipcode() . ' ' . $address->getCity()];
        foreach ($lines as $line) { if ($line) { $this->SetX($x); $this->Cell(90, 5, $this->clean($line), 0, 1, $align); } }
    }

    public function Footer(): void
    {
        // Positionnement à 1,5 cm du bas
        $this->SetY(-15);
        $this->SetFont('Arial', 'I', 7);
        $this->SetTextColor(150, 150, 150);

        // Texte gauche : Identification du devis
        $this->Cell(0, 10, $this->clean('Devis Ludik Event - Lilian SEGARD - SIRET 93048840800012'), 0, 0, 'L');


        // Numérotation des pages à droite
        $this->SetTextColor(150, 150, 150);
        $this->SetFont('Arial', 'I', 8);
        $this->Cell(0, 10, 'Page ' . $this->PageNo() . '/{nb}', 0, 0, 'R');
    }
}
