<?php

namespace App\Core;

class Router
{
    private $routes = [];

    public function __construct()
    {
        $this->registerRoutes();
    }

    private function registerRoutes()
    {
        // Rotas disponíveis
        $this->addRoute('POST', '/api/nfe/emitir', 'NFeController@emitir');
        $this->addRoute('POST', '/api/nfe/cancelar', 'NFeController@cancelar');
        $this->addRoute('POST', '/api/nfe/inutilizar', 'NFeController@inutilizar');
        $this->addRoute('POST', '/api/nfe/carta-correcao', 'NFeController@cartaCorrecao');
    }

    private function addRoute($method, $path, $handler)
    {
        $this->routes[] = [
            'method' => $method,
            'path' => $path,
            'handler' => $handler
        ];
    }

    public function dispatch()
    {
        $method = $_SERVER['REQUEST_METHOD'] ?? 'GET';
        $uri = parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH);

        // Remover o diretório base da URI
        $basePath = dirname($_SERVER['SCRIPT_NAME'] ?? '/');
        if ($basePath !== '/') {
            $uri = substr($uri, strlen($basePath));
        }

        // Remover /pontti_nfe/ da URI se existir
        if (strpos($uri, '/pontti_nfe/') === 0) {
            $uri = substr($uri, 11); // Remove '/pontti_nfe'
        } elseif (strpos($uri, '/pontti_nfe') === 0 && strlen($uri) === 11) {
            // Caso especial: URI é exatamente '/pontti_nfe'
            $uri = '/';
        }

        // Garantir que a URI comece com /
        if (!empty($uri) && $uri[0] !== '/') {
            $uri = '/' . $uri;
        }

        // Debug: Log da URI processada
        error_log("=== DEBUG ROUTER ===");
        error_log("REQUEST_URI: " . ($_SERVER['REQUEST_URI'] ?? 'N/A'));
        error_log("SCRIPT_NAME: " . ($_SERVER['SCRIPT_NAME'] ?? 'N/A'));
        error_log("Base path: " . $basePath);
        error_log("URI após parse_url: " . parse_url($_SERVER['REQUEST_URI'] ?? '/', PHP_URL_PATH));
        error_log("URI processada final: " . $uri);
        error_log("Method: " . $method);
        error_log("Rotas disponíveis: " . json_encode(array_map(function ($route) {
            return $route['method'] . ' ' . $route['path'];
        }, $this->routes)));

        foreach ($this->routes as $route) {
            if ($route['method'] === $method && $this->matchPath($route['path'], $uri)) {
                $this->executeHandler($route['handler'], $this->extractParams($route['path'], $uri));
                return;
            }
        }

        $this->sendResponse(404, [
            'cStat' => '404',
            'message' => 'Rota não encontrada: A rota solicitada não existe',
            'uri_requested' => $uri,
            'method' => $method,
            'available_routes' => array_map(function ($route) {
                return $route['method'] . ' ' . $route['path'];
            }, $this->routes)
        ]);
    }

    private function matchPath($routePath, $uri)
    {
        $routeRegex = preg_replace('/\{([^}]+)\}/', '([^/]+)', $routePath);
        $routeRegex = '#^' . $routeRegex . '$#';
        return preg_match($routeRegex, $uri);
    }

    private function extractParams($routePath, $uri)
    {
        $params = [];
        $routeParts = explode('/', trim($routePath, '/'));
        $uriParts = explode('/', trim($uri, '/'));

        foreach ($routeParts as $index => $part) {
            if (preg_match('/\{([^}]+)\}/', $part, $matches)) {
                $paramName = $matches[1];
                $params[$paramName] = $uriParts[$index] ?? null;
            }
        }

        return $params;
    }

    private function executeHandler($handler, $params)
    {
        list($controller, $method) = explode('@', $handler);
        $controllerClass = "App\\Controllers\\{$controller}";

        if (!class_exists($controllerClass)) {
            $this->sendResponse(500, ['error' => 'Controller não encontrado']);
            return;
        }

        $controllerInstance = new $controllerClass();

        if (!method_exists($controllerInstance, $method)) {
            $this->sendResponse(500, ['error' => 'Método não encontrado']);
            return;
        }

        try {
            $result = $controllerInstance->$method($params);

            // Se chegou até aqui, o controller retornou dados sem enviar resposta
            // Verificar se o controller definiu um status code específico
            $statusCode = http_response_code();
            if ($statusCode === 200) {
                $statusCode = 200; // Manter 200 se não foi alterado
            }

            $this->sendResponse($statusCode, $result);
        } catch (\Exception $e) {
            $this->sendResponse(500, ['error' => $e->getMessage()]);
        }
    }

    private function sendResponse($statusCode, $data)
    {
        // CORS já enviado no index.php
        http_response_code($statusCode);

        // Verificar se os headers já foram enviados
        if (!headers_sent()) {
            header('Content-Type: application/json');
        }

        echo json_encode($data, JSON_UNESCAPED_UNICODE);
        exit;
    }
}
