<?php

declare(strict_types=1);

namespace apexl\Io\services;

use apexl\Io\includes\HookManager;

/**
 * Lazy-loading hook-collected registry base. Many module services follow
 * the same skeleton: a hook key, a HookManager dep, a nullable cache, an
 * `all()` method that runs the hook on first access. This consolidates the
 * skeleton; subclasses own:
 *   - The hook name (via `hookName()`).
 *   - The collection type + empty-state factory (via `emptyCollection()`).
 *   - Any type-narrow lookup helpers (e.g. `find($key)`).
 *
 * Subclasses can be readonly: the cache is a property on this base and
 * mutates via `$this->collected =` which works inside non-readonly
 * children.
 *
 * @template C
 */
abstract class HookCollectedRegistry
{
    /** @var C|null */
    private mixed $collected = null;

    public function __construct(
        protected readonly HookManager $hookManager,
    ) {}

    abstract protected function hookName(): string;

    /** @return C */
    abstract protected function emptyCollection(): mixed;

    /** @return C */
    public function all(): mixed
    {
        if ($this->collected === null) {
            $this->collected = $this->hookManager->processHook(
                $this->hookName(),
                $this->emptyCollection(),
            );
        }
        return $this->collected;
    }
}
