<?php

namespace App\Service\Pdf;

use setasign\Fpdi\Fpdi;
use Symfony\Component\HttpKernel\KernelInterface;

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

class ComptaPdf extends Fpdi
{
    private string $documentTitle;
    private string $periodFrom;
    private string $periodTo;

    /** @var list<array<string, string>> */
    private array $rows = [];

    /** @var list<string> */
    private array $columns = [];

    /** @var array<string, int> */
    private array $columnWidths = [];

    public function __construct(
        private readonly KernelInterface $kernel,
        string $documentTitle,
        string $periodFrom,
        string $periodTo,
    ) {
        parent::__construct();
        $this->documentTitle = $documentTitle;
        $this->periodFrom = $periodFrom;
        $this->periodTo = $periodTo;

        $this->SetTitle($this->enc($documentTitle));
        $this->SetAuthor($this->enc('Association E-Cosplay'));
        $this->SetCreator('CRM E-Cosplay');
    }

    /**
     * @param list<array<string, string>> $rows
     */
    public function setData(array $rows): void
    {
        $this->rows = $rows;
        if (!empty($rows)) {
            $this->columns = array_keys($rows[0]);
            $this->columnWidths = $this->computeColumnWidths();
        }
    }

    public function generate(): void
    {
        $this->AliasNbPages();
        $this->AddPage('L');

        $this->writeContextBlock();
        $this->writeDataTable();
        $this->writeSummary();
        $this->writeSignatureBlock();
    }

    // ---------------------------------------------------------------
    // Header / Footer
    // ---------------------------------------------------------------

    public function Header(): void
    {
        $logo = $this->kernel->getProjectDir().'/public/logo.jpg';
        if (file_exists($logo)) {
            $this->Image($logo, 10, 8, 40);
        }

        // Titre du document
        $this->SetFont('Arial', 'B', 16);
        $this->SetXY(60, 10);
        $this->Cell(0, 8, $this->enc(mb_strtoupper($this->documentTitle)), 0, 1, 'L');

        // Periode
        $this->SetFont('Arial', '', 10);
        $this->SetXY(60, 18);
        $this->Cell(0, 5, $this->enc('Periode : du '.$this->periodFrom.' au '.$this->periodTo), 0, 1, 'L');

        // Date de generation
        $formatter = new \IntlDateFormatter(
            'fr_FR',
            \IntlDateFormatter::FULL,
            \IntlDateFormatter::NONE,
            'Europe/Paris',
            \IntlDateFormatter::GREGORIAN
        );
        $this->SetXY(60, 23);
        $this->SetFont('Arial', '', 9);
        $this->SetTextColor(100, 100, 100);
        $this->Cell(0, 5, $this->enc('Genere le '.$formatter->format(new \DateTime())), 0, 1, 'L');
        $this->SetTextColor(0, 0, 0);

        $this->Ln(5);
    }

    public function Footer(): void
    {
        $this->SetY(-20);
        $this->SetDrawColor(253, 140, 4);
        $this->Line(15, $this->GetY(), $this->GetPageWidth() - 15, $this->GetY());
        $this->Ln(3);
        $this->SetFont('Arial', '', 7);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(0, 3, $this->enc('42 rue de Saint-Quentin - 02800 BEAUTOR - Tel: 07 66 95 70 06 - client@e-cosplay.fr - www.e-cosplay.fr'), 0, 1, 'C');
        $this->Cell(0, 3, $this->enc('Association E-Cosplay - N SIRET 943 121 517 00011 - CODE APE 9329Z - RNA W022006988'), 0, 1, 'C');

        $this->SetFont('Arial', 'I', 7);
        $this->SetTextColor(150, 150, 150);
        $this->Cell(0, 3, $this->enc('Page ').$this->PageNo().' / {nb}', 0, 0, 'C');
    }

    // ---------------------------------------------------------------
    // Bloc legal / contextuel
    // ---------------------------------------------------------------

