<?php
/**
 * Router - Roteador centralizado da API
 * Mapeia actions para controllers
 */

namespace Core;

use Controllers\AuthController;
use Controllers\SitesController;
use Controllers\UsersController;
use Controllers\PixController;
use Controllers\DashboardController;
use Controllers\SettingsController;
use Controllers\SecurityController;
use Controllers\ApiTokensController;

class Router
{
    /**
     * Mapeamento de rotas
     * Formato: 'action' => ['Controller', 'method', 'http_method' ou null para qualquer]
     */
    private static array $routes = [
        // ========== ROTAS PÚBLICAS ==========
        'login' => [AuthController::class , 'login', 'POST'],

        // ========== AUTH ==========
        'logout' => [AuthController::class , 'logout', 'POST'],
        'me' => [AuthController::class , 'me', 'GET'],
        'permissions' => [AuthController::class , null, null], // GET = list, PUT = update

        // ========== SITES ==========
        'sites' => [SitesController::class , null, null], // GET = index, POST = create, PUT = update, DELETE = delete
        'site' => [SitesController::class , null, null], // GET = show, PUT = update, DELETE = delete (singular)
        'sites/regenerate-key' => [SitesController::class , 'regenerateKey', 'POST'],
        'clear-site-events' => [SitesController::class , 'clearEvents', 'POST'],

        // ========== USERS ==========
        'users' => [UsersController::class , null, null], // GET = index, POST = create
        'user' => [UsersController::class , null, null], // GET = show, PUT = update, DELETE = delete (singular)
        'site-users' => [UsersController::class , 'bySite', 'GET'],

        // ========== PIX ==========
        'pix-config' => [PixController::class , null, null], // GET = getConfig, POST/PUT = saveConfig
        'pix-history' => [PixController::class , 'getHistory', 'GET'],
        'pix-stats' => [PixController::class , 'getStats', 'GET'],

        // ========== DASHBOARD / EVENTS ==========
        'dashboard' => [DashboardController::class , 'index', 'GET'],
        'comprehensive-report' => [DashboardController::class , 'comprehensiveReport', 'GET'],
        'get_notifs' => [DashboardController::class , 'getNotifs', 'GET'],
        'read_notifs' => [DashboardController::class , 'readNotifs', 'GET'],
        'events' => [DashboardController::class , null, null], // GET = list, POST = create
        'events/export' => [DashboardController::class , 'exportEvents', 'GET'],
        'event-types' => [DashboardController::class , 'eventTypes', 'GET'],

        // ========== SETTINGS ==========
        'api-token' => [SettingsController::class , 'apiToken', null], // GET e POST
        'ping' => [SettingsController::class , 'ping', 'GET'],

        // ========== API TOKENS (Gerenciamento de APIs externas) ==========
        'api-tokens' => [ApiTokensController::class , null, null], // GET = index, POST = create
        'api-token-item' => [ApiTokensController::class , null, null], // GET = show, PUT = update, DELETE = delete
        'api-token-test' => [ApiTokensController::class , 'test', 'POST'],
        'api-tokens-select' => [ApiTokensController::class , 'listForSelect', 'GET'],

        // ========== SECURITY / CONFIG POR SITE ==========
        'security-config' => [SecurityController::class , null, null], // GET = getConfig, POST = saveConfig
        'ip-rules' => [SecurityController::class , null, null], // GET = getIpRules, POST = addIpRule, DELETE = removeIpRule
        'security-ip-rules' => [SecurityController::class , null, null], // Alias para ip-rules
        'security-logs' => [SecurityController::class , null, null], // GET = getLogs, DELETE = clearLogs
        'audit-logs' => [SecurityController::class , 'getAuditLogs', 'GET'],

        // ========== ENDPOINTS PÚBLICOS (para sites consumirem) ==========
        'site-config' => [SecurityController::class , 'getPublicConfig', 'GET'], // Config completa para o site
        'security-report' => [SecurityController::class , 'reportEvent', 'POST'], // Sites reportam eventos
    ];

