<?php
namespace Core;

/**
 * Base Controller
 * The traffic director. Provides methods to instantiate models, views, and JSON responses.
 */
abstract class Controller {
    
    protected $userId;

    public function __construct() {
        if (session_status() === PHP_SESSION_NONE) {
            session_start();
        }
        $this->userId = $_SESSION['user_id'] ?? null;
    }
    
    /**
     * Dynamic Model Loader
     * Supports namespaced models (App\Modules\...)
     */
    protected function model($modelPath) {
        $namespacedClass = '\\App\\Modules\\' . str_replace('/', '\\', $modelPath);
        if (class_exists($namespacedClass)) {
            return new $namespacedClass();
        }
        $file = ROOT_PATH . '/app/Modules/' . $modelPath . '.php';
        if (file_exists($file)) {
            require_once $file;
            $parts = explode('/', $modelPath);
            $className = end($parts);
            if (class_exists($className)) {
                return new $className();
            }
        }
        error_log("[OTIS] Model not found: {$modelPath}");
        throw new \RuntimeException("خطأ في النظام: تعذر تحميل النموذج ({$modelPath}).");
    }

    /**
     * Dynamic Service Loader
     */
    protected function service($serviceName) {
        $className = '\\Core\\Services\\' . $serviceName;
        if (class_exists($className)) {
            return new $className();
        }
        
        $file = ROOT_PATH . '/core/Services/' . $serviceName . '.php';
        if (file_exists($file)) {
            require_once $file;
            if (class_exists($className)) {
                return new $className();
            }
        }
        return null;
    }

    /**
     * Load a view and pass data to it.
     * $viewPath: e.g., 'Auth/Views/login' -> app/Modules/Auth/Views/login.php
     * Supports rendering within the global 'main.php' layout.
     */
    protected function view($viewPath, $data = [], $useGlobalLayout = true) {
        if (is_array($data)) {
            extract($data);
        }
        $file = __DIR__ . '/../app/Modules/' . $viewPath . '.php';
        if (!file_exists($file)) {
            error_log("[OTIS] View not found: {$viewPath}");
            throw new \RuntimeException("View not found: {$viewPath}");
        }
        if ($useGlobalLayout) {
            ob_start();
            require_once $file;
            $content = ob_get_clean();
            require_once __DIR__ . '/../app/Views/layouts/main.php';
        } else {
            require_once $file;
        }
    }
    
    /**
     * Returns Secure JSON response with correct headers for AJAX calls.
     */
    protected function jsonResponse($data, $statusCode = 200) {
        http_response_code($statusCode);
        header('Content-Type: application/json; charset=utf-8');
        echo json_encode($data, JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_HEX_AMP);
        exit;
    }

    /**
     * Unified JSON error response.
     * @param string $message  Human-readable error message (Arabic or English).
     * @param int    $code     HTTP status code (default 400).
     */
    protected function jsonError(string $message, int $code = 400) {
        $this->jsonResponse(['success' => false, 'error' => $message], $code);
    }

    /**
     * Unified exception handler for controllers.
     * - In AJAX context → returns a JSON error payload.
     * - In regular request → logs the error and shows a graceful message.
     *
     * Usage:
     *   try { ... } catch (\Throwable $e) { $this->handleException($e); }
     */
    protected function handleException(\Throwable $e, string $fallbackMessage = 'حدث خطأ غير متوقع. يرجى المحاولة لاحقاً.') {
        // Always log the real error server-side
        error_log('[OTIS Error] ' . get_class($e) . ': ' . $e->getMessage() . ' in ' . $e->getFile() . ':' . $e->getLine());

        $isAjax = !empty($_SERVER['HTTP_X_REQUESTED_WITH'])
                  && strtolower($_SERVER['HTTP_X_REQUESTED_WITH']) === 'xmlhttprequest';

        if ($isAjax) {
            // Never expose raw exception messages to the client
            $this->jsonError($fallbackMessage, 500);
        }

        // Graceful HTML response for non-AJAX
        http_response_code(500);
        
        $errorView = ROOT_PATH . '/app/Views/errors/500.php';
        if (file_exists($errorView)) {
            require_once $errorView;
        } else {
            echo '<div style="direction:rtl;font-family:sans-serif;padding:30px;background:#fff3f3;border-radius:8px;max-width:600px;margin:40px auto;">';
            echo '<h2 style="color:#c0392b;">⚠ خطأ في النظام</h2>';
            echo '<p>' . htmlspecialchars($fallbackMessage) . '</p>';
            echo '<a href="' . BASE_URL . '/" style="color:#2980b9;">← العودة للرئيسية</a>';
            echo '</div>';
        }
        exit;
    }
}