    private function writeContextBlock(): void
    {
        $this->SetY(35);

        $labelW = 55;
        $dataW = 120;

        // Ligne superieure
        $this->SetDrawColor(200, 200, 200);
        $this->Cell(0, 0.5, '', 'T', 1, 'L');
        $this->Ln(2);

        $this->SetFont('Arial', 'B', 10);
        $this->Cell(0, 5, $this->enc('INFORMATIONS LEGALES ET CONTEXTUELLES'), 0, 1, 'C');
        $this->Ln(1);

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

        // Association / RNA
        $this->Cell($labelW, 5, $this->enc('Association :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 9);
        $this->Cell($dataW, 5, $this->enc('E-Cosplay Association loi 1901 - RNA N W022006988'), 0, 1, 'L');
        $this->SetFont('Arial', '', 9);

        // Siege social
        $this->Cell($labelW, 5, $this->enc('Siege social :'), 0, 0, 'L');
        $this->Cell($dataW, 5, $this->enc('42 rue de Saint-Quentin 02800 Beautor'), 0, 1, 'L');

        // SIRET
        $this->Cell($labelW, 5, $this->enc('SIRET :'), 0, 0, 'L');
        $this->Cell($dataW, 5, $this->enc('943 121 517 00011'), 0, 1, 'L');

        // Code APE
        $this->Cell($labelW, 5, $this->enc('Code APE :'), 0, 0, 'L');
        $this->Cell($dataW, 5, $this->enc('9329Z'), 0, 1, 'L');

        // Document
        $this->Cell($labelW, 5, $this->enc('Document :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 9);
        $this->Cell($dataW, 5, $this->enc($this->documentTitle), 0, 1, 'L');
        $this->SetFont('Arial', '', 9);

        // Periode
        $this->Cell($labelW, 5, $this->enc('Periode comptable :'), 0, 0, 'L');
        $this->Cell($dataW, 5, $this->enc('Du '.$this->periodFrom.' au '.$this->periodTo), 0, 1, 'L');

        // Ligne inferieure
        $this->Ln(2);
        $this->Cell(0, 0.5, '', 'T', 1, 'L');
        $this->Ln(3);
    }

    // ---------------------------------------------------------------
    // Tableau de donnees
    // ---------------------------------------------------------------

    private function writeDataTable(): void
    {
        if (empty($this->rows)) {
            $this->SetFont('Arial', '', 11);
            $this->Cell(0, 10, $this->enc('Aucune donnee sur cette periode.'), 0, 1, 'C');

            return;
        }

        // En-tete du tableau
        $this->SetFont('Arial', 'B', 7);
        $this->SetFillColor(35, 35, 35);
        $this->SetTextColor(255, 255, 255);

        foreach ($this->columns as $col) {
            $w = $this->columnWidths[$col] ?? 25;
            $this->Cell($w, 6, $this->enc($col), 1, 0, 'C', true);
        }
        $this->Ln();
        $this->SetTextColor(0, 0, 0);

        // Donnees
        $this->SetFont('Arial', '', 7);
        $fill = false;
        foreach ($this->rows as $row) {
            // Verifier si on a besoin d'une nouvelle page
            if ($this->GetY() + 5 > $this->GetPageHeight() - 30) {
                $this->AddPage('L');
                $this->SetY(35);

                // Re-dessiner l'en-tete du tableau
                $this->SetFont('Arial', 'B', 7);
                $this->SetFillColor(35, 35, 35);
                $this->SetTextColor(255, 255, 255);
                foreach ($this->columns as $col) {
                    $w = $this->columnWidths[$col] ?? 25;
                    $this->Cell($w, 6, $this->enc($col), 1, 0, 'C', true);
                }
                $this->Ln();
                $this->SetTextColor(0, 0, 0);
                $this->SetFont('Arial', '', 7);
                $fill = false;
            }

            $this->SetFillColor(245, 245, 240);
            foreach ($this->columns as $col) {
                $w = $this->columnWidths[$col] ?? 25;
                $value = $row[$col] ?? '';
                $align = $this->isNumericColumn($col) ? 'R' : 'L';
                $this->Cell($w, 5, $this->enc($value), 'B', 0, $align, $fill);
            }
            $this->Ln();
            $fill = !$fill;
        }

        $this->Ln(3);
    }

    // ---------------------------------------------------------------
    // Resume / totaux
    // ---------------------------------------------------------------

    private function writeSummary(): void
    {
        $this->SetFont('Arial', 'B', 9);
        $this->Cell(0, 6, $this->enc('Total : '.\count($this->rows).' ecriture(s)'), 0, 1, 'L');

        // Si colonnes Debit/Credit, afficher les totaux
        $totalDebit = 0.0;
        $totalCredit = 0.0;
        $hasDebitCredit = false;

        foreach ($this->rows as $row) {
            if (isset($row['Debit'])) {
                $totalDebit += (float) $row['Debit'];
                $hasDebitCredit = true;
            }
            if (isset($row['Credit'])) {
                $totalCredit += (float) $row['Credit'];
            }
            // Grand livre / balance
            if (isset($row['MontantHT'])) {
                $totalDebit += (float) $row['MontantHT'];
            }
        }

        if ($hasDebitCredit) {
            $this->SetFont('Arial', '', 9);
            $this->Cell(60, 5, $this->enc('Total Debit : '.number_format($totalDebit, 2, ',', ' ')).' '.EURO, 0, 0, 'L');
            $this->Cell(60, 5, $this->enc('Total Credit : '.number_format($totalCredit, 2, ',', ' ')).' '.EURO, 0, 1, 'L');
        }

        $this->Ln(5);
    }

    // ---------------------------------------------------------------
    // Bloc signature (champ DocuSeal)
    // ---------------------------------------------------------------

    private function writeSignatureBlock(): void
    {
        // S'assurer qu'on a assez de place
        if ($this->GetY() + 45 > $this->GetPageHeight() - 25) {
            $this->AddPage('L');
            $this->SetY(35);
        }

        $this->SetDrawColor(200, 200, 200);
        $this->Cell(0, 0.5, '', 'T', 1, 'L');
        $this->Ln(3);

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

        $this->SetFont('Arial', '', 9);
        $this->Cell(0, 5, $this->enc('Fait a Beautor, le '.$formatter->format(new \DateTime())), 0, 1, 'L');
        $this->Ln(2);

        $this->SetFont('Arial', 'B', 9);
        $this->Cell(0, 5, $this->enc('Signature du responsable :'), 0, 1, 'L');
        $this->Ln(1);

        // Champ signature DocuSeal (meme format que DevisPdf)
        $this->SetAutoPageBreak(false);
        $this->SetFont('Arial', '', 10);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(60, 20, '{{Sign;type=signature;role=First Party}}', 0, 1, 'L');
    }

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

    /**
     * @return array<string, int>
     */
    private function computeColumnWidths(): array
    {
        if (empty($this->columns)) {
            return []; // @codeCoverageIgnore
        }

        $pageWidth = 277; // A4 landscape - margins
        $widths = [];

        // Colonnes connues avec taille fixe
        $known = [
            'JournalCode' => 15,
            'JournalLib' => 28,
            'EcritureNum' => 22,
            'EcritureDate' => 20,
            'CompteNum' => 25,
            'CompteLib' => 35,
            'CompAuxNum' => 22,
            'CompAuxLib' => 30,
            'PieceRef' => 22,
            'PieceDate' => 20,
            'EcritureLib' => 45,
            'Debit' => 18,
            'Credit' => 18,
            'Lettrage' => 14,
            'DateLettrage' => 20,
            'ValidDate' => 20,
            'MontantDevise' => 18,
            'Idevise' => 12,
            'EcrtureLet' => 14,
            'DateLet' => 18,
            'Montantdevise' => 18,
            'Solde' => 18,
            'CodeJournal' => 15,
            'Statut' => 16,
            'MethodePaiement' => 24,
            'DatePaiement' => 20,
            'CodeComptable' => 25,
            'Client' => 40,
            'NumFacture' => 25,
            'DateFacture' => 20,
            'MontantHT' => 20,
            'MontantTVA' => 20,
            'MontantTTC' => 20,
            'JoursRetard' => 16,
            'Tranche' => 22,
            'DateReglement' => 22,
            'CompteBanque' => 20,
        ];

        $usedWidth = 0;
        $unknownCols = [];

        foreach ($this->columns as $col) {
            if (isset($known[$col])) {
                $widths[$col] = $known[$col];
                $usedWidth += $known[$col];
            } else {
                $unknownCols[] = $col;
            }
        }

        // Distribuer l'espace restant aux colonnes inconnues
        if (!empty($unknownCols)) {
            $remaining = max($pageWidth - $usedWidth, \count($unknownCols) * 15);
            $each = (int) floor($remaining / \count($unknownCols));
            foreach ($unknownCols as $col) {
                $widths[$col] = $each;
            }
        }

        return $widths;
    }

    private function isNumericColumn(string $col): bool
    {
        return \in_array($col, [
            'Debit', 'Credit', 'Solde',
            'MontantHT', 'MontantTVA', 'MontantTTC',
            'MontantDevise', 'Montantdevise',
            'JoursRetard',
        ], true);
    }

    private function enc(string $text): string
    {
        return mb_convert_encoding($text, 'Windows-1252', 'UTF-8');
    }
}
