<?php

declare(strict_types=1);

namespace App\Shared\Infrastructure\Audit;

use App\Shared\Domain\CorrelationId;

/**
 * Thread-local storage for correlation ID.
 *
 * Allows any part of the application to access the current request's
 * correlation ID for audit logging and distributed tracing.
 *
 * For HTTP requests, the CorrelationIdMiddleware sets the ID.
 * For async handlers and CRON jobs, getOrGenerate() auto-creates one.
 *
 * NOTE: Static methods are used here because PHP lacks native thread-local
 * storage (unlike Java's ThreadLocal). This is an accepted exception to the
 * "no static" rule - see project-context.md "Nuance PHP 8.5 sur No Static".
 *
 * @see Story 1.7 - T3: Correlation ID
 */
final class CorrelationIdHolder
{
    private static ?CorrelationId $correlationId = null;

    public static function set(CorrelationId $correlationId): void
    {
        self::$correlationId = $correlationId;
    }

    /**
     * Get current correlation ID, or null if not set.
     *
     * Use getOrGenerate() when you need a correlation ID guaranteed.
     */
    public static function get(): ?CorrelationId
    {
        return self::$correlationId;
    }

    /**
     * Get current correlation ID, or generate one if not set.
     *
     * Use this in contexts without HTTP request (async handlers, CRON jobs)
     * to ensure traceability is never broken.
     */
    public static function getOrGenerate(): CorrelationId
    {
        if (self::$correlationId === null) {
            self::$correlationId = CorrelationId::generate();
        }

        return self::$correlationId;
    }

    public static function clear(): void
    {
        self::$correlationId = null;
    }
}