    /**
     * Despachar requisição para o controller correto
     */
    public static function dispatch(string $action, string $method): void
    {
        // Verificar se a rota existe
        if (!isset(self::$routes[$action])) {
            Response::notFound('Unknown action');
        }

        $route = self::$routes[$action];
        $controller = $route[0];
        $controllerMethod = $route[1];
        $allowedMethod = $route[2];

        // Verificar método HTTP se especificado
        if ($allowedMethod !== null && $method !== $allowedMethod) {
            Response::error("Method {$method} not allowed for this action", 405);
        }

        // Se o método não foi especificado na rota, determinar baseado no HTTP method
        if ($controllerMethod === null) {
            $controllerMethod = self::resolveMethodByHttp($action, $method);
        }

        // Verificar se o método existe no controller
        if (!method_exists($controller, $controllerMethod)) {
            Response::serverError("Controller method not found: {$controller}::{$controllerMethod}");
        }

        // Chamar o método do controller
        call_user_func([$controller, $controllerMethod]);
    }

    /**
     * Resolver método do controller baseado no HTTP method
     */
    private static function resolveMethodByHttp(string $action, string $httpMethod): string
    {
        $mapping = [
            'sites' => [
                'GET' => 'index',
                'POST' => 'create',
                'PUT' => 'update',
                'DELETE' => 'delete'
            ],
            'site' => [
                'GET' => 'show',
                'PUT' => 'update',
                'DELETE' => 'delete'
            ],
            'users' => [
                'GET' => 'index',
                'POST' => 'create'
            ],
            'user' => [
                'GET' => 'show',
                'PUT' => 'update',
                'DELETE' => 'delete'
            ],
            'permissions' => [
                'GET' => 'listPermissions',
                'PUT' => 'updatePermissions'
            ],
            'pix-config' => [
                'GET' => 'getConfig',
                'POST' => 'saveConfig',
                'PUT' => 'saveConfig'
            ],
            'api-token' => [
                'GET' => 'apiToken',
                'POST' => 'apiToken'
            ],
            'api-tokens' => [
                'GET' => 'index',
                'POST' => 'create',
                'PUT' => 'update',
                'DELETE' => 'delete'
            ],
            'api-token-item' => [
                'GET' => 'show',
                'PUT' => 'update',
                'DELETE' => 'delete'
            ],
            'security-config' => [
                'GET' => 'getConfig',
                'POST' => 'saveConfig'
            ],
            'ip-rules' => [
                'GET' => 'getIpRules',
                'POST' => 'addIpRule',
                'DELETE' => 'removeIpRule'
            ],
            'security-ip-rules' => [
                'GET' => 'getIpRules',
                'POST' => 'addIpRule',
                'DELETE' => 'removeIpRule'
            ],
            'security-logs' => [
                'GET' => 'getLogs',
                'DELETE' => 'clearLogs'
            ],
            'events' => [
                'GET' => 'events',
                'POST' => 'createEvent'
            ]
        ];

        if (isset($mapping[$action][$httpMethod])) {
            return $mapping[$action][$httpMethod];
        }

        Response::error("Method {$httpMethod} not allowed for action {$action}", 405);
        return ''; // Final return to satisfy lint, though Response::error exits.
    }

    /**
     * Verificar se uma action é pública (não requer autenticação)
     */
    public static function isPublicRoute(string $action): bool
    {
        $publicRoutes = ['login', 'site-config', 'security-report'];
        return in_array($action, $publicRoutes);
    }

    /**
     * Verificar se a action de pix-config deve ser tratada como pública
     * (quando vem com X-API-Key ao invés de autenticação de admin)
     */
    public static function shouldHandleAsPublic(string $action): bool
    {
        if ($action === 'pix-config') {
            $headers = getallheaders();
            return !empty($headers['X-API-Key'] ?? $headers['x-api-key'] ?? '');
        }
        return false;
    }

    /**
     * Listar todas as rotas disponíveis (para debug)
     */
    public static function listRoutes(): array
    {
        $list = [];
        foreach (self::$routes as $action => $config) {
            $list[] = [
                'action' => $action,
                'controller' => $config[0],
                'method' => $config[1] ?? 'dynamic',
                'http_method' => $config[2] ?? 'any'
            ];
        }
        return $list;
    }
}
