<?php
/**
 * Cache Manager
 * Handles file-based caching for queries and API responses
 */

class CacheManager {
    private $cacheDir;
    private $defaultTTL = 3600; // 1 hour
    private $enabled = true;
    
    public function __construct($cacheDir = null) {
        $this->cacheDir = $cacheDir ?: __DIR__ . '/../tmp/cache/';
        $this->ensureDirectory();
    }
    
    /**
     * Ensure cache directory exists
     */
    private function ensureDirectory() {
        if (!is_dir($this->cacheDir)) {
            mkdir($this->cacheDir, 0755, true);
        }
    }
    
    /**
     * Generate cache key from data
     * @param string $key
     * @return string
     */
    private function getCacheFile($key) {
        return $this->cacheDir . md5($key) . '.cache';
    }
    
    /**
     * Get cached data
     * @param string $key
     * @return mixed|null
     */
    public function get($key) {
        if (!$this->enabled) {
            return null;
        }
        
        $cacheFile = $this->getCacheFile($key);
        
        if (!file_exists($cacheFile)) {
            return null;
        }
        
        $data = unserialize(file_get_contents($cacheFile));
        
        if ($data['expiry'] < time()) {
            $this->delete($key);
            return null;
        }
        
        return $data['value'];
    }
    
    /**
     * Set cached data
     * @param string $key
     * @param mixed $value
     * @param int $ttl Time to live in seconds
     * @return bool
     */
    public function set($key, $value, $ttl = null) {
        if (!$this->enabled) {
            return false;
        }
        
        $ttl = $ttl ?: $this->defaultTTL;
        $cacheFile = $this->getCacheFile($key);
        
        $data = [
            'value' => $value,
            'expiry' => time() + $ttl,
            'created' => time()
        ];
        
        return file_put_contents($cacheFile, serialize($data)) !== false;
    }
    
    /**
     * Delete cached data
     * @param string $key
     * @return bool
     */
    public function delete($key) {
        $cacheFile = $this->getCacheFile($key);
        if (file_exists($cacheFile)) {
            return unlink($cacheFile);
        }
        return true;
    }
    
    /**
     * Clear all cache
     * @return int Number of files deleted
     */
    public function clear() {
        $files = glob($this->cacheDir . '*.cache');
        $count = 0;
        foreach ($files as $file) {
            if (unlink($file)) {
                $count++;
            }
        }
        return $count;
    }
    
    /**
     * Get cache statistics
     * @return array
     */
    public function getStats() {
        $files = glob($this->cacheDir . '*.cache');
        $totalSize = 0;
        $validCount = 0;
        $expiredCount = 0;
        
        foreach ($files as $file) {
            $size = filesize($file);
            $totalSize += $size;
            
            $data = unserialize(file_get_contents($file));
            if ($data && isset($data['expiry'])) {
                if ($data['expiry'] > time()) {
                    $validCount++;
                } else {
                    $expiredCount++;
                }
            }
        }
        
        return [
            'total_files' => count($files),
            'valid_files' => $validCount,
            'expired_files' => $expiredCount,
            'total_size' => $totalSize,
            'total_size_formatted' => $this->formatSize($totalSize)
        ];
    }
    
    /**
     * Format file size
     * @param int $bytes
     * @return string
     */
    private function formatSize($bytes) {
        if ($bytes >= 1073741824) {
            return round($bytes / 1073741824, 2) . ' GB';
        } elseif ($bytes >= 1048576) {
            return round($bytes / 1048576, 2) . ' MB';
        } elseif ($bytes >= 1024) {
            return round($bytes / 1024, 2) . ' KB';
        }
        return $bytes . ' B';
    }
    
    /**
     * Enable/disable cache
     * @param bool $enabled
     */
    public function setEnabled($enabled) {
        $this->enabled = $enabled;
    }
    
    /**
     * Get cache for database query
     * @param string $sql
     * @param array $params
     * @return mixed
     */
    public function getQueryCache($sql, $params = []) {
        $key = 'query_' . md5($sql . serialize($params));
        return $this->get($key);
    }
    
    /**
     * Set cache for database query
     * @param string $sql
     * @param array $params
     * @param mixed $result
     * @param int $ttl
     * @return bool
     */
    public function setQueryCache($sql, $params, $result, $ttl = 300) {
        $key = 'query_' . md5($sql . serialize($params));
        return $this->set($key, $result, $ttl);
    }
}

// Global cache instance
$cacheManager = null;

function getCache() {
    global $cacheManager;
    if ($cacheManager === null) {
        $cacheManager = new CacheManager();
    }
    return $cacheManager;
}