<?php

namespace App\Tests\Service\Pdf;

use App\Entity\Advert;
use App\Entity\AdvertLine;
use App\Entity\Customer;
use App\Entity\OrderNumber;
use App\Service\Pdf\AdvertPdf;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpKernel\KernelInterface;

class AdvertPdfTest extends TestCase
{
    private KernelInterface $kernel;
    private string $projectDir;

    protected function setUp(): void
    {
        $this->projectDir = sys_get_temp_dir().'/advert-pdf-test-'.bin2hex(random_bytes(4));
        mkdir($this->projectDir.'/public', 0775, true);

        $this->kernel = $this->createStub(KernelInterface::class);
        $this->kernel->method('getProjectDir')->willReturn($this->projectDir);
    }

    protected function tearDown(): void
    {
        $this->removeDir($this->projectDir);
    }

    private function removeDir(string $dir): void
    {
        if (!is_dir($dir)) {
            return;
        }
        foreach (scandir($dir) as $item) {
            if ('.' === $item || '..' === $item) {
                continue;
            }
            $path = $dir.'/'.$item;
            is_dir($path) ? $this->removeDir($path) : unlink($path);
        }
        rmdir($dir);
    }

    private function makeAdvert(bool $withCustomer = true, bool $withTva = false): Advert
    {
        $orderNumber = new OrderNumber('04/2026-00001');
        $advert = new Advert($orderNumber, 'secret');
        $advert->setTotalHt('100.00');
        $advert->setTotalTva($withTva ? '20.00' : '0.00');
        $advert->setTotalTtc($withTva ? '120.00' : '100.00');

        if ($withCustomer) {
            $user = new \App\Entity\User();
            $user->setEmail('client@test.fr');
            $user->setFirstName('Jean');
            $user->setLastName('Dupont');
            $user->setPassword('h');
            $customer = new Customer($user);
            $customer->setRaisonSociale('ACME SARL');
            $customer->setAddress('1 rue de la Paix');
            $customer->setAddress2('Bat A');
            $customer->setZipCode('75001');
            $customer->setCity('Paris');
            $advert->setCustomer($customer);
        }

        return $advert;
    }

    // ─── __construct — without urlGenerator (qrBase64 stays empty) ───────────

    public function testConstructWithoutUrlGeneratorAndNoLines(): void
    {
        $advert = $this->makeAdvert();
        $pdf = new AdvertPdf($this->kernel, $advert);

        // The object was constructed without throwing
        $this->assertInstanceOf(AdvertPdf::class, $pdf);
    }

    public function testConstructWithLines(): void
    {
        $advert = $this->makeAdvert();
        $line1 = new AdvertLine($advert, 'Service A', '50.00', 1);
        $line1->setDescription('Description A');
        $advert->addLine($line1);

        $line2 = new AdvertLine($advert, 'Service B', '50.00', 2);
        // No description (empty string branch)
        $advert->addLine($line2);

        $pdf = new AdvertPdf($this->kernel, $advert);
        $this->assertInstanceOf(AdvertPdf::class, $pdf);
    }

    // ─── generate — without urlGenerator, no items (covers basic path) ───────

    public function testGenerateWithNoItemsAndNoTva(): void
    {
        $advert = $this->makeAdvert();
        $pdf = new AdvertPdf($this->kernel, $advert);
        $pdf->generate();

        $output = $pdf->Output('S');
        $this->assertStringStartsWith('%PDF', $output);
    }

    public function testGenerateWithItemsAndTva(): void
    {
        $advert = $this->makeAdvert(true, true); // with TVA
        $line = new AdvertLine($advert, 'Prestation web', '100.00', 1);
        $line->setDescription('Realisation site vitrine');
        $advert->addLine($line);

        $pdf = new AdvertPdf($this->kernel, $advert);
        $pdf->generate();

        $output = $pdf->Output('S');
        $this->assertStringStartsWith('%PDF', $output);
    }

    public function testGenerateWithManyItemsTriggersNewPage(): void
    {
        // Add enough items to force an extra page (GetY() + 30 > 220)
        $advert = $this->makeAdvert();
        for ($i = 1; $i <= 20; ++$i) {
            $line = new AdvertLine($advert, 'Item '.$i, '5.00', $i);
            $line->setDescription(str_repeat('Long description text. ', 5));
            $advert->addLine($line);
        }

        $pdf = new AdvertPdf($this->kernel, $advert);
        $pdf->generate();

        $output = $pdf->Output('S');
        $this->assertStringStartsWith('%PDF', $output);
    }

    public function testGenerateWithLogoFile(): void
    {
        // Create a small real JPEG (1x1 pixel) so FPDF Image() succeeds
        $logoPath = $this->projectDir.'/public/logo.jpg';
        // Minimal valid JPEG bytes (1x1 white pixel)
        $jpegData = base64_decode('/9j/4AAQSkZJRgABAQEAYABgAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgNDRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjL/wAARCAABAAEDASIAAhEBAxEB/8QAFAABAAAAAAAAAAAAAAAAAAAACf/EABQQAQAAAAAAAAAAAAAAAAAAAAD/xAAUAQEAAAAAAAAAAAAAAAAAAAAA/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEQMRAD8AJQAB/9k=');
        file_put_contents($logoPath, $jpegData);

        $advert = $this->makeAdvert();
        $pdf = new AdvertPdf($this->kernel, $advert);
        $pdf->generate();

        $output = $pdf->Output('S');
        $this->assertStringStartsWith('%PDF', $output);
    }

    public function testGenerateWithNoCustomer(): void
    {
        $advert = $this->makeAdvert(false); // no customer
        $pdf = new AdvertPdf($this->kernel, $advert);
        $pdf->generate();

        $output = $pdf->Output('S');
        $this->assertStringStartsWith('%PDF', $output);
    }

    public function testConstructWithUrlGenerator(): void
    {
        $advert = $this->makeAdvert();

        $urlGenerator = $this->createStub(\Symfony\Component\Routing\Generator\UrlGeneratorInterface::class);
        $urlGenerator->method('generate')->willReturn('https://example.com/pay/04-2026-00001');

        $pdf = new AdvertPdf($this->kernel, $advert, $urlGenerator);
        $this->assertInstanceOf(AdvertPdf::class, $pdf);

        // generate() with qrBase64 set → covers displayQrCode (ignored) but also the generate() path
        $pdf->generate();
        $output = $pdf->Output('S');
        $this->assertStringStartsWith('%PDF', $output);
    }
}
