<?php

app_require('classes/system_search_cache.php');

use classes\system_search_cache;

if (!class_exists('SystemSearchTestRedisAdapter')) {
    class SystemSearchTestRedisAdapter
    {
        private array $store = [];

        public function get(string $key): mixed
        {
            return $this->store[$key] ?? null;
        }

        public function set(string $key, string $value): void
        {
            $this->store[$key] = $value;
        }

        public function setEx(string $key, string $value, int $ttl): void
        {
            $this->store[$key] = $value;
        }

        public function delete(string $key): void
        {
            unset($this->store[$key]);
        }

        public function expire(string $key, int $ttl): void
        {
            // TTL is not simulated in this test adapter.
        }

        public function set_array(string $key, array $value): void
        {
            $this->store[$key] = json_encode($value, JSON_UNESCAPED_UNICODE);
        }

        public function get_array(string $key): ?array
        {
            $value = $this->store[$key] ?? null;
            if (!is_string($value)) {
                return null;
            }
            $decoded = json_decode($value, true);
            return is_array($decoded) ? $decoded : null;
        }

        public function clear_keys(string $pattern): void
        {
            $regex = '/^' . str_replace('\*', '.*', preg_quote($pattern, '/')) . '$/';
            foreach (array_keys($this->store) as $key) {
                if (preg_match($regex, $key)) {
                    unset($this->store[$key]);
                }
            }
        }
    }
}

beforeEach(function (): void {
    system_search_cache::setAdapterForTests(new SystemSearchTestRedisAdapter());
});

afterEach(function (): void {
    system_search_cache::setAdapterForTests(null);
});

it('stores and clears query cache entries in the active system search namespace', function (): void {
    $hash = md5('test-query');
    $payload = [
        'results' => [],
        'grouped_results' => [],
        'meta' => [
            'query' => 'acme',
            'max_results' => 50,
            'returned' => 0,
            'truncated' => false,
        ],
    ];

    system_search_cache::setQuery($hash, $payload, 120);
    expect(system_search_cache::getQuery($hash))->toBe($payload);

    system_search_cache::clearAll();
    expect(system_search_cache::getQuery($hash))->toBeNull();
});

it('bumps per-table cache versions when a dirty-table marker is registered', function (): void {
    $hash = md5('test-query');
    system_search_cache::setQuery($hash, ['results' => [], 'grouped_results' => [], 'meta' => []], 120);
    expect(system_search_cache::getQuery($hash))->not->toBeNull();
    $before = system_search_cache::tableVersionFingerprint(['orders']);

    system_search_cache::markDirtyTable('orders');
    $dirty = system_search_cache::consumeDirtyTables();
    $after = system_search_cache::tableVersionFingerprint(['orders']);

    expect(system_search_cache::getQuery($hash))->not->toBeNull();
    expect($dirty)->toContain('orders');
    expect($after)->not->toBe($before);
});
