<?php
/**
 * ============================================
 * APROVAÇÃO AUTOMÁTICA DE COMPROVANTES PIX
 * Usando API OCR.space (gratuita - 25.000/mês)
 * ============================================
 */

date_default_timezone_set('America/Sao_Paulo');

// ========== CONFIGURAÇÕES ==========
// Pegue sua API key gratuita em: https://ocr.space/ocrapi/freekey
define('OCR_API_KEY', 'K82516147688957'); // Sua API key
define('OCR_API_URL', 'https://api.ocr.space/parse/image');

define('COMPROVANTES_DIR', __DIR__ . '/../comprovantes/');
define('LOG_FILE', __DIR__ . '/../logs/auto-approve.log');
define('SCORE_MINIMO', 70);
define('VALOR_TOLERANCIA', 0.50); // 50 centavos de tolerância

/**
 * Log
 */
function logMsg($msg) {
    $logDir = dirname(LOG_FILE);
    if (!is_dir($logDir)) @mkdir($logDir, 0755, true);
    $timestamp = date('Y-m-d H:i:s');
    @file_put_contents(LOG_FILE, "[$timestamp] $msg\n", FILE_APPEND);
    if (php_sapi_name() === 'cli') {
        echo "[$timestamp] $msg\n";
    }
}

/**
 * Resposta JSON
 */
function response($data, $code = 200) {
    http_response_code($code);
    echo json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
    exit;
}

/**
 * Extrai texto usando API OCR.space
 */
function extrairTextoOCR($imagePath) {
    if (!file_exists($imagePath)) {
        logMsg("Arquivo não existe: $imagePath");
        return '';
    }
    
    $fileSize = filesize($imagePath);
    if ($fileSize > 1024 * 1024) { // > 1MB
        logMsg("Arquivo grande ($fileSize bytes), pode demorar...");
    }
    
    // Prepara o arquivo
    $ext = strtolower(pathinfo($imagePath, PATHINFO_EXTENSION));
    $mimeTypes = [
        'jpg' => 'image/jpeg',
        'jpeg' => 'image/jpeg',
        'png' => 'image/png',
        'gif' => 'image/gif',
        'webp' => 'image/webp',
        'pdf' => 'application/pdf'
    ];
    $mimeType = $mimeTypes[$ext] ?? 'image/jpeg';
    
    // Envia para API
    $curl = curl_init();
    
    $postFields = [
        'apikey' => OCR_API_KEY,
        'language' => 'por',
        'isOverlayRequired' => 'false',
        'detectOrientation' => 'true',
        'scale' => 'true',
        'OCREngine' => '2', // Engine 2 é melhor para textos
        'file' => new CURLFile($imagePath, $mimeType, basename($imagePath))
    ];
    
    curl_setopt_array($curl, [
        CURLOPT_URL => OCR_API_URL,
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_POST => true,
        CURLOPT_POSTFIELDS => $postFields,
        CURLOPT_TIMEOUT => 60,
        CURLOPT_SSL_VERIFYPEER => false
    ]);
    
    $response = curl_exec($curl);
    $httpCode = curl_getinfo($curl, CURLINFO_HTTP_CODE);
    $error = curl_error($curl);
    curl_close($curl);
    
    if ($error) {
        logMsg("Erro CURL: $error");
        return '';
    }
    
    if ($httpCode !== 200) {
        logMsg("Erro HTTP: $httpCode");
        return '';
    }
    
    $result = json_decode($response, true);
    
    if (!$result) {
        logMsg("Resposta inválida da API");
        return '';
    }
    
    if (isset($result['ErrorMessage']) && !empty($result['ErrorMessage'])) {
        logMsg("Erro API: " . implode(', ', $result['ErrorMessage']));
        return '';
    }
    
    if (isset($result['ParsedResults'][0]['ParsedText'])) {
        $texto = $result['ParsedResults'][0]['ParsedText'];
        logMsg("OCR extraiu " . strlen($texto) . " caracteres");
        return $texto;
    }
    
    logMsg("Nenhum texto extraído");
    return '';
}

/**
 * Extrai dados do comprovante
 */
