<?php

namespace App\Tests\Entity;

use App\Entity\Advert;
use App\Entity\Facture;
use App\Entity\OrderNumber;
use PHPUnit\Framework\TestCase;

class FactureTest extends TestCase
{
    private const HMAC_SECRET = 'test-secret';

    public function testConstructor(): void
    {
        $order = new OrderNumber('04/2026-00001');
        $facture = new Facture($order, self::HMAC_SECRET);

        $this->assertNull($facture->getId());
        $this->assertSame($order, $facture->getOrderNumber());
        $this->assertNull($facture->getAdvert());
        $this->assertSame(0, $facture->getSplitIndex());
        $this->assertNotEmpty($facture->getHmac());
        $this->assertInstanceOf(\DateTimeImmutable::class, $facture->getCreatedAt());
    }

    public function testSetAdvert(): void
    {
        $order = new OrderNumber('04/2026-00002');
        $facture = new Facture($order, self::HMAC_SECRET);

        $advert = $this->createStub(Advert::class);
        $facture->setAdvert($advert);
        $this->assertSame($advert, $facture->getAdvert());

        $facture->setAdvert(null);
        $this->assertNull($facture->getAdvert());
    }

    public function testSplitIndex(): void
    {
        $order = new OrderNumber('04/2026-00003');
        $facture = new Facture($order, self::HMAC_SECRET);

        $this->assertSame(0, $facture->getSplitIndex());

        $facture->setSplitIndex(2);
        $this->assertSame(2, $facture->getSplitIndex());
    }

    public function testGetInvoiceNumberNoSplit(): void
    {
        $order = new OrderNumber('04/2026-00004');
        $facture = new Facture($order, self::HMAC_SECRET);

        $this->assertSame('04/2026-00004', $facture->getInvoiceNumber());
    }

    public function testGetInvoiceNumberWithSplit(): void
    {
        $order = new OrderNumber('04/2026-00005');
        $facture = new Facture($order, self::HMAC_SECRET);
        $facture->setSplitIndex(3);

        $this->assertSame('04/2026-00005-3', $facture->getInvoiceNumber());
    }

    public function testVerifyHmacValid(): void
    {
        $order = new OrderNumber('04/2026-00006');
        $facture = new Facture($order, self::HMAC_SECRET);

        $this->assertTrue($facture->verifyHmac(self::HMAC_SECRET));
    }

    public function testVerifyHmacInvalid(): void
    {
        $order = new OrderNumber('04/2026-00007');
        $facture = new Facture($order, self::HMAC_SECRET);

        $this->assertFalse($facture->verifyHmac('wrong-secret'));
    }

    public function testStateConstants(): void
    {
        $this->assertSame('created', Facture::STATE_CREATED);
        $this->assertSame('send', Facture::STATE_SEND);
        $this->assertSame('paid', Facture::STATE_PAID);
        $this->assertSame('cancel', Facture::STATE_CANCEL);
    }

    public function testStateGetterSetter(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00010'), self::HMAC_SECRET);

        $this->assertSame(Facture::STATE_CREATED, $facture->getState());

        $facture->setState(Facture::STATE_SEND);
        $this->assertSame(Facture::STATE_SEND, $facture->getState());

        $facture->setState(Facture::STATE_PAID);
        $this->assertSame(Facture::STATE_PAID, $facture->getState());

        $facture->setState(Facture::STATE_CANCEL);
        $this->assertSame(Facture::STATE_CANCEL, $facture->getState());
    }

    public function testSetCustomer(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00011'), self::HMAC_SECRET);

        $this->assertNull($facture->getCustomer());

        $customer = $this->createStub(\App\Entity\Customer::class);
        $facture->setCustomer($customer);
        $this->assertSame($customer, $facture->getCustomer());

        $facture->setCustomer(null);
        $this->assertNull($facture->getCustomer());
    }

