<?phpnamespace App\Core;/** * Error Handler * Handles exceptions and errors, optionally displaying debug info. */class ErrorHandler{    /**     * @var Settings     */    protected $settings;    /**     * ErrorHandler constructor.     *     * @param Settings $settings     */    public function __construct(Settings $settings)    {        $this->settings = $settings;    }    /**     * Register exception and error handlers.     */    public function register(): void    {        set_exception_handler([$this, 'handleException']);        set_error_handler([$this, 'handleError']);        register_shutdown_function([$this, 'handleShutdown']);    }    /**     * Handle uncaught exceptions.     *     * @param \Throwable $exception     */    public function handleException(\Throwable $exception): void    {        $this->renderResponse($exception);    }    /**     * Handle PHP errors.     *     * @param int $level     * @param string $message     * @param string $file     * @param int $line     */    public function handleError(int $level, string $message, string $file, int $line): void    {        if (error_reporting() === 0) {            return; // Suppressed        }        throw new \ErrorException($message, 0, $level, $file, $line);    }    /**     * Handle shutdown events (fatal errors).     */    public function handleShutdown(): void    {        $error = error_get_last();        if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR], true)) {            $this->renderResponse(new \ErrorException($error['message'], 0, $error['type'], $error['file'], $error['line']));        }    }    /**     * Render error response.     *     * @param \Throwable $exception     */    protected function renderResponse(\Throwable $exception): void    {        $debug = $this->settings->get('APP_DEBUG', false);        $code = $exception->getCode() ?: 500;        // Set HTTP response code        http_response_code($code);        // If AJAX or JSON requested, return JSON        if ($this->isAjaxRequest()) {            header('Content-Type: application/json');            echo json_encode([                'error' => $exception->getMessage(),                'code' => $code,                'file' => $exception->getFile(),                'line' => $exception->getLine(),                'trace' => $debug ? $exception->getTrace() : null,            ]);            exit;        }        // Otherwise, render HTML error page        header('Content-Type: text/html; charset=utf-8');        if ($debug) {            // Show detailed error            include $this->getDebugTemplate($exception);        } else {            // Show generic error page            include $this->getGenericTemplate($code);        }        exit;    }    /**     * Check if request is AJAX.     *     * @return bool     */    protected function isAjaxRequest(): bool    {        return isset($_SERVER['HTTP_X_REQUESTED_WITH']) && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';    }    /**     * Path to debug error template.     *     * @param \Throwable $exception     * @return string     */    protected function getDebugTemplate(\Throwable $exception): string    {        // We'll create a simple debug view        ob_start();        ?>        <!DOCTYPE html>        <html lang="ar" dir="rtl">        <head>            <meta charset="UTF-8">            <title>??? ?? ???????</title>            <style>                body {font-family: sans-serif; margin: 20px; background: #f8f9fa; color: #212529;}                .container {max-width: 800px; margin: auto; background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1);}                h1 {color: #dc3545;}                .detail {margin: 15px 0; padding: 10px; background: #f8f9fa; border-left: 4px solid #dc3545;}                .trace {font-family: monospace; font-size: 0.9em; background: #f1f1f1; padding: 10px; overflow: auto;}                a {color: #007bff;}            </style>        </head>        <body>        <div class="container">            <h1>??? ??? ?? ???????</h1>            <p><strong>???????:</strong> <?= htmlspecialchars($exception->getMessage()) ?></p>            <div class="detail">                <strong>?????:</strong> <?= $exception->getCode() ?> <br>                <strong>?????:</strong> <?= htmlspecialchars($exception->getFile()) ?>:<br>                <strong>?????:</strong> <?= $exception->getLine() ?>            </div>            <div class="detail">                <strong>??????:</strong>                <div class="trace"><?= nl2br(htmlspecialchars($exception->getTraceAsString())) ?></div>            </div>        </div>        </body>        </html>        <?php        return ob_get_clean();    }    /**     * Path to generic error template.     *     * @param int $code     * @return string     */    protected function getGenericTemplate(int $code): string    {        ob_start();        ?>        <!DOCTYPE html>        <html lang="ar" dir="rtl">        <head>            <meta charset="UTF-8">            <title>??? <?= htmlspecialchars($code) ?></title>            <style>                body {font-family: sans-serif; margin: 20px; background: #f8f9fa; color: #212529; text-align: center;}                .container {max-width: 600px; margin: auto; padding: 40px;}                h1 {color: #dc3545;}                a {color: #007bff; text-decoration: none;}            </style>        </head>        <body>        <div class="container">            <h1>??? <?= htmlspecialchars($code) ?></h1>            <p>??? ??? ??? ?????. ???? ???????? ??????.</p>            <?php if ($code === 404): ?>                <p>?????? ???????? ??? ??????.</p>            <?php endif; ?>            <a href="<?= $_SERVER['HTTP_HOST'] ?? '/' ?>">?????? ??? ?????? ????????</a>        </div>        </body>        </html>        <?php        return ob_get_clean();    }}
