<?php
namespace Core;

class Router {
    private array $routes = [];
    private array $middleware = [];
    private string $currentPrefix = '';
    private array $currentMiddleware = [];
    
    public function __construct() {
        $this->registerDefaultRoutes();
    }
    
    public function get(string $path, array $handler, array $middleware = []): void {
        $this->addRoute('GET', $path, $handler, $middleware);
    }
    
    public function post(string $path, array $handler, array $middleware = []): void {
        $this->addRoute('POST', $path, $handler, $middleware);
    }
    
    public function group(string $prefix, callable $callback, array $middleware = []): void {
        $previousPrefix = $this->currentPrefix;
        $previousMiddleware = $this->currentMiddleware;
        
        $this->currentPrefix .= $prefix;
        $this->currentMiddleware = array_merge($this->currentMiddleware, $middleware);
        
        $callback($this);
        
        $this->currentPrefix = $previousPrefix;
        $this->currentMiddleware = $previousMiddleware;
    }
    
    private function addRoute(string $method, string $path, array $handler, array $middleware): void {
        $fullPath = $this->currentPrefix . $path;
        $fullMiddleware = array_merge($this->currentMiddleware, $middleware);
        $this->routes[] = [
            'method' => $method,
            'path' => $fullPath,
            'handler' => $handler,
            'middleware' => $fullMiddleware
        ];
    }
    
    public function run(): void {
        $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
        $rawUri = $_SERVER['REQUEST_URI'] ?? '/';
        $uri = parse_url($rawUri, PHP_URL_PATH) ?? '/';
        
        $base = parse_url(APP_URL, PHP_URL_PATH);
        if ($base && $base !== '/' && stripos($uri, $base) === 0) {
            $uri = substr($uri, strlen($base));
        }
        
        // Strip leading /index.php if present in URI
        $uri = preg_replace('#^/index\.php#i', '', $uri);
        
        $uri = rtrim($uri, '/');
        if ($uri === '' || $uri === false) {
            $uri = '/';
        }
        
        $this->dispatch($method, $uri);
    }
    
    private function dispatch(string $method, string $uri): void {
        foreach ($this->routes as $route) {
            if ($route['method'] !== $method) {
                continue;
            }
            
            $params = $this->matchRoute($route['path'], $uri);
            if ($params !== false) {
                $this->callMiddleware($route['middleware']);
                
                [$class, $methodToCall] = $route['handler'];
                $controllerClass = $this->resolveControllerClass($class);
                
                if ($controllerClass && class_exists($controllerClass)) {
                    $controller = new $controllerClass();
                    if (method_exists($controller, $methodToCall)) {
                        call_user_func_array([$controller, $methodToCall], array_values($params));
                        return;
                    }
                }
            }
        }
        
        $this->notFound();
    }
    
    private function resolveControllerClass(string $class): ?string {
        if (class_exists($class)) {
            return $class;
        }

        // Try namespaces for namespaced controllers
        $baseName = basename(str_replace('\\', '/', $class));
        $moduleGuess = str_replace('Controller', '', $baseName);
        
        $moduleMap = [
            'DailyReport'     => 'Reports',
            'ReportTemplate'  => 'Reports',
            'Invoice'         => 'Finance',
            'Budget'          => 'Finance',
            'Expense'         => 'Finance',
            'Billing'         => 'Finance',
            'Role'            => 'Users',
            'User'            => 'Users',
            'Project'         => 'Projects',
            'Client'          => 'Clients',
            'Contractor'      => 'Contractors',
            'Supplier'        => 'Suppliers',
            'Dashboard'       => 'Dashboard',
            'Notification'    => 'Notifications',
            'Settings'        => 'Settings',
        ];

        $moduleName = $moduleMap[$moduleGuess] ?? ($moduleGuess . 's');

        $candidates = [
            "Modules\\{$moduleName}\\Controllers\\{$baseName}",
            "App\\Modules\\{$moduleName}\\Controllers\\{$baseName}",
            "\\Modules\\{$moduleName}\\Controllers\\{$baseName}",
            "\\App\\Modules\\{$moduleName}\\Controllers\\{$baseName}",
        ];

        foreach ($candidates as $candidate) {
            if (class_exists($candidate)) {
                return $candidate;
            }
        }

        return null;
    }
    
    private function matchRoute(string $pattern, string $uri): array|false {
        $patternNorm = rtrim($pattern, '/');
        if ($patternNorm === '') $patternNorm = '/';
        
        if ($patternNorm === $uri) {
            return [];
        }
        
        $patternRegex = preg_replace('/\{([a-zA-Z0-9_]+)\}/', '(?P<\1>[a-zA-Z0-9_-]+)', $patternNorm);
        $patternRegex = "#^" . $patternRegex . "$#";
        
        if (preg_match($patternRegex, $uri, $matches)) {
            $params = [];
            foreach ($matches as $key => $value) {
                if (is_string($key)) {
                    $params[$key] = $value;
                }
            }
            return $params;
        }
        
        return false;
    }
    
