<?php

namespace App\Service\Pdf;

use App\Entity\AttestationCustom;
use Endroid\QrCode\Builder\Builder;
use Endroid\QrCode\Writer\PngWriter;
use setasign\Fpdi\Fpdi;
use Symfony\Component\HttpKernel\KernelInterface;
use Symfony\Component\Routing\Generator\UrlGeneratorInterface;

class AttestationCustomPdf extends Fpdi
{
    private string $qrBase64 = '';
    private string $verifyUrl = '';

    public function __construct(
        private readonly KernelInterface $kernel,
        private readonly AttestationCustom $attestation,
        ?UrlGeneratorInterface $urlGenerator = null,
    ) {
        parent::__construct();
        $this->SetTitle($this->enc('Attestation '.$this->attestation->getReference().' - '.$this->attestation->getTitle()));
        $this->SetAuthor($this->enc('Association E-Cosplay'));

        if (null !== $urlGenerator) {
            $this->verifyUrl = $urlGenerator->generate('app_attestation_custom_verify', [
                'id' => $attestation->getId(),
                'hmac' => $attestation->getHmac(),
            ], UrlGeneratorInterface::ABSOLUTE_URL);

            $builder = new Builder(
                writer: new PngWriter(),
                data: $this->verifyUrl,
                size: 200,
                margin: 10,
            );
            $this->qrBase64 = 'data:image/png;base64,'.base64_encode($builder->build()->getString());
        }
    }

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

        $this->writeHeader();
        $this->writeBody();
        $this->writeQrCode();
        $this->writeSignature();
    }

    /** @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->attestation->getReference().' - HMAC : '.substr($this->attestation->getHmac(), 0, 12).'...'), 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($this->attestation->getCreatedAt())), 0, 1, 'L');

        $this->Ln(10);
    }

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

        // Titre de l'attestation
        $this->SetFont('Arial', 'B', 13);
        $this->SetFillColor(250, 191, 4);
        $this->Cell(0, 10, $this->enc('  OBJET : '.$this->attestation->getTitle()), 0, 1, 'L', true);
        $this->Ln(8);

        // Phrase d'ouverture
        $this->SetFont('Arial', '', 11);
        $this->MultiCell(0, 6, $this->enc(
            'Je soussigne(e), President(e) de l\'Association E-Cosplay et le bureau de l\'association, '
            .'atteste les elements suivants :'
        ), 0, 'L');
        $this->Ln(5);

        // Liste des elements
        $this->SetFont('Arial', '', 10);
        foreach ($this->attestation->getItems() as $i => $item) {
            $this->SetFont('Arial', 'B', 10);
            $this->Cell(8, 6, ($i + 1).'.', 0, 0, 'R');
            $this->SetFont('Arial', '', 10);
            $this->Cell(3, 6, '', 0, 0);
            $this->MultiCell(0, 6, $this->enc($item), 0, 'L');
            $this->Ln(2);
        }

        $this->Ln(5);

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

        $this->SetFont('Arial', '', 11);
        $this->MultiCell(0, 6, $this->enc(
            'La presente attestation est etablie pour faire valoir les droits de l\'Association E-Cosplay. '
            .'Les elements presentes ci-dessus sont conformes et veridiques.'
        ), 0, 'L');
        $this->Ln(3);

        $this->SetFont('Arial', 'I', 9);
        $this->SetTextColor(150, 150, 150);
        $this->MultiCell(0, 4, $this->enc(
            'Toute fausse declaration est susceptible de poursuites conformement aux articles 441-1 et suivants du Code penal. '
            .'Ce document est protege par un code HMAC d\'integrite.'
        ), 0, 'L');
        $this->SetTextColor(0, 0, 0);
        $this->Ln(5);
    }

    /** @codeCoverageIgnore */
    private function writeQrCode(): void
    {
        if ('' === $this->qrBase64) {
            return;
        }

        if ($this->GetY() + 45 > $this->GetPageHeight() - 25) {
            $this->AddPage();
        }

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

        $y = $this->GetY();

        $tmpQr = tempnam(sys_get_temp_dir(), 'qr_').'.png';
        $pngData = base64_decode(str_replace('data:image/png;base64,', '', $this->qrBase64));
        file_put_contents($tmpQr, $pngData);

        $this->Image($tmpQr, 15, $y, 25, 25);
        @unlink($tmpQr);

        $this->SetXY(45, $y);
        $this->SetFont('Arial', 'B', 9);
        $this->Cell(0, 5, $this->enc('Verification publique de cette attestation'), 0, 1, 'L');
        $this->SetX(45);
        $this->SetFont('Arial', '', 8);
        $this->SetTextColor(100, 100, 100);
        $this->Cell(0, 4, $this->enc('Scannez le QR code ou utilisez le lien ci-dessous'), 0, 1, 'L');
        $this->SetX(45);
        $this->SetFont('Arial', '', 7);
        $this->SetTextColor(37, 99, 235);
        $this->Cell(0, 4, $this->enc($this->verifyUrl), 0, 1, 'L');
        $this->SetTextColor(0, 0, 0);

        $this->SetY($y + 28);
        $this->Ln(3);
    }

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

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

        $this->SetFont('Arial', 'B', 9);
        $this->Cell(0, 5, $this->enc('Pour le bureau de l\'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(3);
        $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');
    }
}
