<?php

namespace App\Core;

use App\Core\Cache;
use App\Core\Cache\RedisCache;

/**
 * Cache Manager - Unified Cache Interface
 * يدعم file cache و Redis cache مع fallback تلقائي
 */
class CacheManager
{
    private Cache $fileCache;
    private ?RedisCache $redisCache = null;
    private string $driver;
    private bool $redisAvailable = false;

    public function __construct(array $config = [])
    {
        $this->driver = $config['driver'] ?? 'file';
        $this->fileCache = new Cache(
            $config['file_dir'] ?? null,
            $config['default_ttl'] ?? 3600
        );

        // محاولة استخدام Redis إذا كان مفعّل
        if ($this->driver === 'redis' || $this->driver === 'auto') {
            try {
                // تحميل RedisCache إذا لم يكن محمّلاً
                if (!class_exists('App\Core\Cache\RedisCache')) {
                    $redisCacheFile = __DIR__ . '/Cache/RedisCache.php';
                    if (file_exists($redisCacheFile)) {
                        require_once $redisCacheFile;
                    }
                }
                
                if (class_exists('App\Core\Cache\RedisCache')) {
                    $this->redisCache = new RedisCache($config['redis'] ?? []);
                    $this->redisAvailable = $this->redisCache->isAvailable();
                }
            } catch (\Throwable $e) {
                $this->redisAvailable = false;
                error_log("Redis cache initialization failed: " . $e->getMessage());
            }
        }
    }

    /**
     * جلب قيمة من cache
     */
    public function get(string $key, $default = null)
    {
        // محاولة Redis أولاً
        if ($this->redisAvailable && $this->redisCache) {
            $value = $this->redisCache->get($key);
            if ($value !== null) {
                return $value;
            }
        }

        // Fallback إلى file cache
        $value = $this->fileCache->get($key);
        return $value !== null ? $value : $default;
    }

    /**
     * حفظ قيمة في cache
     */
    public function set(string $key, $value, ?int $ttl = null): bool
    {
        $success = true;

        // حفظ في Redis
        if ($this->redisAvailable && $this->redisCache) {
            $success = $this->redisCache->set($key, $value, $ttl) && $success;
        }

        // حفظ في file cache كـ backup
        $this->fileCache->set($key, $value, $ttl);

        return $success;
    }

    /**
     * حذف قيمة من cache
     */
    public function delete(string $key): bool
    {
        $success = true;

        if ($this->redisAvailable && $this->redisCache) {
            $this->redisCache->delete($key);
        }

        $this->fileCache->delete($key);

        return $success;
    }

    /**
     * التحقق من وجود key
     */
    public function has(string $key): bool
    {
        if ($this->redisAvailable && $this->redisCache) {
            return $this->redisCache->has($key);
        }

        return $this->fileCache->has($key);
    }

    /**
     * Remember pattern
     */
    public function remember(string $key, callable $callback, ?int $ttl = null)
    {
        $value = $this->get($key);
        if ($value !== null) {
            return $value;
        }

        $value = $callback();
        $this->set($key, $value, $ttl);
        return $value;
    }

    /**
     * مسح جميع cache
     */
    public function clear(): bool
    {
        $success = true;

        if ($this->redisAvailable && $this->redisCache) {
            $this->redisCache->flush('*');
        }

        $this->fileCache->clear();

        return $success;
    }

    /**
     * Increment
     */
    public function increment(string $key, int $value = 1): int
    {
        if ($this->redisAvailable && $this->redisCache) {
            return $this->redisCache->increment($key, $value);
        }

        return $this->fileCache->increment($key, $value);
    }

    /**
     * Decrement
     */
    public function decrement(string $key, int $value = 1): int
    {
        if ($this->redisAvailable && $this->redisCache) {
            return $this->redisCache->decrement($key, $value);
        }

        return $this->fileCache->decrement($key, $value);
    }

    /**
     * جلب معلومات cache
     */
    public function getInfo(): array
    {
        $info = [
            'driver' => $this->driver,
            'redis_available' => $this->redisAvailable
        ];

        if ($this->redisAvailable && $this->redisCache) {
            $info['redis'] = $this->redisCache->getInfo();
        }

        return $info;
    }
}