function extrairDados($texto) {
    $dados = [
        'valor' => null,
        'cpf' => null,
        'nome' => null,
        'data' => null,
        'hora' => null,
        'id_transacao' => null,
        'banco' => null
    ];
    
    // Normaliza
    $texto = mb_strtoupper($texto, 'UTF-8');
    $textoLimpo = preg_replace('/\s+/', ' ', $texto);
    
    logMsg("Texto para análise: " . substr($textoLimpo, 0, 300) . "...");
    
    // ========== VALOR ==========
    // R$ 179,40 | R$179.40 | 179,40 | VALOR R$ 179,40
    $padroesValor = [
        '/R\$\s*(\d{1,3}(?:\.\d{3})*[,]\d{2})/',  // R$ 1.234,56
        '/R\$\s*(\d{1,3}[,]\d{2})/',               // R$ 123,45
        '/VALOR[:\s]*R?\$?\s*(\d{1,3}(?:\.\d{3})*[,]\d{2})/i',
        '/QUANTIA[:\s]*R?\$?\s*(\d{1,3}[,]\d{2})/i',
        '/(\d{1,3})[,](\d{2})(?=\s|$|[^0-9])/'    // 179,40 solto
    ];
    
    foreach ($padroesValor as $padrao) {
        if (preg_match($padrao, $textoLimpo, $m)) {
            $valorStr = $m[1] ?? ($m[1] . ',' . $m[2]);
            $valorStr = str_replace('.', '', $valorStr);
            $valorStr = str_replace(',', '.', $valorStr);
            $valor = floatval($valorStr);
            if ($valor > 0 && $valor < 100000) {
                $dados['valor'] = $valor;
                logMsg("Valor encontrado: R$ " . number_format($valor, 2, ',', '.'));
                break;
            }
        }
    }
    
    // ========== CPF ==========
    // 369.046.348-39 | 36904634839
    if (preg_match('/(\d{3})[\.\s]?(\d{3})[\.\s]?(\d{3})[\-\.\s]?(\d{2})/', $textoLimpo, $m)) {
        $cpf = $m[1] . $m[2] . $m[3] . $m[4];
        if (strlen($cpf) === 11) {
            $dados['cpf'] = $cpf;
            logMsg("CPF encontrado: " . substr($cpf, 0, 3) . ".***.***-" . substr($cpf, -2));
        }
    }
    
    // ========== NOME ==========
    $padroesNome = [
        '/(?:PAGADOR|ORIGEM|REMETENTE|DE|NOME)[:\s]+([A-ZÁÀÂÃÉÈÊÍÌÎÓÒÔÕÚÙÛÇ][A-ZÁÀÂÃÉÈÊÍÌÎÓÒÔÕÚÙÛÇ\s]{2,40})(?=\s{2}|CPF|CNPJ|\d|$)/i',
        '/(?:TRANSFERIU|ENVIOU|PAGOU)[:\s]+([A-ZÁÀÂÃÉÈÊÍÌÎÓÒÔÕÚÙÛÇ][A-ZÁÀÂÃÉÈÊÍÌÎÓÒÔÕÚÙÛÇ\s]{2,40})/i'
    ];
    
    foreach ($padroesNome as $padrao) {
        if (preg_match($padrao, $textoLimpo, $m)) {
            $nome = trim($m[1]);
            // Ignora textos que não são nomes
            $ignorar = ['PIX', 'BANCO', 'COMPROVANTE', 'TRANSFERENCIA', 'PAGAMENTO', 'VALOR', 'DATA'];
            $ehNome = true;
            foreach ($ignorar as $ig) {
                if (stripos($nome, $ig) !== false) {
                    $ehNome = false;
                    break;
                }
            }
            if ($ehNome && strlen($nome) >= 3) {
                $dados['nome'] = $nome;
                logMsg("Nome encontrado: $nome");
                break;
            }
        }
    }
    
    // ========== DATA ==========
    if (preg_match('/(\d{2})[\/\-](\d{2})[\/\-](\d{4})/', $textoLimpo, $m)) {
        $dados['data'] = $m[3] . '-' . $m[2] . '-' . $m[1];
        logMsg("Data encontrada: {$dados['data']}");
    }
    
    // ========== HORA ==========
    if (preg_match('/(\d{2}):(\d{2})(?::(\d{2}))?/', $textoLimpo, $m)) {
        $dados['hora'] = $m[1] . ':' . $m[2];
        logMsg("Hora encontrada: {$dados['hora']}");
    }
    
    // ========== ID TRANSAÇÃO ==========
    // UUID ou E+números
    if (preg_match('/([A-F0-9]{8}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{4}-[A-F0-9]{12})/i', $textoLimpo, $m)) {
        $dados['id_transacao'] = strtolower($m[1]);
        logMsg("ID transação (UUID): {$dados['id_transacao']}");
    } elseif (preg_match('/(E\d{20,32})/i', $textoLimpo, $m)) {
        $dados['id_transacao'] = $m[1];
        logMsg("ID transação (E2E): {$dados['id_transacao']}");
    }
    
    // ========== BANCO ==========
    $bancos = [
        'NUBANK' => 'NUBANK',
        'NU PAGAMENTOS' => 'NUBANK',
        'INTER' => 'INTER',
        'BANCO INTER' => 'INTER',
        'ITAU' => 'ITAÚ',
        'ITAÚ' => 'ITAÚ',
        'BRADESCO' => 'BRADESCO',
        'SANTANDER' => 'SANTANDER',
        'CAIXA' => 'CAIXA',
        'CEF' => 'CAIXA',
        'BANCO DO BRASIL' => 'BB',
        'PICPAY' => 'PICPAY',
        'MERCADO PAGO' => 'MERCADO PAGO',
        'MERCADOPAGO' => 'MERCADO PAGO',
        'PAGSEGURO' => 'PAGSEGURO',
        'C6 BANK' => 'C6',
        'C6' => 'C6',
        'NEXT' => 'NEXT',
        'NEON' => 'NEON',
        'ORIGINAL' => 'ORIGINAL',
        'SICOOB' => 'SICOOB',
        'SICREDI' => 'SICREDI'
    ];
    
    foreach ($bancos as $busca => $nome) {
        if (stripos($textoLimpo, $busca) !== false) {
            $dados['banco'] = $nome;
            logMsg("Banco encontrado: $nome");
            break;
        }
    }
    
    return $dados;
}

