<?php

declare(strict_types=1);

namespace Flowaxy\Infrastructure\Cache;

use Flowaxy\Contracts\Cache\CacheInterface;
use Flowaxy\Infrastructure\Persistence\Database\QueryBuilder;

/**
 * Кеширование результатов запросов (только SELECT)
 *
 * @package Flowaxy\Infrastructure\Cache
 */
final class QueryCache
{
    private CacheInterface $cache;
    private string $prefix = 'query:';

    public function __construct(CacheInterface $cache)
    {
        $this->cache = $cache;
    }

    /**
     * Получить результат запроса из кеша или выполнить запрос
     *
     * @param QueryBuilder $query
     * @param int $ttl Время жизни в секундах
     * @return array<int, array<string, mixed>>
     */
    public function remember(QueryBuilder $query, int $ttl = 3600): array
    {
        $key = $this->getCacheKey($query);

        $cached = $this->cache->get($key);
        if ($cached !== null && is_array($cached)) {
            return $cached;
        }

        $result = $query->get();
        $this->cache->set($key, $result, $ttl);

        return $result;
    }

    /**
     * Инвалидировать кеш для таблицы
     *
     * @param string $table Имя таблицы
     * @return void
     */
    public function invalidateTable(string $table): void
    {
        // Простая реализация: очищаем все ключи с префиксом таблицы
        // В реальности нужен более сложный механизм отслеживания
        $pattern = $this->prefix . 'table:' . $table . ':';
        // Для полной реализации нужен доступ к списку всех ключей
        // Это зависит от реализации CacheInterface
    }

    /**
     * Получить ключ кеша для запроса
     *
     * @param QueryBuilder $query
     * @return string
     */
    private function getCacheKey(QueryBuilder $query): string
    {
        $sql = $query->toSql();
        $bindings = $query->getBindings();
        $hash = md5($sql . serialize($bindings));
        return $this->prefix . $hash;
    }
}
