<?php

namespace Core;


class RouteHandler
{
    private $routes = [];
    private $middlewares = [];

    // Add a route with a specific method (GET or POST) and controller/method callback
    public function addRoute(string $name, ?string $path, string $method = 'GET', $controllerMethod = null)
    {
        $this->routes[$name] = [
            'path' => $path,
            'method' => strtoupper($method),
            'controllerMethod' => $controllerMethod,
        ];
    }

    // Add middleware for specific routes
    public function addMiddleware(string $route, callable $middleware)
    {
        $this->middlewares[$route] = $middleware;
    }

    // Handle the incoming request
    public function handleRequest()
    {
        try {
            // Check for both 'page' and 'app_route' parameters for backward compatibility
            $route = isset($_GET['page']) ? $_GET['page'] : (isset($_GET['app_route']) ? $_GET['app_route'] : '');
            $method = $_SERVER['REQUEST_METHOD']; // GET or POST

            // Debugging output: Log the route and method
            error_log("Requested Route: $route, Method: $method");

            // Check if the route exists and matches the request method
            if (isset($this->routes[$route])) {
                $routeInfo = $this->routes[$route];

                // Debugging output: Log the route information
                error_log("Route Info: " . print_r($routeInfo, true));

                if ($routeInfo['method'] !== $method) {
                    // If method doesn't match, show 405 Method Not Allowed
                    http_response_code(405);
                    include 'app/views/error/405.php';
                    return;
                }

                // Run middleware if exists for the route
                if (isset($this->middlewares[$route])) {
                    // Run middleware
                    ($this->middlewares[$route])();
                }

                // If there's a controller method defined, call it
                if ($routeInfo['controllerMethod']) {
                    $controllerMethod = $routeInfo['controllerMethod'];
                    $this->callControllerMethod($controllerMethod);
                } elseif ($routeInfo['path']) {
                    // If a path is defined, include it
                    include $routeInfo['path'];
                } else {
                    $this->handleError(404); // If neither controller nor path is defined
                }
            } else {
                // If route does not exist, show 404 Page Not Found
                $this->handleError(404);
            }
        } catch (\Exception $e) {
            // If an unexpected error occurs, log and show 500 Internal Server Error
          
            $this->handleError(500);
        }
    }

    // Call the controller's method dynamically
    private function callControllerMethod($controllerMethod)
    {
        list($controller, $method) = explode('@', $controllerMethod);

        // Debugging output: Log the controller and method to be called
        error_log("Controller: $controller, Method: $method");

        // Construct the controller file path
        $controllerPath = dirname(__DIR__) . '/app/controllers/' . $controller . '.php';
        
        // Debugging output: Log the constructed path
        error_log("Looking for controller at: $controllerPath");
        
        // Check if the controller file exists and include it
        if (file_exists($controllerPath)) {
            require_once $controllerPath;

            // Check if the class exists (try different variations)
            $controllerClass = $controller; // Try without namespace first
            $namespacedClass = 'App\\Controllers\\' . $controller; // Try with proper namespace
            $oldNamespaceClass = 'App\\controllers\\' . $controller; // Try with old namespace for compatibility
            
            // Try to use the autoloader for namespaced classes
            if (class_exists($namespacedClass)) {
                // Use the proper namespaced class via autoloader
                $controllerInstance = new $namespacedClass();
            } elseif (class_exists($controllerClass)) {
                // Use the non-namespaced class
                $controllerInstance = new $controllerClass();
            } elseif (class_exists($oldNamespaceClass)) {
                // Use the old namespaced class for compatibility
                $controllerInstance = new $oldNamespaceClass();
            } else {
                // Handle the case where no class exists
                $error_msg = "Class not found: " . $controller . " (tried: $controllerClass, $namespacedClass, $oldNamespaceClass)";
                $this->handleError(202, $error_msg);
                return;
            }

            // Check if the method exists within the controller instance
            if (method_exists($controllerInstance, $method)) {
                $controllerInstance->$method();
            } else {
                // Handle the case where the method doesn't exist
                $error_msg = "Method not found: " . $method . " in controller: " . $controller;
                $this->handleError(202, $error_msg);
            }
        } else {
            // Handle the case where the controller file doesn't exist
            $error_msg = "Controller file not found: " . $controllerPath . " (looking for: $controller)";
            $this->handleError(202, $error_msg);
        }
    }

    // Custom error handler
    private function handleError(int $errorCode, string $error_msg = '')
    {
        http_response_code($errorCode);

        switch ($errorCode) {
            case 404:
                include 'app/views/error/404.php';
                break;
            case 405:
                include 'app/views/error/405.php';
                break;
            case 500:
                include 'app/views/error/500.php';
                break;
            case 403:
                include 'app/views/error/403.php'; // Forbidden
                break;
            case 202:
                include 'app/views/error/error.php';
                break;
            default:
                include 'app/views/error/default.php'; // Generic error page
                break;
        }
    }
}
