<?php

namespace App\Service;

use App\Enum\CacheKey;
use Psr\Cache\CacheItemPoolInterface;

class CacheService
{
    public function __construct(
        private CacheItemPoolInterface $cache,
    ) {
    }

    public function get(CacheKey $key, string|int ...$params): mixed
    {
        $item = $this->cache->getItem($this->resolveKey($key, ...$params));

        if (!$item->isHit()) {
            return null;
        }

        return $item->get();
    }

    public function set(CacheKey $key, mixed $value, string|int ...$params): void
    {
        $cacheKey = $this->resolveKey($key, ...$params);
        $item = $this->cache->getItem($cacheKey);
        $item->set($value);
        $item->expiresAfter($key->ttl());
        $this->cache->save($item);
    }

    public function exists(CacheKey $key, string|int ...$params): bool
    {
        return $this->cache->hasItem($this->resolveKey($key, ...$params));
    }

    public function delete(CacheKey $key, string|int ...$params): void
    {
        $this->cache->deleteItem($this->resolveKey($key, ...$params));
    }

    public function remember(CacheKey $key, callable $callback, string|int ...$params): mixed
    {
        $cacheKey = $this->resolveKey($key, ...$params);
        $item = $this->cache->getItem($cacheKey);

        if ($item->isHit()) {
            return $item->get();
        }

        $value = $callback();
        $item->set($value);
        $item->expiresAfter($key->ttl());
        $this->cache->save($item);

        return $value;
    }

    private function resolveKey(CacheKey $key, string|int ...$params): string
    {
        return str_replace(['%d', '%s', '{', '}', '(', ')', '/', '\\', '@', ':'], '_', $key->resolve(...$params));
    }
}
