<?php

declare(strict_types=1);

namespace App\Framework\LiveComponents\Cache;

use App\Framework\Core\ValueObjects\Duration;
use App\Framework\LiveComponents\ValueObjects\ComponentId;
use App\Framework\LiveComponents\ValueObjects\ComponentState;

/**
 * Metrics-Aware Component State Cache Decorator
 *
 * Wraps ComponentStateCache to add automatic metrics collection.
 *
 * Tracks:
 * - Cache hits/misses with lookup times
 * - Cache invalidations
 * - Cache size changes
 */
final readonly class MetricsAwareComponentStateCache
{
    public function __construct(
        private ComponentStateCache $cache,
        private CacheMetricsCollector $metricsCollector
    ) {
    }

    public function store(
        ComponentId $componentId,
        ComponentState $state,
        ?Duration $ttl = null
    ): bool {
        return $this->cache->store($componentId, $state, $ttl);
    }

    public function retrieve(ComponentId $componentId, ComponentState $currentState): ?ComponentState
    {
        $startTime = microtime(true);
        $result = $this->cache->retrieve($componentId, $currentState);
        $lookupTimeMs = (microtime(true) - $startTime) * 1000;

        if ($result !== null) {
            $this->metricsCollector->recordHit(CacheType::STATE, $lookupTimeMs);
        } else {
            $this->metricsCollector->recordMiss(CacheType::STATE, $lookupTimeMs);
        }

        return $result;
    }

    public function has(ComponentId $componentId, ComponentState $state): bool
    {
        return $this->cache->has($componentId, $state);
    }

    public function invalidate(ComponentId $componentId): bool
    {
        $result = $this->cache->invalidate($componentId);

        if ($result) {
            $this->metricsCollector->recordInvalidation(CacheType::STATE);
        }

        return $result;
    }

    public function clear(): bool
    {
        return $this->cache->clear();
    }

    public function getStats(): array
    {
        return $this->cache->getStats();
    }

    public function storeWithAutoTTL(
        ComponentId $componentId,
        ComponentState $state,
        string $componentType
    ): bool {
        return $this->cache->storeWithAutoTTL($componentId, $state, $componentType);
    }
}