/**
 * Calcula score de compatibilidade
 */
function calcularScore($dadosOCR, $cliente) {
    $score = 0;
    $detalhes = [];
    
    $valorCliente = floatval($cliente['valor'] ?? 0);
    $cpfCliente = preg_replace('/\D/', '', $cliente['cpf'] ?? '');
    $nomeCliente = mb_strtoupper(trim($cliente['nome'] ?? ''), 'UTF-8');
    
    // ========== VALOR (40 pontos) ==========
    if ($dadosOCR['valor'] && $valorCliente > 0) {
        $diff = abs($dadosOCR['valor'] - $valorCliente);
        
        if ($diff <= VALOR_TOLERANCIA) {
            $score += 40;
            $detalhes[] = "✅ Valor EXATO: R$ " . number_format($valorCliente, 2, ',', '.');
        } elseif ($diff <= 2.00) {
            $score += 25;
            $detalhes[] = "⚠️ Valor próximo (diff: R$ " . number_format($diff, 2, ',', '.') . ")";
        } elseif ($diff <= 10.00) {
            $score += 10;
            $detalhes[] = "⚠️ Valor similar (diff: R$ " . number_format($diff, 2, ',', '.') . ")";
        } else {
            $detalhes[] = "❌ Valor diferente: R$ " . number_format($dadosOCR['valor'], 2, ',', '.') . " vs R$ " . number_format($valorCliente, 2, ',', '.');
        }
    } else {
        $detalhes[] = "⚠️ Valor não identificado no comprovante";
    }
    
    // ========== CPF (30 pontos) ==========
    if ($dadosOCR['cpf'] && $cpfCliente) {
        if ($dadosOCR['cpf'] === $cpfCliente) {
            $score += 30;
            $detalhes[] = "✅ CPF conferido";
        } elseif (substr($dadosOCR['cpf'], 0, 6) === substr($cpfCliente, 0, 6)) {
            $score += 15;
            $detalhes[] = "⚠️ CPF parcialmente igual";
        } else {
            $detalhes[] = "❌ CPF diferente";
        }
    } else {
        $detalhes[] = "⚠️ CPF não identificado no comprovante";
    }
    
    // ========== NOME (20 pontos) ==========
    if ($dadosOCR['nome'] && $nomeCliente) {
        $nomeOCR = mb_strtoupper(trim($dadosOCR['nome']), 'UTF-8');
        
        if ($nomeOCR === $nomeCliente) {
            $score += 20;
            $detalhes[] = "✅ Nome conferido";
        } else {
            // Compara primeiro nome
            $primeiroOCR = explode(' ', $nomeOCR)[0];
            $primeiroCliente = explode(' ', $nomeCliente)[0];
            
            if ($primeiroOCR === $primeiroCliente && strlen($primeiroOCR) >= 3) {
                $score += 15;
                $detalhes[] = "✅ Primeiro nome confere: $primeiroOCR";
            } else {
                // Similaridade
                similar_text($nomeOCR, $nomeCliente, $percent);
                if ($percent >= 70) {
                    $score += 10;
                    $detalhes[] = "⚠️ Nome similar (" . round($percent) . "%)";
                } else {
                    $detalhes[] = "❌ Nome diferente: $nomeOCR";
                }
            }
        }
    } else {
        $detalhes[] = "⚠️ Nome não identificado no comprovante";
    }
    
    // ========== DATA (10 pontos) ==========
    if ($dadosOCR['data']) {
        $dataOCR = strtotime($dadosOCR['data']);
        $hoje = strtotime('today');
        $diffDias = abs($dataOCR - $hoje) / 86400;
        
        if ($diffDias <= 3) {
            $score += 10;
            $detalhes[] = "✅ Data recente: {$dadosOCR['data']}";
        } elseif ($diffDias <= 7) {
            $score += 5;
            $detalhes[] = "⚠️ Data de " . round($diffDias) . " dias atrás";
        } else {
            $detalhes[] = "❌ Data antiga: {$dadosOCR['data']}";
        }
    }
    
    // ========== BÔNUS ==========
    // Se valor E (cpf OU nome) conferem
    $temValor = $dadosOCR['valor'] && abs($dadosOCR['valor'] - $valorCliente) <= VALOR_TOLERANCIA;
    $temCpfOuNome = ($dadosOCR['cpf'] === $cpfCliente) || 
                    (mb_strtoupper($dadosOCR['nome'] ?? '') === $nomeCliente);
    
    if ($temValor && $temCpfOuNome) {
        $score += 10;
        $detalhes[] = "🎯 Bônus: múltiplos dados conferem";
    }
    
    return [
        'score' => $score,
        'detalhes' => $detalhes,
        'aprovado' => $score >= SCORE_MINIMO,
        'dados_ocr' => $dadosOCR
    ];
}