    public function testTotals(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00012'), self::HMAC_SECRET);

        $this->assertSame('0.00', $facture->getTotalHt());
        $this->assertSame('0.00', $facture->getTotalTva());
        $this->assertSame('0.00', $facture->getTotalTtc());

        $facture->setTotalHt('800.00');
        $facture->setTotalTva('160.00');
        $facture->setTotalTtc('960.00');

        $this->assertSame('800.00', $facture->getTotalHt());
        $this->assertSame('160.00', $facture->getTotalTva());
        $this->assertSame('960.00', $facture->getTotalTtc());
    }

    public function testIsPaid(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00013'), self::HMAC_SECRET);

        $this->assertFalse($facture->isPaid());

        $facture->setIsPaid(true);
        $this->assertTrue($facture->isPaid());

        $facture->setIsPaid(false);
        $this->assertFalse($facture->isPaid());
    }

    public function testPaidAt(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00014'), self::HMAC_SECRET);

        $this->assertNull($facture->getPaidAt());

        $date = new \DateTimeImmutable('2026-03-15');
        $facture->setPaidAt($date);
        $this->assertSame($date, $facture->getPaidAt());

        $facture->setPaidAt(null);
        $this->assertNull($facture->getPaidAt());
    }

    public function testPaidMethod(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00015'), self::HMAC_SECRET);

        $this->assertNull($facture->getPaidMethod());

        $facture->setPaidMethod('stripe');
        $this->assertSame('stripe', $facture->getPaidMethod());

        $facture->setPaidMethod(null);
        $this->assertNull($facture->getPaidMethod());
    }

    public function testFacturePdf(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00016'), self::HMAC_SECRET);

        $this->assertNull($facture->getFacturePdf());

        $facture->setFacturePdf('facture-001.pdf');
        $this->assertSame('facture-001.pdf', $facture->getFacturePdf());

        $facture->setFacturePdf(null);
        $this->assertNull($facture->getFacturePdf());
    }

    public function testFacturePdfFileSetsUpdatedAt(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00017'), self::HMAC_SECRET);

        $this->assertNull($facture->getFacturePdfFile());
        $this->assertNull($facture->getUpdatedAt());

        $tmpFile = tempnam(sys_get_temp_dir(), 'facture_');
        file_put_contents($tmpFile, 'pdf');
        $file = new \Symfony\Component\HttpFoundation\File\File($tmpFile);

        $facture->setFacturePdfFile($file);
        $this->assertSame($file, $facture->getFacturePdfFile());
        $this->assertInstanceOf(\DateTimeImmutable::class, $facture->getUpdatedAt());

        $facture->setFacturePdfFile(null);
        $this->assertNull($facture->getFacturePdfFile());

        @unlink($tmpFile);
    }

    public function testSetUpdatedAt(): void
    {
        $facture = new Facture(new OrderNumber('04/2026-00018'), self::HMAC_SECRET);

        $this->assertNull($facture->getUpdatedAt());

        $now = new \DateTimeImmutable();
        $result = $facture->setUpdatedAt($now);

        $this->assertSame($now, $facture->getUpdatedAt());
        $this->assertSame($facture, $result);

        $facture->setUpdatedAt(null);
        $this->assertNull($facture->getUpdatedAt());
    }

    public function testLinesCollection(): void
    {
        $order = new OrderNumber('04/2026-00019');
        $facture = new Facture($order, self::HMAC_SECRET);

        $this->assertCount(0, $facture->getLines());

        $line = new \App\Entity\FactureLine($facture, 'Hébergement', '50.00', 1);
        $result = $facture->addLine($line);

        $this->assertSame($facture, $result);
        $this->assertCount(1, $facture->getLines());
        $this->assertTrue($facture->getLines()->contains($line));

        // Adding the same line again should not duplicate
        $facture->addLine($line);
        $this->assertCount(1, $facture->getLines());

        $facture->removeLine($line);
        $this->assertCount(0, $facture->getLines());
    }
}
