<?php

namespace App\Service\Pdf;

use App\Entity\Devis;
use setasign\Fpdi\Fpdi;
use Symfony\Component\HttpKernel\KernelInterface;

if (!\defined('EURO')) {
    \define('EURO', \chr(128)); // @codeCoverageIgnore
}

/**
 * Generation PDF d'un devis avec FPDF + fusion CGV via FPDI.
 * Extend Fpdi (qui etend FPDF) pour pouvoir importer les pages des CGV.
 */
class DevisPdf extends Fpdi
{
    /** @var array<int, array{title: string, content: string, priceHt: float}> */
    private array $items = [];

    private int $lastDevisPage = 0;
    private ?\Twig\Environment $twig = null;

    public function __construct(
        private readonly KernelInterface $kernel,
        private readonly Devis $devis,
        ?\Twig\Environment $twig = null,
    ) {
        $this->twig = $twig;
        parent::__construct();

        $items = [];
        foreach ($this->devis->getLines() as $line) {
            $items[$line->getPos()] = [
                'title' => $line->getTitle(),
                'content' => $line->getDescription() ?? '',
                'priceHt' => (float) $line->getPriceHt(),
            ];
        }
        ksort($items);
        $this->items = $items;

        $this->SetTitle($this->enc('Devis N° '.$this->devis->getOrderNumber()->getNumOrder()));
    }

    /** @codeCoverageIgnore */
    public function Header(): void
    {
        // Sur les pages CGV importees (au-dela de la derniere page devis), pas de header
        if ($this->lastDevisPage > 0 && $this->PageNo() > $this->lastDevisPage) {
            return;
        }

        $this->SetFont('Arial', '', 10);
        $logo = $this->kernel->getProjectDir().'/public/logo.jpg';
        if (file_exists($logo)) {
            $this->Image($logo, 10, 8, 53);
        }

        $formatter = new \IntlDateFormatter(
            'fr_FR',
            \IntlDateFormatter::FULL,
            \IntlDateFormatter::NONE,
            'Europe/Paris',
            \IntlDateFormatter::GREGORIAN
        );

        $numDevisText = $this->enc('DEVIS N° '.$this->devis->getOrderNumber()->getNumOrder());
        $dateText = $this->enc('Emis a Beautor, le '.$formatter->format($this->devis->getCreatedAt()));

        $this->Text(15, 80, $numDevisText);
        $this->Text(15, 85, $dateText);

        $this->SetFont('Arial', 'B', 12);

        $y = 60;
        $customer = $this->devis->getCustomer();

        if (null !== $customer) {
            $name = $customer->getRaisonSociale() ?: $customer->getFullName();
            $this->Text(110, $y, $this->enc($name));

            if ($address = $customer->getAddress()) {
                $y += 5;
                $this->Text(110, $y, $this->enc($address));
            }

            if ($address2 = $customer->getAddress2()) {
                $y += 5;
                $this->Text(110, $y, $this->enc($address2));
            }

            $y += 5;
            $cityLine = ($customer->getZipCode() ?? '').' '.($customer->getCity() ?? '');
            $this->Text(110, $y, $this->enc(trim($cityLine)));
        }

        $this->body();
    }

    /** @codeCoverageIgnore */
    private function body(): void
    {
        $this->SetFont('Arial', 'B', 10);
        $this->SetXY(145, 100);
        $this->Cell(40, 5, $this->enc('PRIX HT'), 0, 0, 'C');

        $this->Line(145, 110, 145, 220);
        $this->Line(185, 110, 185, 220);

        $this->Line(0, 100, 5, 100);
        $this->Line(0, 200, 5, 200);
    }

    public function generate(): void
    {
        $this->AliasNbPages();
        $this->AddPage();
        $this->SetFont('Arial', '', 12);

        $startY = 110;
        $this->SetY($startY);
        $contentBottomLimit = 220;

        foreach ($this->items as $item) {
            // @codeCoverageIgnoreStart
            if ($this->GetY() + 30 > $contentBottomLimit) {
                $this->AddPage();
                $this->body();
                $this->SetY($startY);
            }
            // @codeCoverageIgnoreEnd

            $currentY = $this->GetY();

            // Titre
            $this->SetX(20);
            $this->SetFont('Arial', 'B', 11);
            $this->Cell(95, 10, $this->enc($item['title']), 0, 0);

            // Prix HT
            $this->SetFont('Arial', 'B', 11);
            $this->SetXY(142, $currentY);
            $this->Cell(39, 8, number_format($item['priceHt'], 2, ',', ' ').' '.EURO, 0, 1, 'R');

            // Description
            $this->SetFont('Arial', '', 11);
            $this->SetX(30);
            if ('' !== $item['content']) {
                $this->MultiCell(90, 5, $this->enc($item['content']), 0, 'L');
            }

            $this->Ln(5);
        }

        $this->displaySummary();
        $this->displaySign();
        $this->appendCgv();
    }

