<?php

/**
 * Error Handler Middleware
 * Handles errors and exceptions globally
 */
class ErrorHandler {
    
    /**
     * Register error and exception handlers
     */
    public static function register() {
        // Set error handler
        set_error_handler([self::class, 'handleError']);
        
        // Set exception handler
        set_exception_handler([self::class, 'handleException']);
        
        // Set shutdown handler for fatal errors
        register_shutdown_function([self::class, 'handleShutdown']);
    }
    
    /**
     * Handle PHP errors
     * 
     * @param int $errno Error number
     * @param string $errstr Error message
     * @param string $errfile File where error occurred
     * @param int $errline Line number
     * @return bool
     */
    public static function handleError($errno, $errstr, $errfile, $errline) {
        // Don't handle errors that are suppressed with @
        if (!(error_reporting() & $errno)) {
            return false;
        }
        
        // Map error types to severity levels
        $errorTypes = [
            E_ERROR => 'ERROR',
            E_WARNING => 'WARNING',
            E_PARSE => 'PARSE ERROR',
            E_NOTICE => 'NOTICE',
            E_CORE_ERROR => 'CORE ERROR',
            E_CORE_WARNING => 'CORE WARNING',
            E_COMPILE_ERROR => 'COMPILE ERROR',
            E_COMPILE_WARNING => 'COMPILE WARNING',
            E_USER_ERROR => 'USER ERROR',
            E_USER_WARNING => 'USER WARNING',
            E_USER_NOTICE => 'USER NOTICE',
            E_STRICT => 'STRICT',
            E_RECOVERABLE_ERROR => 'RECOVERABLE ERROR',
            E_DEPRECATED => 'DEPRECATED',
            E_USER_DEPRECATED => 'USER DEPRECATED'
        ];
        
        $errorType = $errorTypes[$errno] ?? 'UNKNOWN ERROR';
        
        // Log the error
        self::logError($errorType, $errstr, $errfile, $errline);
        
        // For fatal errors, display error page
        if (in_array($errno, [E_ERROR, E_CORE_ERROR, E_COMPILE_ERROR, E_USER_ERROR])) {
            self::displayErrorPage($errstr);
            exit(1);
        }
        
        // Don't execute PHP internal error handler
        return true;
    }
    
    /**
     * Handle uncaught exceptions
     * 
     * @param Throwable $exception
     */
    public static function handleException($exception) {
        // Log the exception
        self::logException($exception);
        
        // Display error page
        self::displayErrorPage($exception->getMessage());
        
        exit(1);
    }
    
    /**
     * Handle fatal errors on shutdown
     */
    public static function handleShutdown() {
        $error = error_get_last();
        
        if ($error !== null && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
            self::handleError(
                $error['type'],
                $error['message'],
                $error['file'],
                $error['line']
            );
        }
    }
    
    /**
     * Log error to file
     * 
     * @param string $type Error type
     * @param string $message Error message
     * @param string $file File where error occurred
     * @param int $line Line number
     */
    private static function logError($type, $message, $file, $line) {
        $logMessage = sprintf(
            "[%s] %s: %s in %s on line %d",
            date('Y-m-d H:i:s'),
            $type,
            $message,
            $file,
            $line
        );
        
        // Add stack trace for debugging
        $trace = debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS);
        $logMessage .= "\nStack trace:\n" . self::formatStackTrace($trace);
        
