<?php
namespace HaoZiTeam\AIPost\Service\Features;

defined('ABSPATH') || exit;

/**
 * AI Post 异常类层次结构
 */

/**
 * 基础异常类
 */
class AIPostException extends \Exception
{
    protected $error_code;
    protected $error_data;
    
    public function __construct($message = "", $code = 0, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $previous);
        $this->error_code = $code;
        $this->error_data = $error_data;
    }
    
    public function get_error_code()
    {
        return $this->error_code;
    }
    
    public function get_error_data()
    {
        return $this->error_data;
    }
    
    public function to_array()
    {
        return [
            'error' => true,
            'code' => $this->error_code,
            'message' => $this->getMessage(),
            'data' => $this->error_data
        ];
    }
}

/**
 * API异常类
 */
class APIException extends AIPostException
{
    public function __construct($message = "API请求失败", $code = 500, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $error_data, $previous);
    }
}

/**
 * 数据库异常类
 */
class DatabaseException extends AIPostException
{
    public function __construct($message = "数据库操作失败", $code = 501, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $error_data, $previous);
    }
}

/**
 * 缓存异常类
 */
class CacheException extends AIPostException
{
    public function __construct($message = "缓存操作失败", $code = 502, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $error_data, $previous);
    }
}

/**
 * 配置异常类
 */
class ConfigException extends AIPostException
{
    public function __construct($message = "配置错误", $code = 503, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $error_data, $previous);
    }
}

/**
 * 验证异常类
 */
class ValidationException extends AIPostException
{
    public function __construct($message = "数据验证失败", $code = 400, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $error_data, $previous);
    }
}

/**
 * 权限异常类
 */
class PermissionException extends AIPostException
{
    public function __construct($message = "权限不足", $code = 403, $error_data = [], \Throwable $previous = null)
    {
        parent::__construct($message, $code, $error_data, $previous);
    }
}

/**
 * 异常处理器
 */
class ExceptionHandler
{
    private static $instance = null;
    private $log_file;
    private $debug_mode = false;
    
    /**
     * 获取单例实例
     */
    public static function get_instance()
    {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    private function __construct()
    {
        $this->log_file = WP_CONTENT_DIR . '/ai-post-error.log';
        $this->debug_mode = defined('WP_DEBUG') && WP_DEBUG;
    }
    
    /**
     * 注册异常和错误处理器
     */
    public static function register_handlers()
    {
        $handler = self::get_instance();
        
        // 设置异常处理器
        set_exception_handler([$handler, 'handle_exception']);
        
        // 设置错误处理器
        set_error_handler([$handler, 'handle_error']);
        
        // 设置致命错误处理器
        register_shutdown_function([$handler, 'handle_shutdown']);
        
        return $handler;
    }
    
    /**
     * 恢复原始处理器
     */
    public static function restore_handlers()
    {
        restore_error_handler();
        restore_exception_handler();
    }
    
    /**
     * 处理异常
     */
    public function handle_exception(\Throwable $exception)
    {
        $this->log_exception($exception);
        $this->display_exception($exception);
    }
    
    /**
     * 处理错误
     */
    public function handle_error($errno, $errstr, $errfile, $errline)
    {
        // 将错误转换为异常
        if (!(error_reporting() & $errno)) {
            return false;
        }
        
        $exception = new \ErrorException($errstr, 0, $errno, $errfile, $errline);
        $this->handle_exception($exception);
        
        return true;
    }
    
    /**
     * 处理致命错误
     */
    public function handle_shutdown()
    {
        $error = error_get_last();
        if ($error && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
            $exception = new \ErrorException(
                $error['message'],
                0,
                $error['type'],
                $error['file'],
                $error['line']
            );
            $this->handle_exception($exception);
        }
    }
    
    /**
     * 记录异常到日志
     */
    private function log_exception(\Throwable $exception)
    {
        $log_entry = sprintf(
            "[%s] %s: %s in %s:%d\nStack trace:\n%s\n\n",
            date('Y-m-d H:i:s'),
            get_class($exception),
            $exception->getMessage(),
            $exception->getFile(),
            $exception->getLine(),
            $exception->getTraceAsString()
        );
        
        // 写入日志文件
        file_put_contents($this->log_file, $log_entry, FILE_APPEND | LOCK_EX);
        
        // 同时写入PHP错误日志
        error_log($log_entry);
    }
    
    /**
     * 显示异常信息
     */
    private function display_exception(\Throwable $exception)
    {
        // 如果是AJAX请求，返回JSON格式错误
        if (defined('DOING_AJAX') && DOING_AJAX) {
            wp_send_json_error([
                'error' => true,
                'code' => $exception->getCode(),
                'message' => $this->debug_mode ? $exception->getMessage() : '操作失败，请稍后重试',
                'debug' => $this->debug_mode ? [
                    'file' => $exception->getFile(),
                    'line' => $exception->getLine(),
                    'trace' => $exception->getTrace()
                ] : null
            ]);
            exit;
        }
        
        // 如果是REST API请求，返回JSON格式错误
        if (defined('REST_REQUEST') && REST_REQUEST) {
            header('Content-Type: application/json');
            echo json_encode([
                'error' => true,
                'code' => $exception->getCode(),
                'message' => $this->debug_mode ? $exception->getMessage() : 'API请求失败',
                'debug' => $this->debug_mode ? [
                    'file' => $exception->getFile(),
                    'line' => $exception->getLine()
                ] : null
            ]);
            exit;
        }
        
        // 如果是管理员，显示详细错误信息
        if (current_user_can('manage_options') && $this->debug_mode) {
            echo '<div style="background:#f8d7da;border:1px solid #f5c6cb;color:#721c24;padding:15px;margin:20px;border-radius:4px;">';
            echo '<h3 style="margin-top:0;">AI Post 错误</h3>';
            echo '<p><strong>错误类型:</strong> ' . get_class($exception) . '</p>';
            echo '<p><strong>错误信息:</strong> ' . esc_html($exception->getMessage()) . '</p>';
            echo '<p><strong>文件:</strong> ' . esc_html($exception->getFile()) . ':' . $exception->getLine() . '</p>';
            echo '<pre style="background:#fff;padding:10px;border:1px solid #ddd;overflow:auto;">';
            echo esc_html($exception->getTraceAsString());
            echo '</pre>';
            echo '</div>';
        } else {
            // 普通用户显示友好错误信息
            if (is_admin()) {
                add_action('admin_notices', function() {
                    echo '<div class="notice notice-error"><p>AI Post: 发生错误，请检查错误日志或联系管理员。</p></div>';
                });
            }
        }
    }
    
    /**
     * 安全执行代码块，自动捕获异常
     */
    public static function safe_execute(callable $callback, $context = '')
    {
        try {
            return $callback();
        } catch (\Throwable $e) {
            $handler = self::get_instance();
            $handler->handle_exception($e);
            return null;
        }
    }
    
    /**
     * 处理异常（兼容旧版本）
     */
    public function handle(\Throwable $exception, $context = '')
    {
        $this->handle_exception($exception);
    }
}
?>