<?php
/**
 * API Endpoint Principal - Admin Server
 * Recebe eventos dos sites clientes
 */

require_once __DIR__ . '/../../config/database.php';

header('Content-Type: application/json; charset=utf-8');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: POST, GET, OPTIONS');
header('Access-Control-Allow-Headers: Content-Type, Authorization, X-API-Key, X-Signature');

// Handle preflight
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    exit(0);
}

/**
 * Resposta JSON padronizada
 */
function jsonResponse(array $data, int $code = 200): void {
    http_response_code($code);
    echo json_encode($data, JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * Obter API Key do header ou query string
 * Suporta múltiplas formas de envio para compatibilidade
 */
function getApiKey(): ?string {
    // 1. Tentar via query string (mais confiável)
    if (!empty($_GET['api_key'])) {
        return $_GET['api_key'];
    }
    
    // 2. Tentar via $_SERVER (funciona em nginx/php-fpm)
    if (!empty($_SERVER['HTTP_X_API_KEY'])) {
        return $_SERVER['HTTP_X_API_KEY'];
    }
    
    // 3. Tentar via getallheaders() (Apache)
    if (function_exists('getallheaders')) {
        $headers = getallheaders();
        // Case-insensitive search
        foreach ($headers as $key => $value) {
            if (strtolower($key) === 'x-api-key') {
                return $value;
            }
        }
    }
    
    // 4. Verificar Authorization header como fallback
    $auth = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (preg_match('/^Bearer\s+(.+)$/i', $auth, $matches)) {
        return $matches[1];
    }
    
    return null;
}

/**
 * Verificar rate limit
 */
function checkRateLimit(int $siteId, string $ip, int $limit): bool {
    $pdo = getDBConnection();
    $windowStart = date('Y-m-d H:i:00'); // Janela de 1 minuto
    
    // Incrementar contador
    $stmt = $pdo->prepare("
        INSERT INTO rate_limits (site_id, ip_address, request_count, window_start)
        VALUES (?, ?, 1, ?)
        ON DUPLICATE KEY UPDATE request_count = request_count + 1
    ");
    $stmt->execute([$siteId, $ip, $windowStart]);
    
    // Verificar se excedeu
    $stmt = $pdo->prepare("
        SELECT request_count FROM rate_limits 
        WHERE site_id = ? AND ip_address = ? AND window_start = ?
    ");
    $stmt->execute([$siteId, $ip, $windowStart]);
    $count = $stmt->fetchColumn();
    
    return $count <= $limit;
}

/**
 * Obter geolocalização do IP
 */
function getGeoLocation(string $ip): array {
    // IPs locais
    if ($ip === '127.0.0.1' || $ip === '::1' || strpos($ip, '192.168.') === 0 || strpos($ip, '10.') === 0) {
        return ['city' => 'Local', 'region' => 'Local', 'country' => 'BR', 'isp' => 'Local'];
    }
    
    try {
        $ctx = stream_context_create(['http' => ['timeout' => 2]]);
        $response = @file_get_contents("http://ip-api.com/json/{$ip}?fields=status,city,regionName,countryCode,isp&lang=pt-BR", false, $ctx);
        
        if ($response) {
            $data = json_decode($response, true);
            if ($data && ($data['status'] ?? '') === 'success') {
                return [
                    'city' => $data['city'] ?? '',
                    'region' => $data['regionName'] ?? '',
                    'country' => $data['countryCode'] ?? 'BR',
                    'isp' => $data['isp'] ?? ''
                ];
            }
        }
    } catch (Exception $e) {}
    
    return ['city' => '', 'region' => '', 'country' => '', 'isp' => ''];
}

/**
 * Gerar/Obter visitor ID
 */
function getVisitorId(string $ip, string $userAgent): string {
    return hash('sha256', $ip . '|' . $userAgent . '|' . date('Y-m'));
}

// ===============================
// ROTEAMENTO
// ===============================

$method = $_SERVER['REQUEST_METHOD'];
$path = $_GET['action'] ?? '';

// Autenticar API Key
$apiKey = getApiKey();
if (!$apiKey) {
    jsonResponse(['status' => 'error', 'message' => 'API Key required'], 401);
}

$site = validateApiKey($apiKey);
if (!$site) {
    logAudit('invalid_api_key', null, "Key: {$apiKey}");
    jsonResponse(['status' => 'error', 'message' => 'Invalid API Key'], 401);
}

$siteId = (int)$site['id'];
$ip = $_SERVER['REMOTE_ADDR'] ?? '';

// Rate limiting
if (!checkRateLimit($siteId, $ip, $site['rate_limit'] ?? 1000)) {
    jsonResponse(['status' => 'error', 'message' => 'Rate limit exceeded'], 429);
}

// ===============================
// ENDPOINTS
// ===============================

switch ($path) {

    // ------------------------------
    // TRACK - Registrar evento
    // ------------------------------
    case 'track':
        if ($method !== 'POST') {
            jsonResponse(['status' => 'error', 'message' => 'Method not allowed'], 405);
        }
        
        $input = json_decode(file_get_contents('php://input'), true);
        if (!$input || !isset($input['event_type'])) {
            jsonResponse(['status' => 'error', 'message' => 'Invalid event data'], 400);
        }
        
        $pdo = getDBConnection();
        $userAgent = $input['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'] ?? '';
        $visitorId = $input['visitor_id'] ?? getVisitorId($ip, $userAgent);
        $sessionId = $input['session_id'] ?? null;
        
        // IP real do cliente - usar o que veio do site cliente (que já processou os headers)
        // O IP que chega aqui é o IP do servidor do site, não do visitante real
        $clientIp = $input['ip_address'] ?? $ip;
        
        // Geolocalização - usar IP real do cliente
        $geo = getGeoLocation($clientIp);
        
        // Metadados
        $metadata = $input['metadata'] ?? [];

        // Extrair dados específicos
        $placa = $input['placa'] ?? $metadata['placa'] ?? null;
        $renavam = $input['renavam'] ?? $metadata['renavam'] ?? null;
        $valor = $input['valor'] ?? $metadata['valor'] ?? null;
        if ($valor) $valor = floatval($valor);

        // UTM
        $utm = $metadata['utm'] ?? [];

        // PROTEÇÃO CONTRA DUPLICAÇÃO
        // Verificar se já existe evento similar nos últimos 5 segundos
        $stmt = $pdo->prepare("
            SELECT id FROM events
            WHERE site_id = ?
              AND event_type = ?
              AND ip_address = ?
              AND created_at > DATE_SUB(NOW(), INTERVAL 5 SECOND)
              AND (placa = ? OR (placa IS NULL AND ? IS NULL))
            LIMIT 1
        ");
        $stmt->execute([$siteId, $input['event_type'], $clientIp, $placa, $placa]);

        if ($stmt->fetch()) {
            // Evento duplicado - ignorar silenciosamente
            jsonResponse([
                'status' => 'success',
                'message' => 'Event already tracked',
                'duplicate' => true,
                'visitor_id' => $visitorId
            ]);
        }

        try {
            $stmt = $pdo->prepare("
                INSERT INTO events (
                    site_id, event_type, session_id, visitor_id, ip_address, user_agent,
                    referrer, page_url, placa, renavam, valor,
                    geo_city, geo_region, geo_country, geo_isp,
                    utm_source, utm_medium, utm_campaign, utm_term, utm_content,
                    metadata, created_at
                ) VALUES (
                    ?, ?, ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, ?, ?, ?,
                    ?, ?, ?, ?, ?,
                    ?, NOW()
                )
            ");
            
            $stmt->execute([
                $siteId,
                $input['event_type'],
                $sessionId,
                $visitorId,
                $clientIp, // Usar IP real do cliente
                $userAgent,
                $input['referrer'] ?? $metadata['referrer'] ?? null,
                $input['page_url'] ?? $metadata['page'] ?? null,
                $placa,
                $renavam,
                $valor,
                $geo['city'],
                $geo['region'],
                $geo['country'],
                $geo['isp'],
                $utm['utm_source'] ?? null,
                $utm['utm_medium'] ?? null,
                $utm['utm_campaign'] ?? null,
                $utm['utm_term'] ?? null,
                $utm['utm_content'] ?? null,
                json_encode($metadata, JSON_UNESCAPED_UNICODE)
            ]);
            
            // Atualizar visitantes únicos - usar IP real do cliente
            $stmt = $pdo->prepare("
                INSERT INTO unique_visitors (site_id, visitor_id, visit_date, first_seen, last_seen, page_views, ip_address, geo_city, geo_region, user_agent)
                VALUES (?, ?, CURDATE(), NOW(), NOW(), 1, ?, ?, ?, ?)
                ON DUPLICATE KEY UPDATE 
                    last_seen = NOW(),
                    page_views = page_views + 1
            ");
            $stmt->execute([$siteId, $visitorId, $clientIp, $geo['city'], $geo['region'], $userAgent]);
            
            jsonResponse([
                'status' => 'success',
                'message' => 'Event tracked',
                'visitor_id' => $visitorId,
                'timestamp' => date('Y-m-d H:i:s')
            ]);
            
        } catch (Exception $e) {
            logAudit('track_error', $siteId, $e->getMessage(), $clientIp);
            jsonResponse(['status' => 'error', 'message' => 'Failed to track event', 'debug' => $e->getMessage()], 500);
        }
        break;

    // ------------------------------
    // PIX CONFIG - Obter configuração PIX
    // ------------------------------
    case 'pix-config':
        if ($method !== 'GET') {
            jsonResponse(['status' => 'error', 'message' => 'Method not allowed'], 405);
        }
        
        $pdo = getDBConnection();
        $stmt = $pdo->prepare("
            SELECT pix_key, receiver_name, receiver_city, pix_key_type
            FROM pix_config
            WHERE site_id = ? AND is_active = 1
            LIMIT 1
        ");
        $stmt->execute([$siteId]);
        $config = $stmt->fetch();
        
        if (!$config) {
            jsonResponse([
                'status' => 'success',
                'data' => [
                    'pixKey' => '',
                    'receiverName' => 'PAGAMENTO',
                    'receiverCity' => 'SAO PAULO'
                ]
            ]);
        }
        
        // Descriptografar chave PIX
        $pixKey = decryptData($config['pix_key']);
        
        jsonResponse([
            'status' => 'success',
            'data' => [
                'pixKey' => $pixKey,
                'receiverName' => $config['receiver_name'],
                'receiverCity' => $config['receiver_city'],
                'pixKeyType' => $config['pix_key_type']
            ]
        ]);
        break;

    // ------------------------------
    // STATS - Obter estatísticas
    // ------------------------------
    case 'stats':
        if ($method !== 'GET') {
            jsonResponse(['status' => 'error', 'message' => 'Method not allowed'], 405);
        }
        
        $pdo = getDBConnection();
        $today = date('Y-m-d');
        $yesterday = date('Y-m-d', strtotime('-1 day'));
        
        // Estatísticas gerais
        $stats = [];
        
        // Visitas
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ? AND event_type IN ('visit', 'page_view', 'page_load')");
        $stmt->execute([$siteId]);
        $totalVisits = $stmt->fetchColumn();
        
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ? AND event_type IN ('visit', 'page_view', 'page_load') AND DATE(created_at) = ?");
        $stmt->execute([$siteId, $today]);
        $visitsToday = $stmt->fetchColumn();
        
        // Visitantes únicos
        $stmt = $pdo->prepare("SELECT COUNT(DISTINCT visitor_id) FROM events WHERE site_id = ?");
        $stmt->execute([$siteId]);
        $uniqueVisitors = $stmt->fetchColumn();
        
        $stmt = $pdo->prepare("SELECT COUNT(DISTINCT visitor_id) FROM events WHERE site_id = ? AND DATE(created_at) = ?");
        $stmt->execute([$siteId, $today]);
        $uniqueToday = $stmt->fetchColumn();
        
        // Consultas
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ? AND event_type IN ('cnpj_consulta', 'consulta', 'consulta_iniciada', 'consulta_placa')");
        $stmt->execute([$siteId]);
        $totalConsultas = $stmt->fetchColumn();
        
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ? AND event_type IN ('cnpj_consulta', 'consulta', 'consulta_iniciada', 'consulta_placa') AND DATE(created_at) = ?");
        $stmt->execute([$siteId, $today]);
        $consultasToday = $stmt->fetchColumn();
        
        // PIX Gerados (apenas geração, não cópia)
        $pixTypes = "('pix_gerado', 'pix_generation_success', 'pix_generated', 'pix_iniciado')";
        $stmt = $pdo->prepare("SELECT COUNT(*), COALESCE(SUM(valor), 0) FROM events WHERE site_id = ? AND event_type IN {$pixTypes}");
        $stmt->execute([$siteId]);
        $pixData = $stmt->fetch(PDO::FETCH_NUM);
        $totalPix = $pixData[0];
        $valorTotalPix = $pixData[1];
        
        $stmt = $pdo->prepare("SELECT COUNT(*), COALESCE(SUM(valor), 0) FROM events WHERE site_id = ? AND event_type IN {$pixTypes} AND DATE(created_at) = ?");
        $stmt->execute([$siteId, $today]);
        $pixTodayData = $stmt->fetch(PDO::FETCH_NUM);
        $pixToday = $pixTodayData[0];
        $valorHojePix = $pixTodayData[1];
        
        // Códigos copiados
        $copiadosTypes = "('pix_codigo_copiado', 'pix_copied', 'pix_copia_cola')";
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ? AND event_type IN {$copiadosTypes}");
        $stmt->execute([$siteId]);
        $totalCopiados = $stmt->fetchColumn();
        
        $stmt = $pdo->prepare("SELECT COUNT(*) FROM events WHERE site_id = ? AND event_type IN {$copiadosTypes} AND DATE(created_at) = ?");
        $stmt->execute([$siteId, $today]);
        $copiadosHoje = $stmt->fetchColumn();
        
        // Últimos eventos
        $stmt = $pdo->prepare("
            SELECT event_type, placa, renavam, valor, ip_address, geo_city, geo_region, created_at, metadata
            FROM events
            WHERE site_id = ?
            ORDER BY created_at DESC
            LIMIT 50
        ");
        $stmt->execute([$siteId]);
        $recentEvents = $stmt->fetchAll();
        
        jsonResponse([
            'status' => 'success',
            'data' => [
                'stats' => [
                    'visits' => ['total' => (int)$totalVisits, 'today' => (int)$visitsToday],
                    'unique_visitors' => ['total' => (int)$uniqueVisitors, 'today' => (int)$uniqueToday],
                    'consultas' => ['total' => (int)$totalConsultas, 'today' => (int)$consultasToday],
                    'pix_gerados' => ['total' => (int)$totalPix, 'today' => (int)$pixToday],
                    'pix_copiados' => ['total' => (int)$totalCopiados, 'today' => (int)$copiadosHoje],
                    'valor_pix' => ['total' => round((float)$valorTotalPix, 2), 'today' => round((float)$valorHojePix, 2)]
                ],
                'events' => $recentEvents,
                'site' => [
                    'name' => $site['name'],
                    'domain' => $site['domain']
                ],
                'timestamp' => date('Y-m-d H:i:s'),
                'timezone' => 'America/Sao_Paulo'
            ]
        ]);
        break;

    // ------------------------------
    // PING - Health check
    // ------------------------------
    case 'ping':
        jsonResponse([
            'status' => 'success',
            'message' => 'pong',
            'site' => $site['name'],
            'timestamp' => date('Y-m-d H:i:s')
        ]);
        break;

    // ------------------------------
    // CLEAR CACHE - Limpar cache do site (forçar busca nova do PIX)
    // ------------------------------
    case 'clear-cache':
        // Este endpoint é chamado pelo admin quando atualiza o PIX
        // para notificar o site que deve limpar seu cache local
        jsonResponse([
            'status' => 'success',
            'message' => 'Cache cleared notification received',
            'site' => $site['name'],
            'timestamp' => date('Y-m-d H:i:s')
        ]);
        break;

    // ------------------------------
    // API TOKEN - Buscar token de autenticação do DETRAN/GOV
    // Usado pelo client-config.php como fallback
    // Retorna: { status, data: { token, base_url?, api_name? } }
    // ------------------------------
    case 'api-token':
        $pdo = getDBConnection();
        
        // Primeiro tentar pegar do api_tokens vinculado ao site
        $stmt = $pdo->prepare("
            SELECT at.token_value as token, at.base_url, at.name as api_name
            FROM sites s
            LEFT JOIN api_tokens at ON at.id = s.api_token_id AND at.is_active = 1
            WHERE s.id = ?
        ");
        $stmt->execute([$siteId]);
        $apiToken = $stmt->fetch();
        
        if ($apiToken && !empty($apiToken['token'])) {
            jsonResponse([
                'status' => 'success',
                'data' => [
                    'token' => $apiToken['token'],
                    'base_url' => $apiToken['base_url'] ?? '',
                    'api_name' => $apiToken['api_name'] ?? '',
                    'source' => 'api_tokens'
                ]
            ]);
        }
        
        // Fallback: buscar do site_security_config (gov_token)
        $stmt = $pdo->prepare("
            SELECT gov_token, gov_token_expires_at
            FROM site_security_config
            WHERE site_id = ?
        ");
        $stmt->execute([$siteId]);
        $secConfig = $stmt->fetch();
        
        if ($secConfig && !empty($secConfig['gov_token'])) {
            $token = decryptData($secConfig['gov_token']);
            if ($token) {
                jsonResponse([
                    'status' => 'success',
                    'data' => [
                        'token' => $token,
                        'expires_at' => $secConfig['gov_token_expires_at'],
                        'source' => 'site_security_config'
                    ]
                ]);
            }
        }
        
        // Fallback final: buscar do global_settings
        $stmt = $pdo->prepare("
            SELECT setting_value as token, is_encrypted
            FROM global_settings
            WHERE setting_key = 'detran_api_token'
        ");
        $stmt->execute();
        $result = $stmt->fetch();
        
        if ($result && !empty($result['token'])) {
            // Descriptografar se estiver criptografado
            $token = $result['is_encrypted'] ? decryptData($result['token']) : $result['token'];
            
            jsonResponse([
                'status' => 'success',
                'data' => [
                    'token' => $token,
                    'source' => 'global_settings'
                ]
            ]);
        }
        
        // Nenhum token encontrado
        jsonResponse([
            'status' => 'error',
            'message' => 'Token não configurado no servidor',
            'site_id' => $siteId
        ], 404);
        break;

    // ------------------------------
    // SITE-CONFIG - Configuração completa do site (para security-client.php)
    // ------------------------------
    case 'site-config':
        $pdo = getDBConnection();
        
        // Buscar API Token vinculada ao site
        $stmt = $pdo->prepare("
            SELECT at.token_value as api_token, at.base_url as api_base_url, at.name as api_name
            FROM sites s
            LEFT JOIN api_tokens at ON at.id = s.api_token_id AND at.is_active = 1
            WHERE s.id = ?
        ");
        $stmt->execute([$siteId]);
        $apiData = $stmt->fetch(PDO::FETCH_ASSOC);
        
        // Buscar configurações de segurança
        $stmt = $pdo->prepare("
            SELECT 
                rate_limit_enabled, rate_limit_requests, rate_limit_window, rate_limit_block_duration,
                antibot_enabled, antibot_check_useragent, antibot_check_referrer, 
                antibot_check_javascript, antibot_captcha_enabled,
                ddos_enabled, ddos_max_connections, ddos_suspicious_threshold, ddos_block_duration,
                gov_token, gov_token_expires_at,
                block_devtools, block_right_click, block_view_source, block_copy
            FROM site_security_config 
            WHERE site_id = ?
        ");
        $stmt->execute([$siteId]);
        $secConfig = $stmt->fetch(PDO::FETCH_ASSOC);
        
        // Se não existir, criar config padrão
        if (!$secConfig) {
            $stmt = $pdo->prepare("
                INSERT INTO site_security_config (site_id, rate_limit_enabled, antibot_enabled, ddos_enabled)
                VALUES (?, 0, 0, 0)
            ");
            $stmt->execute([$siteId]);
            
            $secConfig = [
                'rate_limit_enabled' => 0,
                'rate_limit_requests' => 100,
                'rate_limit_window' => 60,
                'rate_limit_block_duration' => 3600,
                'antibot_enabled' => 0,
                'antibot_check_useragent' => 1,
                'antibot_check_referrer' => 0,
                'antibot_check_javascript' => 1,
                'antibot_captcha_enabled' => 0,
                'ddos_enabled' => 0,
                'ddos_max_connections' => 50,
                'ddos_suspicious_threshold' => 10,
                'ddos_block_duration' => 7200,
                'gov_token' => null,
                'gov_token_expires_at' => null,
                'block_devtools' => 0,
                'block_right_click' => 0,
                'block_view_source' => 0,
                'block_copy' => 0
            ];
        }
        
        // Prioridade do token: API Token vinculada > gov_token no config
        $govToken = null;
        if (!empty($apiData['api_token'])) {
            $govToken = $apiData['api_token'];
        } elseif (!empty($secConfig['gov_token'])) {
            $govToken = decryptData($secConfig['gov_token']);
        }
        
        $secConfig['gov_token'] = $govToken;
        $secConfig['gov_api_name'] = $apiData['api_name'] ?? null;
        $secConfig['gov_base_url'] = $apiData['api_base_url'] ?? null;
        
        // Buscar IPs bloqueados
        $stmt = $pdo->prepare("
            SELECT ip_address FROM site_ip_rules 
            WHERE site_id = ? AND (rule_type = 'blacklist' OR (rule_type = 'temp_block' AND blocked_until > NOW()))
        ");
        $stmt->execute([$siteId]);
        $blockedIps = $stmt->fetchAll(PDO::FETCH_COLUMN);
        
        // Buscar IPs whitelist
        $stmt = $pdo->prepare("SELECT ip_address FROM site_ip_rules WHERE site_id = ? AND rule_type = 'whitelist'");
        $stmt->execute([$siteId]);
        $whitelistedIps = $stmt->fetchAll(PDO::FETCH_COLUMN);
        
        // Buscar configuração PIX
        $stmt = $pdo->prepare("SELECT pix_key, pix_key_type, receiver_name, receiver_city FROM pix_config WHERE site_id = ?");
        $stmt->execute([$siteId]);
        $pixConfig = $stmt->fetch(PDO::FETCH_ASSOC);
        
        if ($pixConfig && !empty($pixConfig['pix_key'])) {
            $pixConfig['pix_key'] = decryptData($pixConfig['pix_key']);
        }
        
        jsonResponse([
            'status' => 'success',
            'data' => [
                'site' => [
                    'id' => $siteId,
                    'name' => $site['name'],
                    'domain' => $site['domain']
                ],
                'security' => $secConfig,
                'blocked_ips' => $blockedIps ?: [],
                'whitelisted_ips' => $whitelistedIps ?: [],
                'pix' => $pixConfig ?: false
            ]
        ]);
        break;

    // ------------------------------
    // SECURITY-REPORT - Receber eventos de segurança dos sites
    // ------------------------------
    case 'security-report':
        if ($method !== 'POST') {
            jsonResponse(['status' => 'error', 'message' => 'Method not allowed'], 405);
        }
        
        $input = json_decode(file_get_contents('php://input'), true);
        if (!$input) {
            jsonResponse(['status' => 'error', 'message' => 'Invalid input'], 400);
        }
        
        $pdo = getDBConnection();
        
        try {
            // Registrar evento no audit_logs
            $stmt = $pdo->prepare("
                INSERT INTO audit_logs (user_id, action, target_type, target_id, details, ip_address, created_at)
                VALUES (NULL, ?, 'site', ?, ?, ?, NOW())
            ");
            $stmt->execute([
                'security_' . ($input['event_type'] ?? 'unknown'),
                $siteId,
                json_encode($input['details'] ?? []),
                $input['ip_address'] ?? $ip
            ]);
            
            jsonResponse([
                'status' => 'success',
                'message' => 'Event reported'
            ]);
        } catch (Exception $e) {
            jsonResponse(['status' => 'error', 'message' => 'Failed to report event'], 500);
        }
        break;

    default:
        jsonResponse(['status' => 'error', 'message' => 'Unknown action'], 404);
}
