<?php

declare(strict_types=1);

namespace App\Framework\Cache;

use App\Framework\Core\ValueObjects\Duration;

final readonly class LoggingCacheDecorator implements Cache
{
    public function __construct(
        private Cache $innerCache,
    ) {
    }

    public function get(CacheIdentifier ...$identifiers): CacheResult
    {
        $result = $this->innerCache->get(...$identifiers);

        $hitCount = $result->getHits()->count();
        $missCount = $result->getMisses()->count();
        $identifierList = implode(', ', array_map(fn ($id) => $id->toString(), $identifiers));

        error_log("Cache GET: [{$identifierList}] - Hits: {$hitCount}, Misses: {$missCount}");

        return $result;
    }

    public function set(CacheItem ...$items): bool
    {
        $result = $this->innerCache->set(...$items);

        $count = count($items);
        $success = $result ? 'YES' : 'NO';

        foreach ($items as $item) {
            $valueType = $item->value === null ? 'NULL' : gettype($item->value);
            $ttlStr = $item->ttl === null ? 'default' : $item->ttl->toSeconds() . 's';
            error_log("Cache SET: {$item->key} = {$valueType}, TTL: {$ttlStr}");
        }

        error_log("Cache SET_BATCH: {$count} items, Success: {$success}");

        return $result;
    }

    public function has(CacheIdentifier ...$identifiers): array
    {
        $result = $this->innerCache->has(...$identifiers);

        foreach ($result as $identifierString => $exists) {
            $existsStr = $exists ? 'YES' : 'NO';
            error_log("Cache HAS: {$identifierString} = {$existsStr}");
        }

        return $result;
    }

    public function forget(CacheIdentifier ...$identifiers): bool
    {
        $result = $this->innerCache->forget(...$identifiers);

        $count = count($identifiers);
        $success = $result ? 'YES' : 'NO';
        $identifierList = implode(', ', array_map(fn ($id) => $id->toString(), $identifiers));

        error_log("Cache FORGET: [{$identifierList}], Success: {$success}");

        return $result;
    }

    public function clear(): bool
    {
        $result = $this->innerCache->clear();
        $success = $result ? 'YES' : 'NO';
        error_log("Cache CLEAR: Success: {$success}");

        return $result;
    }

    public function remember(CacheKey $key, callable $callback, ?Duration $ttl = null): CacheItem
    {
        $result = $this->innerCache->remember($key, $callback, $ttl);

        $status = $result->isHit ? 'HIT' : 'COMPUTED';
        $ttlStr = $ttl === null ? 'default' : $ttl->toSeconds() . 's';
        error_log("Cache REMEMBER: {$key} = {$status}, TTL: {$ttlStr}");

        return $result;
    }
}
