<?php
defined('ABSPATH') || exit;

/**
 * 缂撳瓨绠＄悊鍣?- 鏀寔Redis銆丮emcached鍜屾枃浠剁紦瀛? */
class CacheManager
{
    const CACHE_PREFIX = 'ai_post_';
    const DEFAULT_TTL = 3600; // 1灏忔椂
    
    private static $instance = null;
    private $cache_client = null;
    private $cache_type = 'file'; // file, redis, memcached
    private $enabled = true;
    
    /**
     * 鑾峰彇鍗曚緥瀹炰緥
     */
    public static function get_instance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct()
    {
        $this->init_cache();
    }
    
    /**
     * 鍒濆鍖栫紦瀛樺鎴风
     */
    private function init_cache()
    {
        $settings = \get_option('ai-post', []);
        $cache_config = isset($settings['cache']) ? $settings['cache'] : [];
        
        // 妫€鏌ユ槸鍚﹀惎鐢ㄧ紦瀛?        $this->enabled = isset($cache_config['enabled']) ? (bool)$cache_config['enabled'] : true;
        
        if (!$this->enabled) {
            return;
        }
        
        // 纭畾缂撳瓨绫诲瀷
        $this->cache_type = isset($cache_config['type']) ? $cache_config['type'] : 'file';
        
        switch ($this->cache_type) {
            case 'redis':
                $this->init_redis($cache_config);
                break;
            case 'memcached':
                $this->init_memcached($cache_config);
                break;
            case 'file':
            default:
                $this->init_file_cache();
                break;
        }
    }
    