    private function callMiddleware(array $middleware): void {
        foreach ($middleware as $m) {
            if (class_exists($m)) {
                $instance = new $m();
                if (method_exists($instance, 'handle')) {
                    $instance->handle();
                }
            }
        }
    }
    
    private function notFound(): void {
        http_response_code(404);
        if (defined('APP_ENV') && APP_ENV === 'development') {
            $rawUri = $_SERVER['REQUEST_URI'] ?? '';
            $method = $_SERVER['REQUEST_METHOD'] ?? '';
            echo "<!-- DEV DEBUG: Method={$method}, RawURI={$rawUri}, APP_URL=" . APP_URL . " -->";
        }
        $viewFile = ROOT_PATH . '/modules/shared/views/404.php';
        if (file_exists($viewFile)) {
            require $viewFile;
        } else {
            echo "<h1>404 Not Found</h1><p>The requested page could not be found.</p>";
        }
        exit;
    }

    private function registerDefaultRoutes(): void {
        // Public marketing site
        $this->get('/', ['MarketingController', 'home']);
        $this->get('/pricing', ['MarketingController', 'pricing']);

        // Auth
        $this->get('/login', ['AuthController', 'showLogin']);
        $this->post('/login', ['AuthController', 'handleLogin']);
        $this->get('/logout', ['AuthController', 'logout']);
        $this->get('/signup', ['AuthController', 'showSignup']);
        $this->post('/signup', ['AuthController', 'handleSignup']);
        
        $this->get('/otp/setup', ['AuthController', 'showOtpSetup']);
        $this->post('/otp/setup', ['AuthController', 'handleOtpSetup']);
        $this->get('/otp/verify', ['AuthController', 'showOtpVerify']);
        $this->post('/otp/verify', ['AuthController', 'handleOtpVerify']);
        
        $this->get('/forgot-password', ['AuthController', 'showForgotPassword']);
        $this->post('/forgot-password', ['AuthController', 'handleForgotPassword']);
        $this->get('/reset-password/{token}', ['AuthController', 'showResetPassword']);
        $this->post('/reset-password', ['AuthController', 'handleResetPassword']);

        // Subscription payment (trial-expiry flow — reached logged-out, via billing session context)
        $this->get('/billing/pay', ['SubscriptionController', 'showPay']);
        $this->post('/billing/pay/initiate', ['SubscriptionController', 'initiate']);
        $this->get('/billing/pay/callback', ['SubscriptionController', 'callback']);
        $this->post('/webhooks/flutterwave', ['SubscriptionController', 'webhook']);

        // Dashboard
        $this->get('/dashboard', ['DashboardController', 'index']);
        $this->get('/dashboard/org', ['DashboardController', 'orgDashboard']);
        $this->get('/dashboard/contractor', ['DashboardController', 'contractorDashboard']);
        $this->get('/dashboard/admin', ['DashboardController', 'superAdminDashboard']);
        
        // Projects (static routes before dynamic {id})
        $this->get('/projects', ['ProjectController', 'index']);
        $this->get('/projects/create', ['ProjectController', 'create']);
        $this->post('/projects/create', ['ProjectController', 'store']);
        $this->get('/projects/categories', ['ProjectController', 'categories']);
        $this->post('/projects/categories/create', ['ProjectController', 'createCategory']);
        $this->post('/projects/categories/{id}/edit', ['ProjectController', 'editCategory']);
        $this->post('/projects/categories/{id}/delete', ['ProjectController', 'deleteCategory']);
        $this->get('/projects/{id}', ['ProjectController', 'show']);
        $this->get('/projects/{id}/edit', ['ProjectController', 'edit']);
        $this->post('/projects/{id}/edit', ['ProjectController', 'update']);
        $this->post('/projects/{id}/delete', ['ProjectController', 'delete']);
        $this->post('/projects/{id}/assign-contractors', ['ProjectController', 'assignContractors']);
        $this->get('/projects/{id}/contractor-response', ['ProjectController', 'contractorResponse']);
        $this->post('/projects/{id}/contractor-response', ['ProjectController', 'contractorResponse']);
        $this->post('/projects/{id}/upload-document', ['ProjectController', 'uploadDocument']);
        $this->post('/projects/documents/{id}/delete', ['ProjectController', 'deleteDocument']);
        $this->get('/projects/{id}/milestones', ['ProjectController', 'milestones']);
        $this->post('/projects/{id}/milestones/create', ['ProjectController', 'createMilestone']);
        $this->post('/projects/milestones/{id}/update', ['ProjectController', 'updateMilestone']);
        $this->post('/projects/milestones/{id}/delete', ['ProjectController', 'deleteMilestone']);
        
        // Clients
        $this->get('/clients', ['ClientController', 'index']);
        $this->get('/clients/create', ['ClientController', 'create']);
        $this->post('/clients/create', ['ClientController', 'store']);
        $this->get('/clients/{id}', ['ClientController', 'show']);
        $this->get('/clients/{id}/edit', ['ClientController', 'edit']);
        $this->post('/clients/{id}/edit', ['ClientController', 'update']);
        $this->post('/clients/{id}/delete', ['ClientController', 'delete']);
        
        // Contractors
        $this->get('/contractors', ['ContractorController', 'index']);
        $this->get('/contractors/create', ['ContractorController', 'create']);
        $this->post('/contractors/create', ['ContractorController', 'store']);
        $this->get('/contractors/{id}', ['ContractorController', 'show']);
        $this->get('/contractors/{id}/edit', ['ContractorController', 'edit']);
        $this->post('/contractors/{id}/edit', ['ContractorController', 'update']);
        $this->post('/contractors/{id}/approve', ['ContractorController', 'approve']);
        $this->post('/contractors/{id}/delete', ['ContractorController', 'suspend']);
        $this->post('/contractors/{id}/upload-doc', ['ContractorController', 'uploadDocument']);
        $this->post('/contractors/docs/{id}/delete', ['ContractorController', 'deleteDocument']);
        $this->post('/contractors/{id}/add-user', ['ContractorController', 'addUser']);
        $this->post('/contractors/{id}/remove-user/{userId}', ['ContractorController', 'removeUser']);

        // Suppliers
        $this->get('/suppliers', ['SupplierController', 'index']);
        $this->get('/suppliers/create', ['SupplierController', 'create']);
        $this->post('/suppliers/create', ['SupplierController', 'store']);
        $this->get('/suppliers/{id}', ['SupplierController', 'show']);
        $this->get('/suppliers/{id}/edit', ['SupplierController', 'edit']);
        $this->post('/suppliers/{id}/edit', ['SupplierController', 'update']);
        $this->post('/suppliers/{id}/approve', ['SupplierController', 'approve']);
        $this->post('/suppliers/{id}/delete', ['SupplierController', 'suspend']);
        $this->post('/suppliers/{id}/upload-doc', ['SupplierController', 'uploadDocument']);
        $this->post('/suppliers/docs/{id}/delete', ['SupplierController', 'deleteDocument']);
        $this->post('/suppliers/{id}/add-user', ['SupplierController', 'addUser']);
        $this->post('/suppliers/{id}/remove-user/{userId}', ['SupplierController', 'removeUser']);
        
        // Finance
        $this->get('/finance/invoices', ['InvoiceController', 'index']);
        $this->get('/finance/invoices/create', ['InvoiceController', 'create']);
        $this->post('/finance/invoices/create', ['InvoiceController', 'store']);
        $this->get('/finance/invoices/export', ['InvoiceController', 'export']);
        $this->get('/finance/invoices/{id}/edit', ['InvoiceController', 'edit']);
        $this->post('/finance/invoices/{id}/edit', ['InvoiceController', 'update']);
        $this->get('/finance/invoices/{id}', ['InvoiceController', 'show']);
        $this->post('/finance/invoices/{id}/submit', ['InvoiceController', 'submit']);
        $this->post('/finance/invoices/{id}/review', ['InvoiceController', 'review']);
        $this->post('/finance/invoices/{id}/approve', ['InvoiceController', 'approve']);
        $this->post('/finance/invoices/{id}/reject', ['InvoiceController', 'reject']);
        $this->post('/finance/invoices/{id}/paid', ['InvoiceController', 'markPaid']);
        $this->post('/finance/invoices/{id}/comment', ['InvoiceController', 'comment']);
        $this->get('/finance/invoices/{id}/pdf', ['InvoiceController', 'downloadPdf']);
        
        $this->get('/finance/budgets/{projectId}', ['BudgetController', 'index']);
        $this->post('/finance/budgets/{projectId}/item', ['BudgetController', 'storeItem']);
        $this->post('/finance/budgets/item/{id}/update', ['BudgetController', 'updateItem']);
        $this->post('/finance/budgets/item/{id}/delete', ['BudgetController', 'deleteItem']);
        
        $this->get('/finance/expenses', ['ExpenseController', 'index']);
        $this->post('/finance/expenses/create', ['ExpenseController', 'store']);
        $this->post('/finance/expenses/{id}/delete', ['ExpenseController', 'delete']);
        
        $this->get('/finance/billing', ['BillingController', 'index']);
        $this->post('/finance/billing/{chargeId}/pay', ['BillingController', 'recordPayment']);
        
        // Reports
        $this->get('/reports/templates', ['ReportTemplateController', 'index']);
        $this->get('/reports/templates/create', ['ReportTemplateController', 'create']);
        $this->post('/reports/templates/create', ['ReportTemplateController', 'store']);
        $this->get('/reports/templates/{id}/edit', ['ReportTemplateController', 'edit']);
        $this->post('/reports/templates/{id}/edit', ['ReportTemplateController', 'update']);
        $this->post('/reports/templates/{id}/delete', ['ReportTemplateController', 'delete']);
        
        $this->get('/reports/daily', ['DailyReportController', 'index']);
        $this->get('/reports/daily/create', ['DailyReportController', 'create']);
        $this->post('/reports/daily/create', ['DailyReportController', 'store']);
        $this->get('/reports/daily/progress', ['DailyReportController', 'progressDashboard']);
        $this->get('/reports/daily/{id}', ['DailyReportController', 'show']);
        $this->post('/reports/daily/{id}/review', ['DailyReportController', 'review']);
        
        // Users & Roles
        $this->get('/users', ['UserController', 'index']);
        $this->get('/users/create', ['UserController', 'create']);
        $this->post('/users/create', ['UserController', 'store']);
        $this->get('/users/roles', ['RoleController', 'index']);
        $this->get('/users/roles/create', ['RoleController', 'create']);
        $this->post('/users/roles/create', ['RoleController', 'store']);
        $this->get('/users/roles/{id}/edit', ['RoleController', 'edit']);
        $this->post('/users/roles/{id}/edit', ['RoleController', 'update']);
        $this->post('/users/roles/{id}/delete', ['RoleController', 'delete']);
        $this->get('/users/{id}', ['UserController', 'show']);
        $this->get('/users/{id}/edit', ['UserController', 'edit']);
        $this->post('/users/{id}/edit', ['UserController', 'update']);
        $this->post('/users/{id}/toggle-active', ['UserController', 'toggleActive']);
        $this->post('/users/{id}/reset-password', ['UserController', 'resetPassword']);
        $this->post('/users/{id}/disable-2fa', ['UserController', 'disableOtp']);

        $this->get('/profile', ['UserController', 'updateProfile']);
        $this->post('/profile', ['UserController', 'updateProfile']);
        $this->post('/profile/change-password', ['UserController', 'changePassword']);

        
        // Notifications
        $this->get('/notifications', ['NotificationController', 'index']);
        $this->post('/notifications/{id}/read', ['NotificationController', 'markAsRead']);
        $this->post('/notifications/{id}/delete', ['NotificationController', 'delete']);
        $this->post('/notifications/read-all', ['NotificationController', 'markAllAsRead']);
        $this->get('/api/notifications/count', ['NotificationController', 'unreadCount']);
        
        // Settings & System
        $this->get('/settings', ['SettingsController', 'orgSettings']);
        $this->post('/settings', ['SettingsController', 'updateOrgSettings']);
        $this->get('/settings/security', ['SettingsController', 'securitySettings']);
        $this->post('/settings/disable-otp', ['SettingsController', 'disableOtp']);
        $this->post('/settings/revoke-session/{token}', ['SettingsController', 'revokeSession']);
        $this->get('/settings/email', ['SettingsController', 'emailSettings']);
        $this->post('/settings/email', ['SettingsController', 'updateEmailSettings']);
        $this->post('/settings/email/test', ['SettingsController', 'testEmail']);
        $this->get('/settings/billing', ['SettingsController', 'billingSettings']);
        $this->get('/settings/audit', ['SettingsController', 'auditLog']);
        
        $this->get('/admin/system', ['SettingsController', 'systemSettings']);
        $this->post('/admin/system', ['SettingsController', 'updateSystemSettings']);
        $this->get('/admin/plans', ['SettingsController', 'plans']);
        $this->post('/admin/plans', ['SettingsController', 'savePlan']);
        $this->post('/admin/plans/{id}/prices', ['SettingsController', 'savePlanPrices']);
        $this->get('/admin/organizations', ['OrganizationController', 'index']);
        $this->get('/admin/organizations/{id}/edit', ['OrganizationController', 'edit']);
        $this->post('/admin/organizations/{id}/edit', ['OrganizationController', 'update']);
        $this->post('/admin/organizations/{id}/approve', ['OrganizationController', 'approve']);
        $this->post('/admin/organizations/{id}/reject', ['OrganizationController', 'reject']);
        $this->post('/admin/organizations/{id}/suspend', ['OrganizationController', 'suspend']);
        $this->post('/admin/organizations/{id}/reactivate', ['OrganizationController', 'reactivate']);
        $this->post('/admin/organizations/{id}/delete', ['OrganizationController', 'delete']);
        $this->get('/admin/organizations/{id}', ['OrganizationController', 'show']);
    }
}
