<?php
/**
* 高性能缓存管理类 - PHP 5.6+ 兼容版本
*/

// 安全检查
if (!defined('CACHE_PATH')) {
    die('禁止直接访问');
}

class Cache {
    private $cache_path;
    private $cache_enabled;
    private $gzip_enabled;

    public function __construct() {
        $this->cache_path = CACHE_PATH;
        
        // 安全地获取配置，提供默认值
        $config = $GLOBALS['config'] ?? [];
        $cache_config = $config['cache'] ?? [];
        
        $this->cache_enabled = $cache_config['enabled'] ?? true;
        $this->gzip_enabled = $cache_config['gzip_cache'] ?? true;

        if (!file_exists($this->cache_path)) {
            @mkdir($this->cache_path, 0755, true);
            // 创建缓存保护文件
            file_put_contents($this->cache_path . '/index.html', '');
            file_put_contents($this->cache_path . '/.htaccess', "Deny from all\n");
        }
    }

    /**
    * 获取缓存 - 优化版本，增强错误处理
    */
    public function get($key, $cache_time = 600) {
        if (!$this->cache_enabled) {
            return null;
        }

        $cache_file = $this->get_cache_filename($key);

        if (file_exists($cache_file)) {
            try {
                $cache_data = $this->read_cache_file($cache_file);

                if ($cache_data && (time() - $cache_data['timestamp'] < $cache_time)) {
                    return $cache_data['data'];
                } else {
                    // 缓存过期，删除文件
                    @unlink($cache_file);
                }
            } catch (Exception $e) {
                error_log("Cache read error: " . $e->getMessage());
                @unlink($cache_file); // 损坏的缓存文件
                return null;
            }
        }
        return null;
    }

    /**
    * 设置缓存 - 优化版本，增强错误处理
    */
    public function set($key, $data) {
        if (!$this->cache_enabled) {
            return false;
        }

        $cache_file = $this->get_cache_filename($key);
        $cache_data = [
            'timestamp' => time(),
            'data' => $data
        ];

        return $this->write_cache_file($cache_file, $cache_data);
    }

    /**
    * 智能获取缓存 - 新增：优先使用缓存，不存在时通过回调生成
    */
    public function smart_get($key, $callback, $cache_time = 600) {
        // 先尝试从缓存获取
        $cached_data = $this->get($key, $cache_time);
        if ($cached_data !== null) {
            return $cached_data;
        }

        // 检查是否已有其他进程在生成缓存
        if (!$this->cache_lock($key)) {
            // 如果被锁定，等待并重试
            usleep(100000); // 等待100ms
            $cached_data = $this->get($key, $cache_time);
            if ($cached_data !== null) {
                return $cached_data;
            }
            // 如果仍然没有，继续生成
        }

        // 生成新数据
        try {
            $data = call_user_func($callback);
            $this->set($key, $data);
            $this->cache_unlock($key);
            return $data;
        } catch (Exception $e) {
            $this->cache_unlock($key);
            throw $e;
        }
    }

    /**
    * 删除缓存
    */
    public function delete($key) {
        $cache_file = $this->get_cache_filename($key);
        if (file_exists($cache_file)) {
            return @unlink($cache_file);
        }
        return true;
    }

    /**
    * 清空所有缓存 - 增强版本
    */
    public function clear() {
        $files = glob($this->cache_path . '/*.cache');
        $count = 0;
        foreach ($files as $file) {
            if (is_file($file) && unlink($file)) {
                $count++;
            }
        }

        // 同时清除锁文件
        $lock_files = glob($this->cache_path . '/*_lock.cache');
        foreach ($lock_files as $file) {
            if (is_file($file)) {
                @unlink($file);
            }
        }

        return $count;
    }

    /**
    * 获取缓存信息 - 增强版本
    */
    public function info() {
        $files = glob($this->cache_path . '/*.cache');
        $total_size = 0;
        $file_count = 0;
        
        foreach ($files as $file) {
            if (is_file($file)) {
                $total_size += filesize($file);
                $file_count++;
            }
        }

        return [
            'count' => $file_count,
            'size' => $total_size,
            'enabled' => $this->cache_enabled,
            'path' => $this->cache_path
        ];
    }

    /**
    * 获取缓存状态 - 新增功能
    */
    public function status() {
        $info = $this->info();
        $status = [
            'enabled' => $info['enabled'],
            'file_count' => $info['count'],
            'total_size' => $this->format_bytes($info['size']),
            'writable' => is_writable($this->cache_path),
            'disk_free' => $this->format_bytes(disk_free_space($this->cache_path))
        ];
        
        return $status;
    }

    /**
    * 获取缓存文件名
    */
    private function get_cache_filename($key) {
        $safe_key = preg_replace('/[^a-zA-Z0-9_-]/', '_', $key);
        return $this->cache_path . '/' . md5($safe_key) . '.cache';
    }