        error_log($logMessage . "\n\n", 3, ERROR_LOG_FILE);
    }
    
    /**
     * Log exception to file
     * 
     * @param Throwable $exception
     */
    private static function logException($exception) {
        $logMessage = sprintf(
            "[%s] EXCEPTION: %s: %s in %s on line %d",
            date('Y-m-d H:i:s'),
            get_class($exception),
            $exception->getMessage(),
            $exception->getFile(),
            $exception->getLine()
        );
        
        $logMessage .= "\nStack trace:\n" . $exception->getTraceAsString();
        
        error_log($logMessage . "\n\n", 3, ERROR_LOG_FILE);
    }
    
    /**
     * Format stack trace for logging
     * 
     * @param array $trace
     * @return string
     */
    private static function formatStackTrace($trace) {
        $output = '';
        
        foreach ($trace as $i => $frame) {
            $file = $frame['file'] ?? '[internal function]';
            $line = $frame['line'] ?? '';
            $function = $frame['function'] ?? '';
            $class = $frame['class'] ?? '';
            $type = $frame['type'] ?? '';
            
            $output .= sprintf(
                "#%d %s(%s): %s%s%s()\n",
                $i,
                $file,
                $line,
                $class,
                $type,
                $function
            );
        }
        
        return $output;
    }
    
    /**
     * Display user-friendly error page
     * 
     * @param string $message Error message
     */
    private static function displayErrorPage($message) {
        // Clear any output buffers
        while (ob_get_level()) {
            ob_end_clean();
        }
        
        http_response_code(500);
        
        // Check if we're in production mode
        $isProduction = (error_reporting() === 0);
        
        // In production, show generic message
        if ($isProduction) {
            $displayMessage = 'An error occurred. Please try again later.';
        } else {
            $displayMessage = htmlspecialchars($message);
        }
        
        // Check if it's an AJAX request
        if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
            strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
            
            header('Content-Type: application/json');
            echo json_encode([
                'success' => false,
                'error' => $displayMessage
            ]);
            return;
        }
        
        // Display HTML error page
        ?>
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>Error - Birthday Reminder</title>
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
            <style>
                body {
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    min-height: 100vh;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }
                .error-container {
                    background: white;
                    border-radius: 15px;
                    padding: 40px;
                    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
                    max-width: 600px;
                    text-align: center;
                }
                .error-icon {
                    font-size: 80px;
                    color: #dc3545;
                    margin-bottom: 20px;
                }
                .error-title {
                    font-size: 32px;
                    font-weight: bold;
                    color: #333;
                    margin-bottom: 15px;
                }
                .error-message {
                    font-size: 16px;
                    color: #666;
                    margin-bottom: 30px;
                }
                .btn-home {
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    border: none;
                    padding: 12px 30px;
                    font-size: 16px;
                    border-radius: 25px;
                    color: white;
                    text-decoration: none;
                    display: inline-block;
                    transition: transform 0.2s;
                }
                .btn-home:hover {
                    transform: translateY(-2px);
                    color: white;
                }
            </style>
        </head>
        <body>
            <div class="error-container">
                <div class="error-icon">⚠️</div>
                <h1 class="error-title">Oops! Something went wrong</h1>
                <p class="error-message"><?= $displayMessage ?></p>
                <a href="<?php echo URL_PATH; ?>/admin/dashboard" class="btn-home">Go to Dashboard</a>
            </div>
        </body>
        </html>
        <?php
    }
    
    /**
     * Display 404 error page
     * 
     * @param string $message Optional custom message
     */
    public static function display404($message = 'Page not found') {
        http_response_code(404);
        
        // Check if it's an AJAX request
        if (!empty($_SERVER['HTTP_X_REQUESTED_WITH']) && 
            strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest') {
            
            header('Content-Type: application/json');
            echo json_encode([
                'success' => false,
                'error' => $message
            ]);
            exit;
        }
        
        ?>
        <!DOCTYPE html>
        <html lang="en">
        <head>
            <meta charset="UTF-8">
            <meta name="viewport" content="width=device-width, initial-scale=1.0">
            <title>404 - Page Not Found</title>
            <link href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.0/dist/css/bootstrap.min.css" rel="stylesheet">
            <style>
                body {
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    min-height: 100vh;
                    display: flex;
                    align-items: center;
                    justify-content: center;
                }
                .error-container {
                    background: white;
                    border-radius: 15px;
                    padding: 40px;
                    box-shadow: 0 10px 40px rgba(0,0,0,0.2);
                    max-width: 600px;
                    text-align: center;
                }
                .error-code {
                    font-size: 120px;
                    font-weight: bold;
                    color: #667eea;
                    line-height: 1;
                    margin-bottom: 20px;
                }
                .error-title {
                    font-size: 32px;
                    font-weight: bold;
                    color: #333;
                    margin-bottom: 15px;
                }
                .error-message {
                    font-size: 16px;
                    color: #666;
                    margin-bottom: 30px;
                }
                .btn-home {
                    background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
                    border: none;
                    padding: 12px 30px;
                    font-size: 16px;
                    border-radius: 25px;
                    color: white;
                    text-decoration: none;
                    display: inline-block;
                    transition: transform 0.2s;
                }
                .btn-home:hover {
                    transform: translateY(-2px);
                    color: white;
                }
            </style>
        </head>
        <body>
            <div class="error-container">
                <div class="error-code">404</div>
                <h1 class="error-title">Page Not Found</h1>
                <p class="error-message"><?= htmlspecialchars($message) ?></p>
                <a href="<?php echo URL_PATH; ?>/admin/dashboard" class="btn-home">Go to Dashboard</a>
            </div>
        </body>
        </html>
        <?php
        exit;
    }
}
