<?php

namespace Tests\Unit\Ticket;

use App\Domains\Auth\Models\User;
use App\Domains\Tenant\Models\Tenant;
use App\Domains\Ticket\Models\Ticket;
use Illuminate\Support\Carbon;
use Tests\TestCase;

class TicketTest extends TestCase
{
    protected function tearDown(): void
    {
        Carbon::setTestNow();

        parent::tearDown();
    }

    public function test_it_maps_its_dates_and_relations(): void
    {
        $ticket = new Ticket;
        $ticket->setRawAttributes([
            'source_catalog_item_id' => '20',
            'source_variant_id' => '30',
            'starts_at' => '2026-07-21 10:00:00',
            'expires_at' => '2026-07-22 10:00:00',
            'used_at' => null,
            'user_id' => '10',
        ]);

        $this->assertSame('tickets', $ticket->getTable());
        $this->assertFalse($ticket->usesTimestamps());
        $this->assertSame(20, $ticket->source_catalog_item_id);
        $this->assertSame(30, $ticket->source_variant_id);
        $this->assertInstanceOf(Carbon::class, $ticket->starts_at);
        $this->assertInstanceOf(Carbon::class, $ticket->expires_at);
        $this->assertNull($ticket->used_at);
        $this->assertSame(10, $ticket->user_id);
        $this->assertInstanceOf(Tenant::class, $ticket->tenant()->getRelated());
        $this->assertInstanceOf(User::class, $ticket->user()->getRelated());
    }

    public function test_unused_ticket_without_date_restrictions_is_valid(): void
    {
        $this->assertTrue((new Ticket)->isValid());
    }

    public function test_ticket_is_invalid_before_its_start_date(): void
    {
        Carbon::setTestNow('2026-07-21 10:00:00');
        $ticket = new Ticket(['starts_at' => now()->addSecond()]);

        $this->assertFalse($ticket->isValid());
    }

    public function test_ticket_is_valid_when_its_start_date_is_reached(): void
    {
        Carbon::setTestNow('2026-07-21 10:00:00');
        $ticket = new Ticket(['starts_at' => now()]);

        $this->assertTrue($ticket->isValid());
    }

    public function test_ticket_is_invalid_when_it_expires(): void
    {
        Carbon::setTestNow('2026-07-21 10:00:00');
        $ticket = new Ticket(['expires_at' => now()]);

        $this->assertFalse($ticket->isValid());
    }

    public function test_used_ticket_is_invalid(): void
    {
        $ticket = new Ticket(['used_at' => now()->subSecond()]);

        $this->assertFalse($ticket->isValid());
    }

    public function test_it_appends_computed_status_fields(): void
    {
        Carbon::setTestNow('2026-07-21 10:00:00');
        $ticket = new Ticket([
            'starts_at' => now()->subHour(),
            'expires_at' => now()->addHour(),
        ]);

        $attributes = $ticket->toArray();

        $this->assertTrue($attributes['is_valid']);
        $this->assertFalse($attributes['is_expired']);
        $this->assertFalse($attributes['is_used']);
    }

    public function test_unused_ticket_is_expired_when_its_expiration_date_is_reached(): void
    {
        Carbon::setTestNow('2026-07-21 10:00:00');
        $ticket = new Ticket(['expires_at' => now()]);

        $this->assertFalse($ticket->is_valid);
        $this->assertTrue($ticket->is_expired);
        $this->assertFalse($ticket->is_used);
    }

    public function test_used_ticket_is_not_reported_as_expired(): void
    {
        Carbon::setTestNow('2026-07-21 10:00:00');
        $ticket = new Ticket([
            'expires_at' => now()->subHour(),
            'used_at' => now()->subDay(),
        ]);

        $this->assertFalse($ticket->is_valid);
        $this->assertFalse($ticket->is_expired);
        $this->assertTrue($ticket->is_used);
    }
}
