<?php

namespace App\Service\Pdf;

use App\Entity\Echeancier;
use App\Entity\EcheancierLine;
use setasign\Fpdi\Fpdi;
use Symfony\Component\HttpKernel\KernelInterface;

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

class EcheancierAttestationPdf extends Fpdi
{
    public function __construct(
        private readonly KernelInterface $kernel,
        private readonly Echeancier $echeancier,
    ) {
        parent::__construct();
        $this->SetTitle($this->enc('Attestation echeancier '.$this->echeancier->getReference()));
        $this->SetAuthor($this->enc('Association E-Cosplay'));
    }

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

        $this->writeHeader();
        $this->writeStatusBlock();
        $this->writeFinancialSummary();
        $this->writeEcheancesTable();
        $this->writeSepaInfo();
        $this->writeFooterAttestation();
    }

    /** @codeCoverageIgnore */
    public function Header(): void
    {
    }

    /** @codeCoverageIgnore */
    public function Footer(): void
    {
        $this->SetY(-22);
        $this->SetDrawColor(253, 140, 4);
        $this->Line(15, $this->GetY(), 195, $this->GetY());
        $this->Ln(3);
        $this->SetFont('Arial', '', 7);
        $this->SetTextColor(0, 0, 0);
        $this->Cell(190, 3, $this->enc('42 rue de Saint-Quentin - 02800 BEAUTOR - Tel: 07 66 95 70 06 - client@e-cosplay.fr'), 0, 1, 'C');
        $this->Cell(190, 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(190, 3, $this->enc('Page ').$this->PageNo().' / {nb}', 0, 0, 'C');
    }

    /** @codeCoverageIgnore */
    private function writeHeader(): void
    {
        $logo = $this->kernel->getProjectDir().'/public/logo.jpg';
        if (file_exists($logo)) {
            $this->Image($logo, 10, 8, 45);
        }

        $this->SetFont('Arial', 'B', 16);
        $this->SetXY(60, 10);
        $this->Cell(0, 8, $this->enc('ATTESTATION'), 0, 1, 'L');

        $this->SetFont('Arial', '', 9);
        $this->SetXY(60, 18);
        $this->SetTextColor(150, 150, 150);
        $this->Cell(0, 5, $this->enc('Ref. : '.$this->echeancier->getReference()), 0, 1, 'L');
        $this->SetTextColor(0, 0, 0);

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

        $this->SetFont('Arial', '', 10);
        $this->SetXY(60, 24);
        $this->Cell(0, 5, $this->enc('Emise a Beautor, le '.$formatter->format(new \DateTime())), 0, 1, 'L');

        // Client
        $customer = $this->echeancier->getCustomer();
        $y = 35;
        $this->SetFont('Arial', 'B', 11);
        $this->SetXY(120, $y);
        $name = $customer->getRaisonSociale() ?: $customer->getFullName();
        $this->Cell(0, 5, $this->enc($name), 0, 1, 'L');

        if ($address = $customer->getAddress()) {
            $y += 5;
            $this->SetXY(120, $y);
            $this->SetFont('Arial', '', 10);
            $this->Cell(0, 5, $this->enc($address), 0, 1, 'L');
        }

        $y += 5;
        $this->SetXY(120, $y);
        $this->SetFont('Arial', '', 10);
        $cityLine = ($customer->getZipCode() ?? '').' '.($customer->getCity() ?? '');
        $this->Cell(0, 5, $this->enc(trim($cityLine)), 0, 1, 'L');

        if ($customer->getEmail()) {
            $y += 5;
            $this->SetXY(120, $y);
            $this->Cell(0, 5, $this->enc($customer->getEmail()), 0, 1, 'L');
        }

        $this->Ln(10);
    }

    /** @codeCoverageIgnore */
    private function writeStatusBlock(): void
    {
        $this->SetY(65);

        $state = $this->echeancier->getState();
        $stateLabel = match ($state) {
            Echeancier::STATE_COMPLETED => 'TERMINE',
            Echeancier::STATE_ACTIVE => 'EN COURS',
            Echeancier::STATE_CANCELLED => 'ANNULE',
            Echeancier::STATE_PENDING_SETUP => 'EN ATTENTE SEPA',
            Echeancier::STATE_SIGNED => 'SIGNE',
            default => mb_strtoupper($state),
        };

        // Bandeau statut
        if (Echeancier::STATE_COMPLETED === $state) {
            $this->SetFillColor(22, 163, 74);
        } elseif (Echeancier::STATE_CANCELLED === $state) {
            $this->SetFillColor(220, 38, 38);
        } else {
            $this->SetFillColor(37, 99, 235);
        }
        $this->SetTextColor(255, 255, 255);
        $this->SetFont('Arial', 'B', 12);
        $this->Cell(0, 10, $this->enc('  STATUT : '.$stateLabel), 0, 1, 'L', true);
        $this->SetTextColor(0, 0, 0);
        $this->Ln(5);

        // Motif
        $this->SetFont('Arial', 'B', 11);
        $this->Cell(0, 6, $this->enc('OBJET'), 0, 1, 'L');
        $this->SetFont('Arial', '', 10);
        $this->MultiCell(0, 5, $this->enc($this->echeancier->getDescription()), 0, 'L');
        $this->Ln(3);
    }

    /** @codeCoverageIgnore */
    private function writeFinancialSummary(): void
    {
        $this->SetDrawColor(200, 200, 200);
        $this->Cell(0, 0.5, '', 'T', 1, 'L');
        $this->Ln(3);

        $this->SetFont('Arial', 'B', 11);
        $this->Cell(0, 6, $this->enc('RESUME FINANCIER'), 0, 1, 'L');
        $this->Ln(2);

        $labelW = 60;
        $remaining = $this->echeancier->getTotalWithMajoration() - $this->echeancier->getTotalPaid();

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, $this->enc('Creance initiale :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(0, 6, number_format((float) $this->echeancier->getTotalAmountHt(), 2, ',', ' ').' '.EURO, 0, 1, 'L');

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, $this->enc('Majoration (5%) :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 10);
        $this->SetTextColor(220, 38, 38);
        $this->Cell(0, 6, '+ '.number_format($this->echeancier->getMajoration(), 2, ',', ' ').' '.EURO, 0, 1, 'L');
        $this->SetTextColor(0, 0, 0);

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, $this->enc('Total a payer :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 11);
        $this->Cell(0, 6, number_format($this->echeancier->getTotalWithMajoration(), 2, ',', ' ').' '.EURO, 0, 1, 'L');

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, $this->enc('Total paye :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 11);
        $this->SetTextColor(22, 163, 74);
        $this->Cell(0, 6, number_format($this->echeancier->getTotalPaid(), 2, ',', ' ').' '.EURO, 0, 1, 'L');
        $this->SetTextColor(0, 0, 0);

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, $this->enc('Restant du :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 11);
        if ($remaining > 0) {
            $this->SetTextColor(220, 38, 38);
        } else {
            $this->SetTextColor(22, 163, 74);
        }
        $this->Cell(0, 6, number_format($remaining, 2, ',', ' ').' '.EURO, 0, 1, 'L');
        $this->SetTextColor(0, 0, 0);

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, $this->enc('Progression :'), 0, 0, 'L');
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(0, 6, $this->echeancier->getNbPaid().'/'.$this->echeancier->getNbLines().' echeances ('.$this->echeancier->getProgress().'%)', 0, 1, 'L');

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

    /** @codeCoverageIgnore */
    private function writeEcheancesTable(): void
    {
        $this->SetFont('Arial', 'B', 11);
        $this->Cell(0, 6, $this->enc('DETAIL DES ECHEANCES'), 0, 1, 'L');
        $this->Ln(2);

        $this->SetFont('Arial', 'B', 9);
        $this->SetFillColor(35, 35, 35);
        $this->SetTextColor(255, 255, 255);
        $this->Cell(15, 7, $this->enc('N'), 1, 0, 'C', true);
        $this->Cell(40, 7, $this->enc('Date prevue'), 1, 0, 'C', true);
        $this->Cell(35, 7, $this->enc('Montant'), 1, 0, 'C', true);
        $this->Cell(30, 7, $this->enc('Statut'), 1, 0, 'C', true);
        $this->Cell(50, 7, $this->enc('Paye le'), 1, 1, 'C', true);
        $this->SetTextColor(0, 0, 0);

        $this->SetFont('Arial', '', 9);
        $fill = false;
        $months = [1 => 'Janvier', 'Fevrier', 'Mars', 'Avril', 'Mai', 'Juin', 'Juillet', 'Aout', 'Septembre', 'Octobre', 'Novembre', 'Decembre'];

        foreach ($this->echeancier->getLines() as $line) {
            $this->SetFillColor(245, 245, 240);

            $monthName = $months[(int) $line->getScheduledAt()->format('n')] ?? '';
            $dateLabel = $line->getScheduledAt()->format('d').' '.$monthName.' '.$line->getScheduledAt()->format('Y');

            $statusLabel = match ($line->getState()) {
                EcheancierLine::STATE_OK => 'Paye',
                EcheancierLine::STATE_KO => 'Echoue',
                default => 'En attente',
            };

            $paidDate = null !== $line->getPaidAt() ? $line->getPaidAt()->format('d/m/Y H:i') : '-';

            $this->Cell(15, 6, (string) $line->getPosition(), 'B', 0, 'C', $fill);
            $this->Cell(40, 6, $this->enc($dateLabel), 'B', 0, 'L', $fill);
            $this->Cell(35, 6, number_format((float) $line->getAmount(), 2, ',', ' ').' '.EURO, 'B', 0, 'R', $fill);

            if (EcheancierLine::STATE_OK === $line->getState()) {
                $this->SetTextColor(22, 163, 74);
            } elseif (EcheancierLine::STATE_KO === $line->getState()) {
                $this->SetTextColor(220, 38, 38);
            } else {
                $this->SetTextColor(180, 130, 0);
            }
            $this->Cell(30, 6, $this->enc($statusLabel), 'B', 0, 'C', $fill);
            $this->SetTextColor(0, 0, 0);

            $this->Cell(50, 6, $this->enc($paidDate), 'B', 1, 'C', $fill);

            $fill = !$fill;
        }

        $this->Ln(5);
    }

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

        $this->SetFont('Arial', 'B', 11);
        $this->Cell(0, 6, $this->enc('INFORMATIONS SEPA'), 0, 1, 'L');
        $this->Ln(2);

        $labelW = 50;

        $this->SetFont('Arial', '', 10);
        $this->Cell($labelW, 6, 'IBAN :', 0, 0, 'L');
        $this->SetFont('Arial', 'B', 10);
        $this->Cell(0, 6, '**** **** **** '.$this->echeancier->getStripeSepaLast4(), 0, 1, 'L');

        if (null !== $this->echeancier->getStripeSepaBankName()) {
            $this->SetFont('Arial', '', 10);
            $this->Cell($labelW, 6, $this->enc('Code banque :'), 0, 0, 'L');
            $this->SetFont('Arial', 'B', 10);
            $this->Cell(0, 6, $this->echeancier->getStripeSepaBankName(), 0, 1, 'L');
        }

        if (null !== $this->echeancier->getStripeSepaCountry()) {
            $this->SetFont('Arial', '', 10);
            $this->Cell($labelW, 6, 'Pays :', 0, 0, 'L');
            $this->SetFont('Arial', 'B', 10);
            $this->Cell(0, 6, $this->echeancier->getStripeSepaCountry(), 0, 1, 'L');
        }

        $this->Ln(5);
    }

    /** @codeCoverageIgnore */
    private function writeFooterAttestation(): void
    {
        if ($this->GetY() + 30 > $this->GetPageHeight() - 25) {
            $this->AddPage();
        }

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

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

        $completed = Echeancier::STATE_COMPLETED === $this->echeancier->getState();
        if ($completed) {
            $this->MultiCell(0, 5, $this->enc(
                'La presente attestation certifie que l\'integralite des echeances de l\'echeancier '
                .$this->echeancier->getReference().' a ete reglee. Le debiteur est libere de toute obligation '
                .'de paiement au titre de cet echeancier.'
            ), 0, 'L');
        } else {
            $remaining = $this->echeancier->getTotalWithMajoration() - $this->echeancier->getTotalPaid();
            $this->MultiCell(0, 5, $this->enc(
                'La presente attestation est un document de situation de l\'echeancier '
                .$this->echeancier->getReference().'. Le solde restant du est de '
                .number_format($remaining, 2, ',', ' ').' EUR.'
            ), 0, 'L');
        }

        $this->SetTextColor(0, 0, 0);
        $this->Ln(5);

        $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(5);

        $this->SetFont('Arial', 'B', 9);
        $this->Cell(85, 5, $this->enc('Pour Association E-Cosplay :'), 0, 1, 'L');
        $this->Ln(2);
        $this->SetFont('Arial', '', 10);
        $this->Cell(85, 20, '{{Sign;type=signature;role=First Party}}', 0, 1, 'L');

        $this->Ln(5);
        $this->SetFont('Arial', 'I', 8);
        $this->SetTextColor(150, 150, 150);
        $this->Cell(0, 4, $this->enc('Signature electronique via DocuSeal - Valeur juridique (reglement eIDAS, art. 1367 Code civil)'), 0, 1, 'C');
        $this->SetTextColor(0, 0, 0);
    }

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