<?php

declare(strict_types=1);

namespace Builder\Core\Foundation\Resources;

use Builder\Core\Foundation\Contracts\Modules\FieldHandler;

/**
 * Registry that maps field component names to their handler interface class names.
 *
 * Module service providers call register() to opt in to the write pipeline:
 *
 *     app(FieldHandlerRegistry::class)->register(
 *         FieldComponent::Media->value,
 *         MediaFieldHandler::class,
 *     );
 *
 * ResourcePersistenceService and RevisionService use this registry to dispatch
 * load/sync operations without hardcoding component names.
 */
final class FieldHandlerRegistry
{
    /** @var array<string, class-string<FieldHandler>> */
    private array $handlers = [];

    /**
     * Register a handler interface for the given component name.
     * The handler will be resolved from the service container when needed.
     *
     * @param  class-string<FieldHandler>  $handlerInterface
     */
    public function register(string $componentName, string $handlerInterface): static
    {
        $this->handlers[$componentName] = $handlerInterface;

        return $this;
    }

    public function has(string $componentName): bool
    {
        return isset($this->handlers[$componentName]) && app()->bound($this->handlers[$componentName]);
    }

    /**
     * Resolve the handler instance from the container for the given component name.
     * Returns null when no handler is registered or the binding is absent.
     */
    public function resolve(string $componentName): ?FieldHandler
    {
        if (! $this->has($componentName)) {
            return null;
        }

        /** @var FieldHandler */
        return app($this->handlers[$componentName]);
    }

    /** @return array<string, class-string<FieldHandler>> */
    public function all(): array
    {
        return $this->handlers;
    }
}
