<?php

namespace App\Core;

/**
 * Cache - نظام التخزين المؤقت
 */
class Cache
{
    private string $cacheDir;
    private int $defaultTtl;

    public function __construct(?string $cacheDir = null, int $defaultTtl = 3600)
    {
        $this->cacheDir = $cacheDir ?? __DIR__ . '/../../cache';
        $this->defaultTtl = $defaultTtl;
        
        if (!is_dir($this->cacheDir)) {
            @mkdir($this->cacheDir, 0755, true);
        }
    }

    /**
     * جلب قيمة من الـ cache
     */
    public function get(string $key): mixed
    {
        $file = $this->getCacheFile($key);
        
        if (!file_exists($file)) {
            return null;
        }

        $data = @file_get_contents($file);
        if ($data === false) {
            return null;
        }

        $cacheData = @unserialize($data);
        if ($cacheData === false || !is_array($cacheData)) {
            @unlink($file);
            return null;
        }

        // التحقق من انتهاء الصلاحية
        if (isset($cacheData['expires_at']) && $cacheData['expires_at'] < time()) {
            @unlink($file);
            return null;
        }

        return $cacheData['value'] ?? null;
    }

    /**
     * حفظ قيمة في الـ cache
     */
    public function set(string $key, mixed $value, ?int $ttl = null): bool
    {
        $ttl = $ttl ?? $this->defaultTtl;
        $file = $this->getCacheFile($key);
        
        $cacheData = [
            'value' => $value,
            'expires_at' => time() + $ttl,
            'created_at' => time()
        ];

        $data = serialize($cacheData);
        return @file_put_contents($file, $data, LOCK_EX) !== false;
    }

    /**
     * حذف قيمة من الـ cache
     */
    public function delete(string $key): bool
    {
        $file = $this->getCacheFile($key);
        if (file_exists($file)) {
            return @unlink($file);
        }
        return true;
    }

    /**
     * التحقق من وجود قيمة في الـ cache
     */
    public function has(string $key): bool
    {
        $file = $this->getCacheFile($key);
        
        if (!file_exists($file)) {
            return false;
        }

        $data = @file_get_contents($file);
        if ($data === false) {
            return false;
        }

        $cacheData = @unserialize($data);
        if ($cacheData === false || !is_array($cacheData)) {
            @unlink($file);
            return false;
        }

        // التحقق من انتهاء الصلاحية
        if (isset($cacheData['expires_at']) && $cacheData['expires_at'] < time()) {
            @unlink($file);
            return false;
        }

        return true;
    }

    /**
     * مسح جميع الـ cache
     */
    public function clear(): bool
    {
        $files = glob($this->cacheDir . '/*.cache');
        $success = true;
        
        foreach ($files as $file) {
            if (is_file($file)) {
                if (!@unlink($file)) {
                    $success = false;
                }
            }
        }
        
        return $success;
    }

    /**
     * مسح الـ cache المنتهية الصلاحية
     */
    public function clean(): int
    {
        $files = glob($this->cacheDir . '/*.cache');
        $cleaned = 0;
        
        foreach ($files as $file) {
            if (!is_file($file)) {
                continue;
            }

            $data = @file_get_contents($file);
            if ($data === false) {
                @unlink($file);
                $cleaned++;
                continue;
            }

            $cacheData = @unserialize($data);
            if ($cacheData === false || !is_array($cacheData)) {
                @unlink($file);
                $cleaned++;
                continue;
            }

            if (isset($cacheData['expires_at']) && $cacheData['expires_at'] < time()) {
                @unlink($file);
                $cleaned++;
            }
        }
        
        return $cleaned;
    }

    /**
     * جلب أو حفظ (cache remember pattern)
     */
    public function remember(string $key, callable $callback, ?int $ttl = null): mixed
    {
        $value = $this->get($key);
        
        if ($value !== null) {
            return $value;
        }

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

    /**
     * جلب مسار ملف الـ cache
     */
    private function getCacheFile(string $key): string
    {
        $safeKey = preg_replace('/[^a-z0-9_-]/i', '_', $key);
        return $this->cacheDir . '/' . md5($safeKey) . '.cache';
    }

    /**
     * زيادة قيمة عددية
     */
    public function increment(string $key, int $value = 1): int
    {
        $current = $this->get($key) ?? 0;
        $newValue = (int)$current + $value;
        $this->set($key, $newValue, $this->defaultTtl);
        return $newValue;
    }

    /**
     * تقليل قيمة عددية
     */
    public function decrement(string $key, int $value = 1): int
    {
        return $this->increment($key, -$value);
    }
}
