<?php

declare(strict_types=1);

namespace App\Tests\Unit\Shared\Infrastructure\Audit;

use App\Shared\Domain\CorrelationId;
use App\Shared\Infrastructure\Audit\CorrelationIdHolder;
use PHPUnit\Framework\TestCase;

/**
 * @see Story 1.7 - T3: Correlation ID
 */
final class CorrelationIdHolderTest extends TestCase
{
    protected function tearDown(): void
    {
        CorrelationIdHolder::clear();
    }

    public function testInitiallyReturnsNull(): void
    {
        CorrelationIdHolder::clear();

        $this->assertNull(CorrelationIdHolder::get());
    }

    public function testSetAndGetCorrelationId(): void
    {
        $correlationId = CorrelationId::generate();

        CorrelationIdHolder::set($correlationId);

        $this->assertSame($correlationId, CorrelationIdHolder::get());
    }

    public function testClearRemovesCorrelationId(): void
    {
        CorrelationIdHolder::set(CorrelationId::generate());

        CorrelationIdHolder::clear();

        $this->assertNull(CorrelationIdHolder::get());
    }

    public function testSetOverwritesPreviousValue(): void
    {
        $first = CorrelationId::generate();
        $second = CorrelationId::generate();

        CorrelationIdHolder::set($first);
        CorrelationIdHolder::set($second);

        $this->assertSame($second, CorrelationIdHolder::get());
    }

    public function testGetOrGenerateReturnsExistingId(): void
    {
        $existing = CorrelationId::generate();
        CorrelationIdHolder::set($existing);

        $result = CorrelationIdHolder::getOrGenerate();

        $this->assertSame($existing, $result);
    }

    public function testGetOrGenerateCreatesNewIdWhenNoneSet(): void
    {
        CorrelationIdHolder::clear();

        $result = CorrelationIdHolder::getOrGenerate();

        $this->assertNotNull($result);
        $this->assertInstanceOf(CorrelationId::class, $result);
    }

    public function testGetOrGenerateStoresGeneratedId(): void
    {
        CorrelationIdHolder::clear();

        $first = CorrelationIdHolder::getOrGenerate();
        $second = CorrelationIdHolder::getOrGenerate();

        // Should return the same generated ID, not create a new one each time
        $this->assertSame($first, $second);
    }
}