    /**
     * Genere les CGV depuis le template Twig via Dompdf puis les importe via FPDI.
     */
    /** @codeCoverageIgnore */
    private function displaySign(): void
    {
        $this->SetAutoPageBreak(false);
        $this->SetXY(15, $this->GetPageHeight() - 45);
        $this->SetFont('Arial', '', 10);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(30, 10, '{{Sign;type=signature;role=First Party}}', 0, 0, 'L');
    }

    /** @codeCoverageIgnore */
    private function appendCgv(): void
    {
        if (null === $this->twig) {
            return;
        }

        try {
            $html = $this->twig->render('pdf/cgv.html.twig');
            $dompdf = new \Dompdf\Dompdf();
            $dompdf->loadHtml($html);
            $dompdf->setPaper('A4');
            $dompdf->render();

            $tmpCgv = tempnam(sys_get_temp_dir(), 'cgv_').'.pdf';
            file_put_contents($tmpCgv, $dompdf->output());

            $this->lastDevisPage = $this->PageNo();
            $pageCount = $this->setSourceFile($tmpCgv);

            for ($i = 1; $i <= $pageCount; ++$i) {
                $tpl = $this->importPage($i);
                $size = $this->getTemplateSize($tpl);
                $this->AddPage($size['orientation'] ?? 'P', [$size['width'], $size['height']]);
                $this->useTemplate($tpl);

                // Sur la DERNIERE page CGV : champ signature DocuSeal
                if ($i === $pageCount) {
                    $this->SetAutoPageBreak(false);
                    $this->SetXY(15, $this->GetPageHeight() - 35);
                    $this->SetFont('Arial', '', 10);
                    $this->SetTextColor(0, 0, 0);
                    $this->Cell(60, 20, '{{SignCGV;type=signature;role=First Party}}', 0, 0, 'L');
                }
            }

            @unlink($tmpCgv);
        } catch (\Throwable) {
            // CGV generation is best-effort
        }
    }

    /** @codeCoverageIgnore */
    private function displaySummary(): void
    {
        $totalHt = (float) $this->devis->getTotalHt();
        $totalTva = (float) $this->devis->getTotalTva();
        $totalTtc = (float) $this->devis->getTotalTtc();
        $tvaEnabled = $totalTva > 0.01;

        $this->SetY($tvaEnabled ? -60 : -50);

        $this->SetFont('Arial', 'B', 12);
        $this->SetX(105);
        $this->Cell(40, 10, $this->enc('Total HT :'), 0, 0, 'R');
        $this->Cell(40, 10, number_format($totalHt, 2, ',', ' ').' '.EURO, 0, 1, 'R');

        if ($tvaEnabled) {
            $this->SetFont('Arial', '', 12);
            $this->SetX(105);
            $this->Cell(40, 10, $this->enc('TVA (20%) :'), 0, 0, 'R');
            $this->Cell(40, 10, number_format($totalTva, 2, ',', ' ').' '.EURO, 0, 1, 'R');

            $this->SetFont('Arial', 'B', 12);
            $this->SetX(105);
            $this->Cell(40, 10, $this->enc('Total TTC :'), 0, 0, 'R');
            $this->Cell(40, 10, number_format($totalTtc, 2, ',', ' ').' '.EURO, 0, 1, 'R');
        } else {
            $this->SetFont('Arial', '', 8);
            $this->SetX(105);
            $this->Cell(80, 5, $this->enc('TVA non applicable - art. 293 B du CGI'), 0, 1, 'R');
        }
    }

    /** @codeCoverageIgnore */
    public function Footer(): void
    {
        // Sur les pages CGV importees (au-dela de la derniere page devis), pas de footer
        if ($this->lastDevisPage > 0 && $this->PageNo() > $this->lastDevisPage) {
            return;
        }

        $this->SetY(-28);
        $this->SetDrawColor(253, 140, 4);
        $this->Line(15, $this->GetY(), 195, $this->GetY());
        $this->Ln(4);
        $this->SetFont('Arial', '', 8);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(190, 4, $this->enc('42 rue de Saint-Quentin - 02800 BEAUTOR - Tél: 07 66 95 70 06'), 0, 1, 'C');
        $this->Cell(190, 4, $this->enc('e-mail : client@e-cosplay.fr - www.e-cosplay.fr'), 0, 1, 'C');
        $this->Cell(190, 4, $this->enc('Association E-Cosplay - N°SIRET 943 121 517 00011 - CODE APE 9329Z - RNA W022006988'), 0, 1, 'C');

        // Numero de page avec alias {nb}
        $this->SetFont('Arial', 'I', 7);
        $this->SetTextColor(150, 150, 150);
        $this->Cell(190, 4, $this->enc('Page ').$this->PageNo().' / {nb}', 0, 0, 'C');
    }

    /**
     * Encode une chaine UTF-8 en Windows-1252 (requis par FPDF).
     */
    private function enc(string $text): string
    {
        return mb_convert_encoding($text, 'Windows-1252', 'UTF-8');
    }
}
