<?php

namespace App\Tests\Entity;

use App\Entity\Devis;
use App\Entity\OrderNumber;
use PHPUnit\Framework\TestCase;
use Symfony\Component\HttpFoundation\File\File;

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

    private function createDevis(): Devis
    {
        return new Devis(new OrderNumber('04/2026-00001'), self::HMAC_SECRET);
    }

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

        $this->assertNull($devis->getId());
        $this->assertSame($order, $devis->getOrderNumber());
        $this->assertSame(Devis::STATE_CREATED, $devis->getState());
        $this->assertNotEmpty($devis->getHmac());
        $this->assertInstanceOf(\DateTimeImmutable::class, $devis->getCreatedAt());
        $this->assertNull($devis->getUpdatedAt());
        $this->assertCount(0, $devis->getLines());
    }

    public function testState(): void
    {
        $devis = $this->createDevis();
        $devis->setState(Devis::STATE_SEND);
        $this->assertSame(Devis::STATE_SEND, $devis->getState());

        $devis->setState(Devis::STATE_ACCEPTED);
        $this->assertSame(Devis::STATE_ACCEPTED, $devis->getState());
    }

    public function testRaisonMessage(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getRaisonMessage());

        $devis->setRaisonMessage('Trop cher');
        $this->assertSame('Trop cher', $devis->getRaisonMessage());
    }

    public function testTotals(): void
    {
        $devis = $this->createDevis();
        $this->assertSame('0.00', $devis->getTotalHt());
        $this->assertSame('0.00', $devis->getTotalTva());
        $this->assertSame('0.00', $devis->getTotalTtc());

        $devis->setTotalHt('1000.00');
        $devis->setTotalTva('200.00');
        $devis->setTotalTtc('1200.00');

        $this->assertSame('1000.00', $devis->getTotalHt());
        $this->assertSame('200.00', $devis->getTotalTva());
        $this->assertSame('1200.00', $devis->getTotalTtc());
    }

    public function testSubmitterIds(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getSubmitterSiteconseilId());
        $this->assertNull($devis->getSubmitterCustomerId());

        $devis->setSubmitterSiteconseilId(42);
        $devis->setSubmitterCustomerId(99);

        $this->assertSame(42, $devis->getSubmitterSiteconseilId());
        $this->assertSame(99, $devis->getSubmitterCustomerId());
    }

    public function testUnsignedPdf(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getUnsignedPdf());
        $this->assertNull($devis->getUnsignedPdfFile());

        $devis->setUnsignedPdf('devis-001.pdf');
        $this->assertSame('devis-001.pdf', $devis->getUnsignedPdf());

        $tmpFile = tempnam(sys_get_temp_dir(), 'devis_');
        file_put_contents($tmpFile, 'pdf');
        $file = new File($tmpFile);

        $devis->setUnsignedPdfFile($file);
        $this->assertSame($file, $devis->getUnsignedPdfFile());
        $this->assertInstanceOf(\DateTimeImmutable::class, $devis->getUpdatedAt());

        $devis->setUnsignedPdfFile(null);
        $this->assertNull($devis->getUnsignedPdfFile());

        @unlink($tmpFile);
    }

    public function testSignedPdf(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getSignedPdf());
        $this->assertNull($devis->getSignedPdfFile());

        $devis->setSignedPdf('devis-signed.pdf');
        $this->assertSame('devis-signed.pdf', $devis->getSignedPdf());

        $tmpFile = tempnam(sys_get_temp_dir(), 'devis_s_');
        file_put_contents($tmpFile, 'pdf');
        $file = new File($tmpFile);

        $devis->setSignedPdfFile($file);
        $this->assertSame($file, $devis->getSignedPdfFile());
        $this->assertInstanceOf(\DateTimeImmutable::class, $devis->getUpdatedAt());

        @unlink($tmpFile);
    }

    public function testAuditPdf(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getAuditPdf());
        $this->assertNull($devis->getAuditPdfFile());

        $devis->setAuditPdf('devis-audit.pdf');
        $this->assertSame('devis-audit.pdf', $devis->getAuditPdf());

        $tmpFile = tempnam(sys_get_temp_dir(), 'devis_a_');
        file_put_contents($tmpFile, 'pdf');
        $file = new File($tmpFile);

        $devis->setAuditPdfFile($file);
        $this->assertSame($file, $devis->getAuditPdfFile());
        $this->assertInstanceOf(\DateTimeImmutable::class, $devis->getUpdatedAt());

        @unlink($tmpFile);
    }

    public function testVerifyHmacValid(): void
    {
        $devis = $this->createDevis();
        $this->assertTrue($devis->verifyHmac(self::HMAC_SECRET));
    }

    public function testVerifyHmacInvalid(): void
    {
        $devis = $this->createDevis();
        $this->assertFalse($devis->verifyHmac('wrong-secret'));
    }

    public function testSetCustomer(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getCustomer());

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

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

    public function testSubmissionId(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getSubmissionId());

        $devis->setSubmissionId('sub_xyz789');
        $this->assertSame('sub_xyz789', $devis->getSubmissionId());

        $devis->setSubmissionId(null);
        $this->assertNull($devis->getSubmissionId());
    }

    public function testSetAdvert(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getAdvert());

        $order = new OrderNumber('04/2026-00099');
        $advert = new \App\Entity\Advert($order, self::HMAC_SECRET);
        $devis->setAdvert($advert);
        $this->assertSame($advert, $devis->getAdvert());

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

    public function testLinesCollection(): void
    {
        $devis = $this->createDevis();
        $this->assertCount(0, $devis->getLines());

        $line = new \App\Entity\DevisLine($devis, 'Service web', '200.00', 1);
        $result = $devis->addLine($line);

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

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

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

    public function testSetUpdatedAt(): void
    {
        $devis = $this->createDevis();
        $this->assertNull($devis->getUpdatedAt());

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

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

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

    public function testStateConstants(): void
    {
        $this->assertSame('created', Devis::STATE_CREATED);
        $this->assertSame('send', Devis::STATE_SEND);
        $this->assertSame('accepted', Devis::STATE_ACCEPTED);
        $this->assertSame('refused', Devis::STATE_REFUSED);
        $this->assertSame('cancel', Devis::STATE_CANCEL);
    }
}
