<?php

declare(strict_types=1);

namespace CliqThemes\UI\Data;

use CliqThemes\UI\Contracts\DataProvider;

/**
 * Lightweight container responsible for storing and resolving data providers by identifier.
 */
final class DataProviderRegistry
{
    /**
     * @var array<string, DataProvider>
     */
    private array $providers = [];

    /**
     * Stores a provider reference under a unique identifier.
     */
    public function register(string $identifier, DataProvider $provider): void
    {
        $this->providers[$identifier] = $provider;
    }

    /**
     * Registers a keyed array of providers.
     *
     * @param array<string, DataProvider> $providers
     */
    public function registerMany(array $providers): void
    {
        foreach ($providers as $identifier => $provider) {
            if (! $provider instanceof DataProvider) {
                continue;
            }

            $this->register((string) $identifier, $provider);
        }
    }

    /**
     * Checks whether the registry knows about the given identifier.
     */
    public function has(string $identifier): bool
    {
        return isset($this->providers[$identifier]);
    }

    /**
     * Resolves a provider from the registry or throws if it does not exist.
     */
    public function get(string $identifier): DataProvider
    {
        if (! $this->has($identifier)) {
            throw new \InvalidArgumentException(esc_html(sprintf('Data provider "%s" is not registered.', $identifier)));
        }

        return $this->providers[$identifier];
    }

    /**
     * Removes a provider from the registry.
     */
    public function forget(string $identifier): void
    {
        unset($this->providers[$identifier]);
    }

    /**
     * Returns all registered providers keyed by their identifier.
     *
     * @return array<string,DataProvider>
     */
    public function all(): array
    {
        return $this->providers;
    }
}
