<?php

declare(strict_types=1);

namespace CliqThemes\UI\Data;

use CliqThemes\UI\Contracts\DataRepository;

/**
 * Default {@see DataRepository}: lazily-resolved, host-overridable option datasets
 * owned by the framework. Ships the generic web-platform data (Google font
 * families) so hosts pull it via CliqUI::dataRepo()->get('font_family') rather than
 * maintaining their own copy. Each dataset passes through a
 * `cliqthemes_ui_data_{key}` filter so a host can extend or replace it.
 */
final class OptionRepository implements DataRepository
{
    /** @var array<string, callable> */
    private array $providers = [];

    /** @var array<string, array<int|string, mixed>> */
    private array $cache = [];

    public function __construct()
    {
        $this->registerDefaults();
    }

    public function register(string $key, callable $provider): void
    {
        $this->providers[$key] = $provider;
        unset($this->cache[$key]);
    }

    public function has(string $key): bool
    {
        return isset($this->providers[$key]);
    }

    public function get(string $key): array
    {
        if (! array_key_exists($key, $this->cache)) {
            $data = isset($this->providers[$key]) ? (array) ($this->providers[$key])() : [];
            if (function_exists('apply_filters')) {
                /** @var array<int|string, mixed> $data */
                $data = (array) apply_filters('cliqthemes_ui_data_' . $key, $data);
            }
            $this->cache[$key] = $data;
        }

        return $this->cache[$key];
    }

    private function registerDefaults(): void
    {
        // Complete, grouped font catalog from the framework's Fonts class — each
        // option is { value, label, group } (system | google | earlyaccess). Pure
        // data: the "Theme default" empty option is added by the control, not here.
        // The JS loader lazy-injects whichever Google family is selected.
        $this->register('font_family', static fn (): array => Fonts::getFontsAsOptions());
    }
}
