<?php

declare(strict_types=1);

namespace App\Framework\EventSourcing\Sagas;

use App\Framework\EventSourcing\DomainEvent;

/**
 * Default Saga Registry Implementation
 *
 * In-memory registry of saga classes and their subscriptions
 */
final class DefaultSagaRegistry implements SagaRegistry
{
    /** @var array<string, class-string<SagaInterface>> */
    private array $sagas = [];

    /** @var array<class-string, array<class-string<SagaInterface>>> */
    private array $eventSubscriptions = [];

    /** @var array<class-string<SagaInterface>, class-string> */
    private array $autoStartEvents = [];

    public function register(string $sagaClass): void
    {
        $sagaName = $sagaClass::getName();
        $this->sagas[$sagaName] = $sagaClass;

        // Register event subscriptions
        $subscribedTo = $sagaClass::subscribedTo();
        foreach ($subscribedTo as $eventClass) {
            if (! isset($this->eventSubscriptions[$eventClass])) {
                $this->eventSubscriptions[$eventClass] = [];
            }
            $this->eventSubscriptions[$eventClass][] = $sagaClass;
        }
    }

    public function getSagaClass(string $sagaName): string
    {
        if (! isset($this->sagas[$sagaName])) {
            throw new \RuntimeException("Saga not found: {$sagaName}");
        }

        return $this->sagas[$sagaName];
    }

    public function getSagasForEvent(DomainEvent $event): array
    {
        $eventClass = get_class($event);

        return $this->eventSubscriptions[$eventClass] ?? [];
    }

    public function shouldAutoStart(string $sagaClass, DomainEvent $event): bool
    {
        if (! isset($this->autoStartEvents[$sagaClass])) {
            return false;
        }

        $autoStartEventClass = $this->autoStartEvents[$sagaClass];

        return get_class($event) === $autoStartEventClass;
    }

    public function getAll(): array
    {
        return array_values($this->sagas);
    }

    /**
     * Configure saga to auto-start on specific event
     *
     * @param class-string<SagaInterface> $sagaClass
     * @param class-string $eventClass
     */
    public function configureAutoStart(string $sagaClass, string $eventClass): void
    {
        $this->autoStartEvents[$sagaClass] = $eventClass;
    }
}
