<?php
declare(strict_types=1);
namespace App\Platform\Soc\Event;

use Throwable;

final class SecurityEvent
{
    private static ?EventDispatcher $dispatcher = null;
    private static ?EventRegistry $registry = null;

    /** @param array<string,mixed> $metadata */
    public static function info(string $name, string $message, array $metadata = []): ?string
    {
        return self::record($name, EventSeverity::INFO, $message, $metadata);
    }

    /** @param array<string,mixed> $metadata */
    public static function warning(string $name, string $message, array $metadata = []): ?string
    {
        return self::record($name, EventSeverity::WARNING, $message, $metadata);
    }

    /** @param array<string,mixed> $metadata */
    public static function critical(string $name, string $message, array $metadata = []): ?string
    {
        return self::record($name, EventSeverity::CRITICAL, $message, $metadata);
    }

    /** @param array<string,mixed> $metadata */
    public static function emit(
        string $name,
        string $message,
        array $metadata = [],
        ?string $subjectType = null,
        ?string $subjectReference = null,
        ?EventSeverity $severity = null,
    ): ?string {
        try {
            $definition = self::registry()->definition($name);
            $event = SecurityEventRecord::create(
                $severity ?? $definition['severity'] ?? EventSeverity::INFO,
                $definition['category'] ?? 'application',
                $definition['module'] ?? 'unknown',
                $name,
                (string) ($metadata['result'] ?? 'recorded'),
                $message,
                $metadata,
                $subjectType,
                $subjectReference,
            );
            return self::dispatcher()->dispatch($event);
        } catch (Throwable $exception) {
            error_log('[AXIOM SOC EVENT] ' . $name . ' (' . $exception->getMessage() . ')');
            return null;
        }
    }

    /** @param array<string,mixed> $metadata */
    private static function record(string $name, EventSeverity $severity, string $message, array $metadata): ?string
    {
        return self::emit($name, $message, $metadata, null, null, $severity);
    }

    private static function dispatcher(): EventDispatcher
    {
        return self::$dispatcher ??= new EventDispatcher();
    }

    private static function registry(): EventRegistry
    {
        return self::$registry ??= new EventRegistry();
    }
}
