<?php

declare(strict_types=1);

namespace Apexl\Io\Cache\Hooks;

use Apexl\Config\ConfigurationInterface;
use Apexl\Config\Exceptions\MissingConfigException;
use Apexl\Io\Cache\Collections\CacheStreamCollection;
use Apexl\Io\Cache\Dtos\CacheStreamConfigDto;
use Apexl\Io\Cache\Interfaces\CacheDriverFactoryInterface;
use Apexl\Io\Cache\Services\CacheManager;
use Apexl\Io\Cache\Services\CacheStream;
use Apexl\Io\Cache\Services\CacheStreamRegistry;
use Apexl\Io\Interfaces\AbstractHook;
use DI\Container;
use DI\DependencyException;
use DI\NotFoundException;
use Stash\Driver\Ephemeral;

final readonly class RegisterDefaultCacheStreams implements AbstractHook
{
    public function __construct(
        private Container $container,
        private ConfigurationInterface $config,
        private CacheStreamRegistry $cacheStreamRegistry,
    ) {}

    public function hooks(): array
    {
        return [
            CacheManager::HOOK__REGISTER_CACHE_STREAMS,
        ];
    }

    /**
     * @param CacheStreamCollection $streams
     * @throws DependencyException
     * @throws NotFoundException
     * @throws MissingConfigException
     */
    public function __invoke(CacheStreamCollection $streams): void
    {
        if (!$this->config->get('cache.enabled')) {
            // If cache is disabled then we don't need to register any streams.
            return;
        }

        if ($this->config->get('cache.register_ephemeral')) {
            $streams->set('ephemeral', new CacheStream(new Ephemeral()));
        }

        foreach ($this->config->get('cache.streams') ?? [] as $stream) {
            $stream = CacheStreamConfigDto::from($stream);
            /** @var CacheDriverFactoryInterface $factory */
            $factory = $this->container->get($stream->factory);
            if ($factory->loadable($stream->options)) {
                $streams->set($stream->name, $this->cacheStreamRegistry->get($factory->make($stream->options)));
            }
        }
    }
}