    /**
     * 鍒濆鍖朢edis瀹㈡埛绔?     */
    private function init_redis($config)
    {
        if (!class_exists('Redis')) {
            \error_log('AI Post Cache: Redis鎵╁睍鏈畨瑁咃紝鍥為€€鍒版枃浠剁紦瀛?');
            $this->cache_type = 'file';
            $this->init_file_cache();
            return;
        }
        
        try {
            $redis = new \Redis();
            
            $host = isset($config['redis_host']) ? $config['redis_host'] : '127.0.0.1';
            $port = isset($config['redis_port']) ? (int)$config['redis_port'] : 6379;
            $timeout = isset($config['redis_timeout']) ? (float)$config['redis_timeout'] : 2.5;
            $password = isset($config['redis_password']) ? $config['redis_password'] : '';
            $database = isset($config['redis_database']) ? (int)$config['redis_database'] : 0;
            
            if ($redis->connect($host, $port, $timeout)) {
                if (!empty($password) && !$redis->auth($password)) {
                    throw new \Exception('Redis璁よ瘉澶辫触');
                }
                
                if ($database > 0) {
                    $redis->select($database);
                }
                
                // 娴嬭瘯杩炴帴
                if ($redis->ping() === '+PONG') {
                    $this->cache_client = $redis;
                    \error_log('AI Post Cache: Redis杩炴帴鎴愬姛');
                } else {
                    throw new \Exception('Redis ping澶辫触');
                }
            } else {
                throw new \Exception('Redis杩炴帴澶辫触');
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: Redis鍒濆鍖栧け璐? ' . $e->getMessage());
            $this->cache_type = 'file';
            $this->init_file_cache();
        }
    }
    
    /**
     * 鍒濆鍖朚emcached瀹㈡埛绔?     */
    private function init_memcached($config)
    {
        if (!class_exists('Memcached') && !class_exists('Memcache')) {
            \error_log('AI Post Cache: Memcached鎵╁睍鏈畨瑁咃紝鍥為€€鍒版枃浠剁紦瀛?');
            $this->cache_type = 'file';
            $this->init_file_cache();
            return;
        }
        
        try {
            if (class_exists('Memcached')) {
                $memcached = new \Memcached();
                $memcached->setOption(\Memcached::OPT_BINARY_PROTOCOL, true);
                $memcached->setOption(\Memcached::OPT_TCP_NODELAY, true);
                $memcached->setOption(\Memcached::OPT_NO_BLOCK, true);
            } else {
                $memcached = new \Memcache();
            }
            
            $servers = isset($config['memcached_servers']) ? $config['memcached_servers'] : '127.0.0.1:11211';
            $server_list = explode(',', $servers);
            
            $added = false;
            foreach ($server_list as $server) {
                $parts = explode(':', trim($server));
                $host = $parts[0];
                $port = isset($parts[1]) ? (int)$parts[1] : 11211;
                $weight = isset($parts[2]) ? (int)$parts[2] : 1;
                
                if (class_exists('Memcached')) {
                    if ($memcached->addServer($host, $port, $weight)) {
                        $added = true;
                    }
                } else {
                    if ($memcached->addServer($host, $port, true, $weight)) {
                        $added = true;
                    }
                }
            }
            
            if ($added) {
                // 娴嬭瘯杩炴帴
                $stats = $memcached->getStats();
                if (!empty($stats)) {
                    $this->cache_client = $memcached;
                    \error_log('AI Post Cache: Memcached杩炴帴鎴愬姛');
                } else {
                    throw new \Exception('Memcached鑾峰彇鐘舵€佸け璐?');
                }
            } else {
                throw new \Exception('Memcached娣诲姞鏈嶅姟鍣ㄥけ璐?');
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: Memcached鍒濆鍖栧け璐? ' . $e->getMessage());
            $this->cache_type = 'file';
            $this->init_file_cache();
        }
    }
    
    /**
     * 鍒濆鍖栨枃浠剁紦瀛?     */
    private function init_file_cache()
    {
        $cache_dir = WP_CONTENT_DIR . '/cache/ai-post/';
        
        if (!file_exists($cache_dir)) {
            if (!wp_mkdir_p($cache_dir)) {
                \error_log('AI Post Cache: 鏃犳硶鍒涘缓缂撳瓨鐩綍: ' . $cache_dir);
                $this->enabled = false;
                return;
            }
        }
        
        // 妫€鏌ョ洰褰曟槸鍚﹀彲鍐?
        if (!is_writable($cache_dir)) {
            \error_log('AI Post Cache: 缂撳瓨鐩綍涓嶅彲鍐? ' . $cache_dir);
            $this->enabled = false;
            return;
        }
        
        $this->cache_client = $cache_dir;
        \error_log('AI Post Cache: 鏂囦欢缂撳瓨宸插惎鐢紝鐩綍: ' . $cache_dir);
    }
    
    /**
     * 鐢熸垚缂撳瓨閿?     */
    private function get_cache_key($key)
    {
        return self::CACHE_PREFIX . md5($key);
    }
    
    /**
     * 鑾峰彇缂撳瓨
     */
    public function get($key, $default = null)
    {
        if (!$this->enabled) {
            return $default;
        }
        
        $cache_key = $this->get_cache_key($key);
        
        try {
            switch ($this->cache_type) {
                case 'redis':
                    $value = $this->cache_client->get($cache_key);
                    if ($value !== false) {
                        return unserialize($value);
                    }
                    break;
                    
                case 'memcached':
                    if (class_exists('Memcached')) {
                        $value = $this->cache_client->get($cache_key);
                        if ($this->cache_client->getResultCode() === \Memcached::RES_SUCCESS) {
                            return $value;
                        }
                    } else {
                        $value = $this->cache_client->get($cache_key);
                        if ($value !== false) {
                            return $value;
                        }
                    }
                    break;
                    
                case 'file':
                    $cache_file = $this->cache_client . $cache_key . '.cache';
                    if (file_exists($cache_file)) {
                        $data = file_get_contents($cache_file);
                        $cache_data = unserialize($data);
                        
                        // 妫€鏌ユ槸鍚﹁繃鏈?
                        if (isset($cache_data['expires']) && $cache_data['expires'] > time()) {
                            return $cache_data['data'];
                        } else {
                            // 杩囨湡锛屽垹闄ゆ枃浠?
                            @unlink($cache_file);
                        }
                    }
                    break;
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: 鑾峰彇缂撳瓨澶辫触: ' . $e->getMessage());
        }
        
        return $default;
    }
    
    /**
     * 璁剧疆缂撳瓨
     */
    public function set($key, $value, $ttl = null)
    {
        if (!$this->enabled) {
            return false;
        }
        
        if ($ttl === null) {
            $ttl = self::DEFAULT_TTL;
        }
        
        $cache_key = $this->get_cache_key($key);
        
        try {
            switch ($this->cache_type) {
                case 'redis':
                    $serialized = serialize($value);
                    return $this->cache_client->setex($cache_key, $ttl, $serialized);
                    
                case 'memcached':
                    if (class_exists('Memcached')) {
                        return $this->cache_client->set($cache_key, $value, $ttl);
                    } else {
                        return $this->cache_client->set($cache_key, $value, 0, $ttl);
                    }
                    
                case 'file':
                    $cache_file = $this->cache_client . $cache_key . '.cache';
                    $cache_data = [
                        'data' => $value,
                        'expires' => time() + $ttl,
                        'created' => time()
                    ];
                    
                    $result = file_put_contents($cache_file, serialize($cache_data));
                    return $result !== false;
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: 璁剧疆缂撳瓨澶辫触: ' . $e->getMessage());
            return false;
        }
        
        return false;
    }
    
    /**
     * 鍒犻櫎缂撳瓨
     */
    public function delete($key)
    {
        if (!$this->enabled) {
            return false;
        }
        
        $cache_key = $this->get_cache_key($key);
        
        try {
            switch ($this->cache_type) {
                case 'redis':
                    return $this->cache_client->del($cache_key) > 0;
                    
                case 'memcached':
                    if (class_exists('Memcached')) {
                        return $this->cache_client->delete($cache_key);
                    } else {
                        return $this->cache_client->delete($cache_key);
                    }
                    
                case 'file':
                    $cache_file = $this->cache_client . $cache_key . '.cache';
                    if (file_exists($cache_file)) {
                        return unlink($cache_file);
                    }
                    return true;
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: 鍒犻櫎缂撳瓨澶辫触: ' . $e->getMessage());
            return false;
        }
        
        return false;
    }
    
    /**
     * 娓呯┖鎵€鏈夌紦瀛?     */
    public function clear()
    {
        if (!$this->enabled) {
            return false;
        }
        
        try {
            switch ($this->cache_type) {
                case 'redis':
                    $keys = $this->cache_client->keys(self::CACHE_PREFIX . '*');
                    if (!empty($keys)) {
                        return $this->cache_client->del($keys) > 0;
                    }
                    return true;
                    
                case 'memcached':
                    if (class_exists('Memcached')) {
                        return $this->cache_client->flush();
                    } else {
                        return $this->cache_client->flush();
                    }
                    
                case 'file':
                    $cache_dir = $this->cache_client;
                    $files = glob($cache_dir . '*.cache');
                    $success = true;
                    foreach ($files as $file) {
                        if (!unlink($file)) {
                            $success = false;
                        }
                    }
                    return $success;
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: 娓呯┖缂撳瓨澶辫触: ' . $e->getMessage());
            return false;
        }
        
        return false;
    }
    
    /**
     * 妫€鏌ョ紦瀛樻槸鍚﹀瓨鍦?     */
    public function has($key)
    {
        if (!$this->enabled) {
            return false;
        }
        
        $cache_key = $this->get_cache_key($key);
        
        try {
            switch ($this->cache_type) {
                case 'redis':
                    return $this->cache_client->exists($cache_key) > 0;
                    
                case 'memcached':
                    if (class_exists('Memcached')) {
                        $this->cache_client->get($cache_key);
                        return $this->cache_client->getResultCode() === \Memcached::RES_SUCCESS;
                    } else {
                        return $this->cache_client->get($cache_key) !== false;
                    }
                    
                case 'file':
                    $cache_file = $this->cache_client . $cache_key . '.cache';
                    if (file_exists($cache_file)) {
                        $data = file_get_contents($cache_file);
                        $cache_data = unserialize($data);
                        return isset($cache_data['expires']) && $cache_data['expires'] > time();
                    }
                    break;
            }
        } catch (\Exception $e) {
            \error_log('AI Post Cache: 妫€鏌ョ紦瀛樺け璐? ' . $e->getMessage());
        }
        
        return false;
    }
    
    /**
     * 鑾峰彇缂撳瓨缁熻淇℃伅
     */
    public function get_stats()
    {
        if (!$this->enabled) {
            return ['enabled' => false];
        }
        
        $stats = [
            'enabled' => true,
            'type' => $this->cache_type,
            'status' => 'unknown'
        ];
        
        try {
            switch ($this->cache_type) {
                case 'redis':
                    $info = $this->cache_client->info();
                    $stats['status'] = 'connected';
                    $stats['used_memory'] = isset($info['used_memory']) ? $this->format_bytes($info['used_memory']) : 'unknown';
                    $stats['connected_clients'] = isset($info['connected_clients']) ? $info['connected_clients'] : 'unknown';
                    break;
                    
                case 'memcached':
                    $server_stats = $this->cache_client->getStats();
                    $stats['status'] = !empty($server_stats) ? 'connected' : 'disconnected';
                    if (!empty($server_stats)) {
                        $first_server = reset($server_stats);
                        $stats['curr_items'] = isset($first_server['curr_items']) ? $first_server['curr_items'] : 'unknown';
                        $stats['bytes'] = isset($first_server['bytes']) ? $this->format_bytes($first_server['bytes']) : 'unknown';
                    }
                    break;
                    
                case 'file':
                    $cache_dir = $this->cache_client;
                    $files = glob($cache_dir . '*.cache');
                    $stats['status'] = 'connected';
                    $stats['file_count'] = count($files);
                    $stats['total_size'] = $this->format_bytes($this->get_directory_size($cache_dir));
                    break;
            }
        } catch (\Exception $e) {
            $stats['status'] = 'error: ' . $e->getMessage();
        }
        
        return $stats;
    }
    
    /**
     * 鑾峰彇鐩綍澶у皬
     */
    private function get_directory_size($path)
    {
        $size = 0;
        $files = glob($path . '/*');
        
        foreach ($files as $file) {
            if (is_file($file)) {
                $size += filesize($file);
            }
        }
        
        return $size;
    }
    
    /**
     * 鏍煎紡鍖栧瓧鑺傚ぇ灏?     */
    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];
    }
    
    /**
     * 缂撳瓨AI API鍝嶅簲
     */
    public function cache_ai_response($prompt, $model, $response, $ttl = 1800)
    {
        $cache_key = 'ai_response_' . md5($prompt . $model);
        return $this->set($cache_key, $response, $ttl);
    }
    
    /**
     * 鑾峰彇缂撳瓨鐨凙I鍝嶅簲
     */
    public function get_cached_ai_response($prompt, $model)
    {
        $cache_key = 'ai_response_' . md5($prompt . $model);
        return $this->get($cache_key);
    }
    
    /**
     * 缂撳瓨鎻掍欢璁剧疆
     */
    public function cache_settings($settings, $ttl = 300)
    {
        return $this->set('plugin_settings', $settings, $ttl);
    }
    
    /**
     * 鑾峰彇缂撳瓨鐨勬彃浠惰缃?     */
    public function get_cached_settings()
    {
        return $this->get('plugin_settings');
    }
    
    /**
     * 缂撳瓨瀛椾綋鐘舵€?     */
    public function cache_font_status($status, $ttl = 600)
    {
        return $this->set('font_status', $status, $ttl);
    }
    
    /**
     * 鑾峰彇缂撳瓨鐨勫瓧浣撶姸鎬?     */
    public function get_cached_font_status()
    {
        return $this->get('font_status');
    }
}

if (!class_exists('HaoZiTeam\\AIPost\\Service\\Features\\CacheManager', false)) {
    class_alias('CacheManager', 'HaoZiTeam\\AIPost\\Service\\Features\\CacheManager');
}

