<?php

declare(strict_types=1);

namespace App\Framework\Cache;

use App\Framework\Core\Events\EventDispatcher;
use App\Framework\Performance\Contracts\PerformanceCollectorInterface;
use App\Framework\Serializer\Serializer;

/**
 * Builder für die einfache Komposition von Cache-Decorators
 *
 * Ermöglicht eine fluent API für das Erstellen von Cache-Instanzen
 * mit verschiedenen Decorators.
 */
final class CacheBuilder
{
    private Cache $cache;

    private function __construct(Cache $baseCache)
    {
        $this->cache = $baseCache;
    }

    /**
     * Startet mit einem Base-Cache
     */
    public static function create(Cache $baseCache): self
    {
        return new self($baseCache);
    }

    /**
     * Fügt Logging-Funktionalität hinzu
     */
    public function withLogging(): self
    {
        $this->cache = new LoggingCacheDecorator($this->cache);

        return $this;
    }

    /**
     * Fügt Komprimierung hinzu
     *
     * @deprecated Use GeneralCache with compression parameter instead
     */
    public function withCompression(CompressionAlgorithm $algorithm, Serializer $serializer): self
    {
        trigger_error('CacheBuilder::withCompression() is deprecated. Use GeneralCache with compression parameter instead.', E_USER_DEPRECATED);

        // For backward compatibility, wrap with GeneralCache that has compression
        // This assumes the cache implements CacheDriver, otherwise this will fail
        if ($this->cache instanceof CacheDriver) {
            $this->cache = new GeneralCache($this->cache, $serializer, $algorithm);
        }

        return $this;
    }

    /**
     * Fügt Performance-Metriken hinzu
     */
    public function withMetrics(PerformanceCollectorInterface $collector, bool $enabled = true): self
    {
        // Create default cache metrics instance
        $cacheMetrics = new \App\Framework\Cache\Metrics\CacheMetrics();

        $this->cache = new \App\Framework\Cache\Metrics\MetricsDecoratedCache(
            $this->cache,
            $cacheMetrics,
            'CacheBuilder',
            $collector,
            $enabled
        );

        return $this;
    }

    /**
     * Fügt Validierung hinzu
     */
    public function withValidation(array $config = []): self
    {
        $this->cache = new ValidationCacheDecorator($this->cache, $config);

        return $this;
    }

    /**
     * Fügt Event-Dispatching hinzu
     */
    public function withEvents(EventDispatcher $eventDispatcher): self
    {
        $this->cache = new EventCacheDecorator($this->cache, $eventDispatcher);

        return $this;
    }

    /**
     * Fügt einen benutzerdefinierten Decorator hinzu
     */
    public function withCustomDecorator(callable $decoratorFactory): self
    {
        $this->cache = $decoratorFactory($this->cache);

        return $this;
    }

    /**
     * Erstellt eine Cache-Instanz mit allen konfigurierten Decorators
     */
    public function build(): Cache
    {
        return $this->cache;
    }

    /**
     * Convenience-Methode für eine vollständig ausgestattete Cache-Instanz
     */
    public static function createFull(
        Cache $baseCache,
        PerformanceCollectorInterface $performanceCollector,
        EventDispatcher $eventDispatcher,
        CompressionAlgorithm $compression,
        Serializer $serializer,
        array $validationConfig = []
    ): Cache {
        return self::create($baseCache)
            ->withValidation($validationConfig)
            ->withCompression($compression, $serializer)
            ->withMetrics($performanceCollector, true)
            ->withEvents($eventDispatcher)
            ->withLogging()
            ->build();
    }

    /**
     * Convenience-Methode für eine Performance-optimierte Cache-Instanz
     */
    public static function createPerformant(
        Cache $baseCache,
        PerformanceCollectorInterface $performanceCollector,
        CompressionAlgorithm $compression,
        Serializer $serializer
    ): Cache {
        return self::create($baseCache)
            ->withCompression($compression, $serializer)
            ->withMetrics($performanceCollector, true)
            ->build();
    }

    /**
     * Convenience-Methode für eine Development-Cache-Instanz mit vollständigem Monitoring
     */
    public static function createDevelopment(
        Cache $baseCache,
        PerformanceCollectorInterface $performanceCollector,
        EventDispatcher $eventDispatcher,
        array $validationConfig = []
    ): Cache {
        return self::create($baseCache)
            ->withValidation($validationConfig)
            ->withMetrics($performanceCollector, true)
            ->withEvents($eventDispatcher)
            ->withLogging()
            ->build();
    }
}