    /**
    * 读取缓存文件 - 增强错误处理
    */
    private function read_cache_file($filename) {
        if (!file_exists($filename) || !is_readable($filename)) {
            return null;
        }
        
        $content = @file_get_contents($filename);
        if ($content === false) {
            return null;
        }
        
        if ($this->gzip_enabled) {
            $content = @gzdecode($content);
            if ($content === false) {
                return null;
            }
        }
        
        $data = json_decode($content, true);
        if (json_last_error() !== JSON_ERROR_NONE) {
            return null;
        }
        
        return $data;
    }

    /**
    * 写入缓存文件 - 增强错误处理
    */
    private function write_cache_file($filename, $data) {
        $content = json_encode($data, JSON_UNESCAPED_UNICODE);
        if (json_last_error() !== JSON_ERROR_NONE) {
            error_log("Cache JSON encode error: " . json_last_error_msg());
            return false;
        }

        if ($this->gzip_enabled) {
            $content = gzencode($content, 9);
            if ($content === false) {
                return false;
            }
        }

        // 使用临时文件避免写入过程中读取到不完整数据
        $temp_file = $filename . '.tmp';
        $result = file_put_contents($temp_file, $content, LOCK_EX);
        
        if ($result) {
            // 重命名原子操作
            if (rename($temp_file, $filename)) {
                @chmod($filename, 0644);
                return true;
            } else {
                @unlink($temp_file);
                return false;
            }
        }
        
        @unlink($temp_file);
        return false;
    }

    /**
    * 缓存锁机制 - 防止缓存雪崩
    */
    private function cache_lock($key, $timeout = 10) {
        $lock_key = $key . '_lock';
        $lock_time = $this->get($lock_key);

        if ($lock_time && (time() - $lock_time < $timeout)) {
            return false; // 已被锁定
        }

        $this->set($lock_key, time());
        return true;
    }

    private function cache_unlock($key) {
        $lock_key = $key . '_lock';
        $this->delete($lock_key);
    }

    /**
    * 格式化字节大小 - 新增工具函数
    */
    private function format_bytes($bytes, $precision = 2) {
        $units = ['B', 'KB', 'MB', 'GB', 'TB'];
        $bytes = max($bytes, 0);
        $pow = floor(($bytes ? log($bytes) : 0) / log(1024));
        $pow = min($pow, count($units) - 1);
        $bytes /= pow(1024, $pow);
        
        return round($bytes, $precision) . ' ' . $units[$pow];
    }

    /**
    * 清理过期缓存 - 新增维护功能
    */
    public function cleanup($max_age = 86400) {
        $files = glob($this->cache_path . '/*.cache');
        $cleaned = 0;
        $current_time = time();
        
        foreach ($files as $file) {
            // 跳过锁文件
            if (strpos(basename($file), '_lock') !== false) {
                continue;
            }
            
            $file_time = filemtime($file);
            if ($current_time - $file_time > $max_age) {
                if (unlink($file)) {
                    $cleaned++;
                }
            }
        }
        
        return $cleaned;
    }
}

// 全局缓存实例
if (!isset($GLOBALS['cache'])) {
    $GLOBALS['cache'] = new Cache();
}

/**
* 初始化缓存系统 - 增强版本
*/
function init_cache() {
    // 自动清理过期缓存（每天执行一次）
    $last_clean = $GLOBALS['cache']->get('last_clean');
    if (!$last_clean || (time() - $last_clean > 86400)) {
        $cleaned = $GLOBALS['cache']->cleanup(86400); // 清理超过1天的缓存
        if ($cleaned > 0) {
            error_log("Auto cleaned {$cleaned} expired cache files");
        }
        $GLOBALS['cache']->set('last_clean', time());
    }
    
    // 检查缓存目录权限
    if (!is_writable(CACHE_PATH)) {
        error_log("Cache directory is not writable: " . CACHE_PATH);
    }
}

/**
* 快捷缓存函数 - 增强版本
*/
function get_cache($key, $cache_time = 600) {
    return $GLOBALS['cache']->get($key, $cache_time);
}

function set_cache($key, $data) {
    return $GLOBALS['cache']->set($key, $data);
}

function delete_cache($key) {
    return $GLOBALS['cache']->delete($key);
}

function clear_all_cache() {
    return $GLOBALS['cache']->clear();
}

/**
* 智能缓存获取 - 新增
*/
function smart_cache($key, $callback, $cache_time = 600) {
    return $GLOBALS['cache']->smart_get($key, $callback, $cache_time);
}

/**
* 获取缓存状态 - 新增
*/
function cache_status() {
    return $GLOBALS['cache']->status();
}
?>