/**
 * Aprova comprovante
 */
function aprovarComprovante($pendente, $scoreInfo) {
    $pendentesFile = COMPROVANTES_DIR . 'pendentes.json';
    $aprovadosFile = COMPROVANTES_DIR . 'aprovados.json';
    
    // Carrega arquivos
    $pendentes = file_exists($pendentesFile) ? json_decode(file_get_contents($pendentesFile), true) : [];
    $aprovados = file_exists($aprovadosFile) ? json_decode(file_get_contents($aprovadosFile), true) : [];
    
    // Remove dos pendentes
    $pendentes = array_values(array_filter($pendentes, function($p) use ($pendente) {
        return ($p['id'] ?? '') !== ($pendente['id'] ?? '') &&
               ($p['pix_id'] ?? '') !== ($pendente['pix_id'] ?? '');
    }));
    
    // Adiciona aos aprovados
    $pendente['status'] = 'aprovado';
    $pendente['aprovado_em'] = date('Y-m-d H:i:s');
    $pendente['aprovado_por'] = 'AUTO_OCR';
    $pendente['auto_approve'] = $scoreInfo;
    
    $aprovados[] = $pendente;
    
    // Salva
    file_put_contents($pendentesFile, json_encode($pendentes, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    file_put_contents($aprovadosFile, json_encode($aprovados, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    
    logMsg("✅ APROVADO: {$pendente['arquivo']} | Score: {$scoreInfo['score']} | Cliente: " . ($pendente['cliente']['nome'] ?? 'N/A'));
    
    return true;
}

/**
 * Remove pendente com arquivo inexistente
 */
function removerPendenteInvalido($pendente) {
    $pendentesFile = COMPROVANTES_DIR . 'pendentes.json';
    $pendentes = file_exists($pendentesFile) ? json_decode(file_get_contents($pendentesFile), true) : [];
    
    $pendentes = array_values(array_filter($pendentes, function($p) use ($pendente) {
        return ($p['id'] ?? '') !== ($pendente['id'] ?? '');
    }));
    
    file_put_contents($pendentesFile, json_encode($pendentes, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE));
    logMsg("🗑️ Removido pendente com arquivo inexistente: {$pendente['arquivo']}");
}

/**
 * Processa todos os pendentes
 */
function processarPendentes() {
    $pendentesFile = COMPROVANTES_DIR . 'pendentes.json';
    
    if (!file_exists($pendentesFile)) {
        logMsg("Nenhum arquivo pendentes.json");
        return ['processados' => 0, 'aprovados' => 0, 'removidos' => 0];
    }
    
    $pendentes = json_decode(file_get_contents($pendentesFile), true) ?: [];
    
    if (empty($pendentes)) {
        logMsg("Nenhum comprovante pendente");
        return ['processados' => 0, 'aprovados' => 0, 'removidos' => 0];
    }
    
    logMsg("=== Iniciando processamento de " . count($pendentes) . " comprovantes ===");
    
    $processados = 0;
    $aprovados = 0;
    $removidos = 0;
    
    foreach ($pendentes as $pendente) {
        $arquivo = COMPROVANTES_DIR . ($pendente['arquivo'] ?? '');
        
        // Verifica se arquivo existe
        if (!file_exists($arquivo)) {
            removerPendenteInvalido($pendente);
            $removidos++;
            continue;
        }
        
        $processados++;
        logMsg("--- Processando: {$pendente['arquivo']} ---");
        
        // Extrai texto via OCR
        $texto = extrairTextoOCR($arquivo);
        
        if (empty($texto)) {
            logMsg("⚠️ Não foi possível extrair texto de: {$pendente['arquivo']}");
            continue;
        }
        
        // Extrai dados
        $dadosOCR = extrairDados($texto);
        
        // Calcula score
        $scoreInfo = calcularScore($dadosOCR, $pendente['cliente'] ?? []);
        
        logMsg("Score: {$scoreInfo['score']} | " . implode(' | ', $scoreInfo['detalhes']));
        
        if ($scoreInfo['aprovado']) {
            aprovarComprovante($pendente, $scoreInfo);
            $aprovados++;
        } else {
            logMsg("❌ Score insuficiente ({$scoreInfo['score']} < " . SCORE_MINIMO . ")");
        }
        
        // Pausa para não exceder limite da API (1 req/seg na versão gratuita)
        sleep(1);
    }
    
    logMsg("=== Finalizado: $processados processados, $aprovados aprovados, $removidos removidos ===");
    
    return [
        'processados' => $processados,
        'aprovados' => $aprovados,
        'removidos' => $removidos
    ];
}

// ========== API / CLI ==========
if (php_sapi_name() !== 'cli') {
    header('Content-Type: application/json');
    header('Access-Control-Allow-Origin: *');
    
    $action = $_GET['action'] ?? $_POST['action'] ?? 'process';
    
    switch ($action) {
        case 'process':
            $resultado = processarPendentes();
            response(['success' => true, 'resultado' => $resultado]);
            break;
            
        case 'status':
            $pendentesFile = COMPROVANTES_DIR . 'pendentes.json';
            $aprovadosFile = COMPROVANTES_DIR . 'aprovados.json';
            
            $pendentes = file_exists($pendentesFile) ? json_decode(file_get_contents($pendentesFile), true) : [];
            $aprovados = file_exists($aprovadosFile) ? json_decode(file_get_contents($aprovadosFile), true) : [];
            
            response([
                'success' => true,
                'pendentes' => count($pendentes),
                'aprovados' => count($aprovados),
                'api_key_configurada' => !empty(OCR_API_KEY),
                'score_minimo' => SCORE_MINIMO
            ]);
            break;
            
        case 'test':
            // Testa OCR com um arquivo específico
            $arquivo = $_GET['arquivo'] ?? '';
            if (empty($arquivo)) {
                response(['error' => 'Parâmetro arquivo obrigatório'], 400);
            }
            
            $path = COMPROVANTES_DIR . basename($arquivo);
            if (!file_exists($path)) {
                response(['error' => 'Arquivo não encontrado'], 404);
            }
            
            $texto = extrairTextoOCR($path);
            $dados = extrairDados($texto);
            
            response([
                'success' => true,
                'texto_extraido' => substr($texto, 0, 1000),
                'dados' => $dados
            ]);
            break;
            
        default:
            response(['error' => 'Ação inválida'], 400);
    }
    exit;
}

// ========== CLI ==========
echo "===========================================\n";
echo "  APROVAÇÃO AUTOMÁTICA DE COMPROVANTES\n";
echo "  Usando API OCR.space\n";
echo "===========================================\n\n";

echo "API Key: " . (OCR_API_KEY ? "✅ Configurada" : "❌ Não configurada") . "\n";
echo "Score mínimo: " . SCORE_MINIMO . " pontos\n";
echo "Diretório: " . COMPROVANTES_DIR . "\n\n";

$resultado = processarPendentes();

echo "\n===========================================\n";
echo "RESULTADO:\n";
echo "  Processados: {$resultado['processados']}\n";
echo "  Aprovados: {$resultado['aprovados']}\n";
echo "  Removidos: {$resultado['removidos']}\n";
echo "===========================================\n";