<?php

namespace App\Tests\Entity;

use App\Entity\Billet;
use App\Entity\BilletBuyer;
use App\Entity\BilletOrder;
use PHPUnit\Framework\TestCase;

class BilletOrderTest extends TestCase
{
    public function testDefaults(): void
    {
        $ticket = new BilletOrder();

        self::assertNull($ticket->getId());
        self::assertNull($ticket->getBilletBuyer());
        self::assertNull($ticket->getBillet());
        self::assertNull($ticket->getBilletName());
        self::assertSame(0, $ticket->getUnitPriceHT());
        self::assertSame(0.0, $ticket->getUnitPriceHTDecimal());
        self::assertSame(BilletOrder::STATE_VALID, $ticket->getState());
        self::assertTrue($ticket->isValid());
        self::assertSame('', $ticket->getSecurityKey());
        self::assertNull($ticket->isInvitation());
        self::assertNull($ticket->getFirstScannedAt());
        self::assertMatchesRegularExpression('/^ETICKET-[A-Z0-9]{4}-[A-Z0-9]{4}-[A-Z0-9]{4}$/', $ticket->getReference());
        self::assertInstanceOf(\DateTimeImmutable::class, $ticket->getCreatedAt());
    }

    public function testSetAndGetBilletBuyer(): void
    {
        $ticket = new BilletOrder();
        $buyer = new BilletBuyer();
        $result = $ticket->setBilletBuyer($buyer);

        self::assertSame($buyer, $ticket->getBilletBuyer());
        self::assertSame($ticket, $result);
    }

    public function testSetAndGetBillet(): void
    {
        $ticket = new BilletOrder();
        $billet = new Billet();
        $result = $ticket->setBillet($billet);

        self::assertSame($billet, $ticket->getBillet());
        self::assertSame($ticket, $result);
    }

    public function testSetAndGetBilletName(): void
    {
        $ticket = new BilletOrder();
        $result = $ticket->setBilletName('Entree VIP');

        self::assertSame('Entree VIP', $ticket->getBilletName());
        self::assertSame($ticket, $result);
    }

    public function testSetAndGetUnitPriceHT(): void
    {
        $ticket = new BilletOrder();
        $result = $ticket->setUnitPriceHT(1500);

        self::assertSame(1500, $ticket->getUnitPriceHT());
        self::assertSame(15.0, $ticket->getUnitPriceHTDecimal());
        self::assertSame($ticket, $result);
    }

    public function testSetAndGetState(): void
    {
        $ticket = new BilletOrder();
        $result = $ticket->setState(BilletOrder::STATE_INVALID);

        self::assertSame(BilletOrder::STATE_INVALID, $ticket->getState());
        self::assertFalse($ticket->isValid());
        self::assertSame($ticket, $result);

        $ticket->setState(BilletOrder::STATE_EXPIRED);
        self::assertSame(BilletOrder::STATE_EXPIRED, $ticket->getState());
        self::assertFalse($ticket->isValid());

        $ticket->setState(BilletOrder::STATE_VALID);
        self::assertTrue($ticket->isValid());
    }

    public function testSetAndGetSecurityKey(): void
    {
        $ticket = new BilletOrder();
        $result = $ticket->setSecurityKey('ABC123');

        self::assertSame('ABC123', $ticket->getSecurityKey());
        self::assertSame($ticket, $result);
    }

    public function testGenerateSecurityKey(): void
    {
        $key = BilletOrder::generateSecurityKey('ETICKET-ABCD-1234-EFGH', 'my-secret');

        self::assertSame(16, \strlen($key));
        self::assertMatchesRegularExpression('/^[A-F0-9]{16}$/', $key);

        $key2 = BilletOrder::generateSecurityKey('ETICKET-ABCD-1234-EFGH', 'my-secret');
        self::assertSame($key, $key2);

        $key3 = BilletOrder::generateSecurityKey('ETICKET-XXXX-YYYY-ZZZZ', 'my-secret');
        self::assertNotSame($key, $key3);
    }

    public function testSetAndGetIsInvitation(): void
    {
        $ticket = new BilletOrder();
        $result = $ticket->setIsInvitation(true);

        self::assertTrue($ticket->isInvitation());
        self::assertSame($ticket, $result);

        $ticket->setIsInvitation(null);
        self::assertNull($ticket->isInvitation());
    }

    public function testSetAndGetFirstScannedAt(): void
    {
        $ticket = new BilletOrder();
        $date = new \DateTimeImmutable();
        $result = $ticket->setFirstScannedAt($date);

        self::assertSame($date, $ticket->getFirstScannedAt());
        self::assertSame($ticket, $result);
    }

    public function testUniqueReferences(): void
    {
        $t1 = new BilletOrder();
        $t2 = new BilletOrder();

        self::assertNotSame($t1->getReference(), $t2->getReference());
    }
}
