<?php

namespace App\Framework\Cache;

use App\Framework\Cache\Compression\GzipCompression;
use App\Framework\Cache\Compression\NullCompression;
use App\Framework\Cache\Driver\ApcuCache;
use App\Framework\Cache\Driver\FileCache;
use App\Framework\Cache\Driver\InMemoryCache;
use App\Framework\Cache\Driver\NullCache;
use App\Framework\Cache\Driver\RedisCache;
use App\Framework\Cache\Serializer\JsonSerializer;
use App\Framework\Cache\Serializer\PhpSerializer;
use App\Framework\DI\Initializer;

final readonly class CacheInitializer
{
    public function __construct(
        private string $redisHost = 'redis',
        private int    $redisPort = 6379,
        private int    $compressionLevel = -1,
        private int    $minCompressionLength = 1024
    ) {}

    #[Initializer]
    public function __invoke(): Cache
    {
        $this->clear();

        $serializer = new PhpSerializer();
        $serializer = new JsonSerializer();
        $compression = new GzipCompression($this->compressionLevel, $this->minCompressionLength);


        // L1 Cache:
        if(function_exists('apcu_clear_cache')) {
            $apcuCache  = new GeneralCache(new APCuCache);
        }else {
            $apcuCache  = new GeneralCache(new InMemoryCache);
        }

        $compressedApcuCache = new CompressionCacheDecorator(
            $apcuCache,
            $compression,
            $serializer
        );

        // L2 Cache:
        $redisCache  = new GeneralCache(new RedisCache(host: $this->redisHost, port: $this->redisPort));
        $compressedRedisCache = new CompressionCacheDecorator(
            $redisCache,
            $compression,
            $serializer
        );

        $multiLevelCache = new MultiLevelCache($compressedApcuCache, $compressedRedisCache);

        #return $multiLevelCache;

        return new LoggingCacheDecorator($multiLevelCache);


        #return new GeneralCache(new NullCache());
    }

    private function clear(): void
    {
        apcu_clear_cache();
    }
}
