<?php
/**
 * Backend Cartão de Crédito - Versão Simples Atualizada para SDK v3.5+
 * Mantém a lógica original, apenas atualiza para nova versão do SDK
 */

// Autoload do Composer
require __DIR__ . '/../vendor/autoload.php'; 

// Conexão com o banco de dados
require __DIR__ . '/../config/config_db.php'; 

// Importa o arquivo com o access token
require __DIR__ . '/../config/token.php'; 

// Imports do SDK v3.5+
use MercadoPago\Client\Payment\PaymentClient;
use MercadoPago\Client\Common\RequestOptions;
use MercadoPago\MercadoPagoConfig;
use MercadoPago\Exceptions\MPApiException;

// Tratamento global de erros
set_error_handler(function($errno, $errstr, $errfile, $errline) {
    error_log("Erro em process_payment.php: [$errno] $errstr em $errfile:$errline");
    return false;
});

// Defina o cabeçalho da resposta como JSON
header('Content-Type: application/json; charset=utf-8');

// Garantir que sempre retorne JSON, mesmo em caso de erro fatal
register_shutdown_function(function() {
    $error = error_get_last();
    if ($error !== NULL && in_array($error['type'], [E_ERROR, E_PARSE, E_CORE_ERROR, E_COMPILE_ERROR])) {
        http_response_code(500);
        echo json_encode([
            'status' => 'error',
            'message' => 'Erro interno do servidor. Por favor, tente novamente.'
        ]);
    }
});

// Configurar o token de acesso do Mercado Pago (Nova forma v3)
try {
    MercadoPagoConfig::setAccessToken(ACCESS_TOKEN);
    MercadoPagoConfig::setRuntimeEnviroment(MercadoPagoConfig::LOCAL);
} catch (Exception $e) {
    echo json_encode(['status' => 'error', 'message' => 'Erro na configuração do SDK: ' . $e->getMessage()]);
    exit;
}

function getFriendlyErrorMessage($error_code) {
    $error_messages = [
        "cc_rejected_insufficient_amount" => "Seu cartão não possui saldo suficiente.",
        "cc_rejected_bad_filled_security_code" => "O código de segurança foi preenchido incorretamente.",
        "cc_rejected_blacklist" => "O pagamento foi rejeitado. Entre em contato com seu banco.",
        "cc_rejected_bad_filled_date" => "A data de vencimento foi preenchida incorretamente.",
        "cc_rejected_bad_filled_other" => "Houve um erro ao processar o pagamento. Verifique os dados e tente novamente.",
        "cc_rejected_card_disabled" => "Seu cartão está desativado. Entre em contato com seu banco.",
        "cc_rejected_duplicated_payment" => "Você já fez um pagamento para este valor.",
        "cc_rejected_high_risk" => "O pagamento foi recusado por razões de segurança.",
        "cc_rejected_invalid_installments" => "O número de parcelas selecionado não é válido.",
        "cc_rejected_max_attempts" => "Você atingiu o número máximo de tentativas com esse cartão.",
        "cc_rejected_other_reason" => "Seu cartão não pôde ser processado. Tente outro cartão ou forma de pagamento."
    ];

    return $error_messages[$error_code] ?? "O pagamento foi recusado. Verifique os detalhes do cartão ou tente outra forma de pagamento.";
}

try {
    // Recebe os dados enviados pelo front-end (JSON)
    $raw_input = file_get_contents('php://input');
    $data = json_decode($raw_input, true);
    
    // ============================================================
    // DEBUG TEMPORÁRIO: Log do payload recebido do frontend
    // ============================================================
    $debug_log = "=== DEBUG ADDRESS PAYLOAD - " . date('Y-m-d H:i:s') . " ===\n";
    $debug_log .= "RAW INPUT (primeiros 1000 chars): " . substr($raw_input, 0, 1000) . "\n\n";
    $debug_log .= "DECODED DATA:\n";
    $debug_log .= print_r($data, true) . "\n";
    $debug_log .= "\nPOST DATA:\n";
    $debug_log .= print_r($_POST, true) . "\n";
    $debug_log .= "\n==========================================\n\n";
    file_put_contents(__DIR__ . '/debug_address_payload.txt', $debug_log, FILE_APPEND);
    // ============================================================
    
    // LOG PARA DEBUG: Registrar dados recebidos
    error_log("=== PROCESS_PAYMENT DEBUG ===");
    error_log("Raw input: " . substr($raw_input, 0, 500));
    error_log("Decoded data keys: " . implode(', ', array_keys($data ?: [])));
    error_log("Transaction amount: " . ($data['transaction_amount'] ?? 'NULL'));
    error_log("Description: " . ($data['description'] ?? 'NULL'));
    error_log("Product ID: " . ($data['product']['id'] ?? 'NULL'));
    error_log("Token: " . (isset($data['token']) ? 'PRESENT' : 'MISSING'));
    error_log("Installments: " . ($data['installments'] ?? 'NULL'));
    error_log("Payment Method ID: " . ($data['payment_method_id'] ?? 'NULL'));
    error_log("Payer Email: " . ($data['payer']['email'] ?? 'NULL'));

    if (!isset($data['token'])) {
        throw new Exception('Token não foi gerado no front-end.');
    }
    
    // Validação de campos obrigatórios
    if (!isset($data['transaction_amount']) || empty($data['transaction_amount'])) {
        error_log("ERRO: transaction_amount não fornecido ou vazio");
        throw new Exception('Valor da transação não fornecido.');
    }
    
    if (!isset($data['description']) || empty($data['description'])) {
        error_log("ERRO: description não fornecido ou vazio");
        throw new Exception('Descrição da transação não fornecida.');
    }
    
    // Validação de campos obrigatórios do Mercado Pago
    if (!isset($data['payment_method_id']) || empty($data['payment_method_id'])) {
        error_log("ERRO: payment_method_id não fornecido ou vazio");
        throw new Exception('Método de pagamento não foi identificado. Recarregue a página e tente novamente.');
    }
    
    if (!isset($data['installments']) || empty($data['installments']) || !is_numeric($data['installments'])) {
        error_log("ERRO: installments não fornecido, vazio ou inválido: " . ($data['installments'] ?? 'NULL'));
        throw new Exception('Número de parcelas não foi selecionado. Selecione uma opção de parcelamento.');
    }
    
    // Validar estrutura do payer
    if (!isset($data['payer']) || !is_array($data['payer'])) {
        error_log("ERRO: payer não fornecido ou não é array");
        throw new Exception('Dados do pagador não foram fornecidos.');
    }
    
    if (!isset($data['payer']['email']) || empty($data['payer']['email'])) {
        error_log("ERRO: payer.email não fornecido ou vazio");
        throw new Exception('Email do pagador é obrigatório.');
    }
    
    // ============================================================
    // ETAPA 1: PREPARAÇÃO DE VARIÁVEIS SEGURAS (GLOBAL SETUP)
    // Todas as variáveis são definidas aqui com fallbacks seguros
    // ============================================================
    
    // Criar referência externa única
    $external_reference = uniqid('txn_', true);
    
    // 1.1. NOME E SOBRENOME (múltiplas fontes com fallback)
    $safeName = 'Consumidor';
    $safeLastName = '';
    
    // Prioridade 1: cardholderName
    if (isset($data['cardholderName']) && !empty(trim($data['cardholderName']))) {
        $name_parts = explode(' ', trim($data['cardholderName']), 2);
        $safeName = $name_parts[0] ?? 'Consumidor';
        $safeLastName = $name_parts[1] ?? '';
    }
    // Prioridade 2: payer.full_name
    elseif (isset($data['payer']['full_name']) && !empty(trim($data['payer']['full_name']))) {
        $name_parts = explode(' ', trim($data['payer']['full_name']), 2);
        $safeName = $name_parts[0] ?? 'Consumidor';
        $safeLastName = $name_parts[1] ?? '';
    }
    // Prioridade 3: payer.first_name + last_name
    elseif (isset($data['payer']['first_name']) && !empty(trim($data['payer']['first_name']))) {
        $safeName = trim($data['payer']['first_name']);
        $safeLastName = isset($data['payer']['last_name']) ? trim($data['payer']['last_name']) : '';
    }
    
    // 1.2. EMAIL (já validado acima, mas garantir fallback)
    $safeEmail = isset($data['payer']['email']) && !empty($data['payer']['email']) 
        ? trim($data['payer']['email']) 
        : 'consumidor@email.com';
    
    // 1.3. TELEFONE E DDD (múltiplas fontes com fallback)
    $safeAreaCode = '11'; // Fallback: São Paulo
    $safePhoneNumber = '000000000'; // Fallback seguro
    
    // Prioridade 1: payer.phone já separado
    if (isset($data['payer']['phone']['area_code']) && !empty($data['payer']['phone']['area_code'])) {
        $safeAreaCode = substr(preg_replace('/\D/', '', $data['payer']['phone']['area_code']), 0, 2);
    }
    if (isset($data['payer']['phone']['number']) && !empty($data['payer']['phone']['number'])) {
        $safePhoneNumber = preg_replace('/\D/', '', $data['payer']['phone']['number']);
        if (strlen($safePhoneNumber) > 9) {
            $safePhoneNumber = substr($safePhoneNumber, -9);
        }
    }
    // Prioridade 2: payer.phone como string completa
    elseif (isset($data['payer']['phone']) && is_string($data['payer']['phone'])) {
        $phone_clean = preg_replace('/\D/', '', $data['payer']['phone']);
        if (strlen($phone_clean) >= 10) {
            $safeAreaCode = substr($phone_clean, 0, 2);
            $safePhoneNumber = substr($phone_clean, 2);
        } elseif (strlen($phone_clean) >= 8) {
            $safePhoneNumber = substr($phone_clean, -9);
        }
    }
    // Prioridade 3: phone direto no $data
    elseif (isset($data['phone']) && !empty($data['phone'])) {
        $phone_clean = preg_replace('/\D/', '', $data['phone']);
        if (strlen($phone_clean) >= 10) {
            $safeAreaCode = substr($phone_clean, 0, 2);
            $safePhoneNumber = substr($phone_clean, 2);
        }
    }
    
    // Telefone completo para o banco (formato string)
    $safePhoneFull = trim($safeAreaCode . ' ' . $safePhoneNumber);
    if (empty($safePhoneFull)) {
        $safePhoneFull = '00000000000';
    }
    
    // 1.4. DOCUMENTO (CPF/CNPJ)
    $safeDocType = 'CPF';
    $safeDocNumber = '';
    
    if (isset($data['payer']['identification']['type']) && !empty($data['payer']['identification']['type'])) {
        $safeDocType = strtoupper(trim($data['payer']['identification']['type']));
    }
    if (isset($data['payer']['identification']['number']) && !empty($data['payer']['identification']['number'])) {
        $safeDocNumber = preg_replace('/\D/', '', $data['payer']['identification']['number']);
    }
    elseif (isset($data['cpf']) && !empty($data['cpf'])) {
        $safeDocNumber = preg_replace('/\D/', '', $data['cpf']);
    }
    elseif (isset($data['payer']['cpf']) && !empty($data['payer']['cpf'])) {
        $safeDocNumber = preg_replace('/\D/', '', $data['payer']['cpf']);
    }
    
    // 1.5. PARCELAS (sempre > 0)
    $safeInstallments = 1;
    if (isset($data['installments']) && !empty($data['installments']) && is_numeric($data['installments'])) {
        $safeInstallments = max(1, (int)$data['installments']);
    }
    
    // 1.6. PRODUTOS ADICIONAIS E METADADOS
    $safeAdditionalProducts = isset($data['additional_products']) && is_array($data['additional_products']) 
        ? $data['additional_products'] 
        : [];
    $safeMetaData = json_encode($safeAdditionalProducts);
    
    // 1.7. LINK ENTREGÁVEL
    $safeLinkEntregavel = isset($data['product']['link_entregavel']) && !empty($data['product']['link_entregavel'])
        ? $data['product']['link_entregavel']
        : '';
    
    // 1.8. BUSCAR PRODUTO_ID E PRODUTOR_ID (MOVED - ANTES da validação de endereço)
    // CRÍTICO: Buscar tipo_produto ANTES de validar endereço
    $produto_id = isset($data['product']['id']) ? intval($data['product']['id']) : null;
    $produtor_id = null;
    $afiliado_id = null;
    $tipo_produto = 'digital'; // Default
    
    if ($produto_id) {
        try {
            $sql_produto = "SELECT usuario_id, tipo_produto FROM produtos WHERE id = :produto_id LIMIT 1";
            $stmt_produto = $pdo->prepare($sql_produto);
            $stmt_produto->execute([':produto_id' => $produto_id]);
            $produto = $stmt_produto->fetch(PDO::FETCH_ASSOC);
            if ($produto) {
                $produtor_id = intval($produto['usuario_id']);
                $tipo_produto = $produto['tipo_produto'] ?? 'digital';
            }
        } catch (PDOException $e) {
            error_log("Erro ao buscar produtor: " . $e->getMessage());
        }
    }
    
    // 1.7.1. ENDEREÇO E FRETE (Produtos Físicos) - AGORA DEPOIS de buscar tipo_produto
    $safeEnderecoJson = null;
    $safeFreteCobrado = 0;
    $safeStatusEntrega = null;
    
    // VALIDAÇÃO CRÍTICA: Se produto é físico, endereço é OBRIGATÓRIO
    if ($tipo_produto === 'fisico') {
        if (!isset($data['endereco_json']) || empty($data['endereco_json'])) {
            throw new Exception('Por favor, preencha todos os campos de endereço obrigatórios. Produtos físicos requerem endereço de entrega.');
        }
        
        $endereco_array = json_decode($data['endereco_json'], true);
        if (json_last_error() !== JSON_ERROR_NONE || !is_array($endereco_array)) {
            throw new Exception('Erro ao processar dados de endereço. Por favor, verifique os campos e tente novamente.');
        }
        
        // Validar campos obrigatórios
        $campos_faltando = [];
        if (empty($endereco_array['cep']) || strlen(preg_replace('/[^0-9]/', '', $endereco_array['cep'])) !== 8) {
            $campos_faltando[] = 'CEP';
        }
        if (empty($endereco_array['rua'])) {
            $campos_faltando[] = 'Rua';
        }
        if (empty($endereco_array['numero']) || $endereco_array['numero'] === '0') {
            $campos_faltando[] = 'Número';
        }
        if (empty($endereco_array['bairro'])) {
            $campos_faltando[] = 'Bairro';
        }
        if (empty($endereco_array['cidade'])) {
            $campos_faltando[] = 'Cidade';
        }
        if (empty($endereco_array['estado']) || strlen($endereco_array['estado']) !== 2) {
            $campos_faltando[] = 'Estado (UF)';
        }
        
        if (!empty($campos_faltando)) {
            throw new Exception('Por favor, preencha todos os campos de endereço obrigatórios: ' . implode(', ', $campos_faltando));
        }
        
        $safeEnderecoJson = $data['endereco_json'];
        $safeStatusEntrega = 'preparando';
    } elseif (isset($data['endereco_json']) && !empty($data['endereco_json'])) {
        // Produto digital mas endereço fornecido (opcional)
        $endereco_array = json_decode($data['endereco_json'], true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($endereco_array)) {
            if (!empty($endereco_array['cep']) && !empty($endereco_array['rua']) && 
                !empty($endereco_array['numero']) && !empty($endereco_array['bairro']) && 
                !empty($endereco_array['cidade']) && !empty($endereco_array['estado'])) {
                $safeEnderecoJson = $data['endereco_json'];
            }
        }
    }
    
    if (isset($data['frete_cobrado']) && is_numeric($data['frete_cobrado'])) {
        $safeFreteCobrado = max(0, floatval($data['frete_cobrado']));
    }
    
    // 1.9. BUSCAR AFILIADO DO COOKIE (MOVED - DEPOIS de buscar produto_id)
    if (isset($_COOKIE['affiliate_id']) && isset($_COOKIE['affiliate_produto_id'])) {
        $cookie_afiliado_id = intval($_COOKIE['affiliate_id']);
        $cookie_produto_id = intval($_COOKIE['affiliate_produto_id']);
        
        if ($cookie_produto_id == $produto_id && $cookie_afiliado_id > 0) {
            try {
                $sql_afiliado = "SELECT usuario_id FROM afiliacoes WHERE id = :afiliado_id AND produto_id = :produto_id AND status = 'ativo' LIMIT 1";
                $stmt_afiliado = $pdo->prepare($sql_afiliado);
                $stmt_afiliado->execute([':afiliado_id' => $cookie_afiliado_id, ':produto_id' => $produto_id]);
                $afiliado = $stmt_afiliado->fetch(PDO::FETCH_ASSOC);
                if ($afiliado) {
                    $afiliado_id = intval($afiliado['usuario_id']);
                }
            } catch (PDOException $e) {
                error_log("Erro ao buscar afiliado: " . $e->getMessage());
            }
        }
    }
    
    // ============================================================
    // ETAPA 2: INSERT NO BANCO DE DADOS (USANDO VARIÁVEIS SEGURAS)
    // ============================================================
    try {
        // Tentar INSERT completo incluindo campos de produto físico
        $stmt = $pdo->prepare("INSERT INTO transacoes (produto_id, produtor_id, afiliado_id, nome, sobrenome, email, telefone, cpf, device_ip, valor, descricao, status, tipo_pagamento, gateway, device_id, external_reference, metadados, link_entregavel, endereco_json, frete_cobrado, status_entrega) 
                               VALUES (:produto_id, :produtor_id, :afiliado_id, :nome, :sobrenome, :email, :telefone, :cpf, :device_ip, :valor, :descricao, :status, :tipo_pagamento, :gateway, :device_id, :external_reference, :metadados, :link_entregavel, :endereco_json, :frete_cobrado, :status_entrega)");
        $stmt->execute([
            ':produto_id' => $produto_id,
            ':produtor_id' => $produtor_id,
            ':afiliado_id' => $afiliado_id,
            ':nome' => $safeName,
            ':sobrenome' => $safeLastName,
            ':email' => $safeEmail,
            ':telefone' => $safePhoneFull,
            ':cpf' => !empty($safeDocNumber) ? $safeDocNumber : null,
            ':device_ip' => isset($data['client_ip']) ? $data['client_ip'] : null,
            ':valor' => round((float)$data['transaction_amount'], 2),
            ':descricao' => $data['description'],
            ':status' => 'Pendente',
            ':tipo_pagamento' => 'Cartão de Crédito',
            ':gateway' => 'mercadopago',
            ':device_id' => isset($data['device_id']) ? $data['device_id'] : null,
            ':external_reference' => $external_reference,
            ':metadados' => $safeMetaData,
            ':link_entregavel' => $safeLinkEntregavel,
            ':endereco_json' => $safeEnderecoJson,
            ':frete_cobrado' => $safeFreteCobrado,
            ':status_entrega' => $safeStatusEntrega
        ]);
    } catch (PDOException $e) {
        // Se falhar por colunas novas não existirem, tentar sem elas
        if (strpos($e->getMessage(), 'endereco_json') !== false || strpos($e->getMessage(), 'frete_cobrado') !== false || strpos($e->getMessage(), 'status_entrega') !== false) {
            try {
                // Tentar com colunas principais mas sem as novas
                $stmt = $pdo->prepare("INSERT INTO transacoes (produto_id, produtor_id, afiliado_id, nome, sobrenome, email, telefone, cpf, device_ip, valor, descricao, status, tipo_pagamento, gateway, device_id, external_reference, metadados, link_entregavel) 
                                       VALUES (:produto_id, :produtor_id, :afiliado_id, :nome, :sobrenome, :email, :telefone, :cpf, :device_ip, :valor, :descricao, :status, :tipo_pagamento, :gateway, :device_id, :external_reference, :metadados, :link_entregavel)");
                $stmt->execute([
                    ':produto_id' => $produto_id,
                    ':produtor_id' => $produtor_id,
                    ':afiliado_id' => $afiliado_id,
                    ':nome' => $safeName,
                    ':sobrenome' => $safeLastName,
                    ':email' => $safeEmail,
                    ':telefone' => $safePhoneFull,
                    ':cpf' => !empty($safeDocNumber) ? $safeDocNumber : null,
                    ':device_ip' => isset($data['client_ip']) ? $data['client_ip'] : null,
                    ':valor' => round((float)$data['transaction_amount'], 2),
                    ':descricao' => $data['description'],
                    ':status' => 'Pendente',
                    ':tipo_pagamento' => 'Cartão de Crédito',
                    ':gateway' => 'mercadopago',
                    ':device_id' => isset($data['device_id']) ? $data['device_id'] : null,
                    ':external_reference' => $external_reference,
                    ':metadados' => $safeMetaData,
                    ':link_entregavel' => $safeLinkEntregavel
                ]);
            } catch (PDOException $e2) {
                // Se ainda falhar, tentar versão mínima (retrocompatibilidade)
                if (strpos($e2->getMessage(), 'produto_id') !== false || strpos($e2->getMessage(), 'produtor_id') !== false || strpos($e2->getMessage(), 'afiliado_id') !== false) {
                    $stmt = $pdo->prepare("INSERT INTO transacoes (nome, sobrenome, email, telefone, cpf, device_ip, valor, descricao, status, tipo_pagamento, gateway, device_id, external_reference, metadados, link_entregavel) 
                                           VALUES (:nome, :sobrenome, :email, :telefone, :cpf, :device_ip, :valor, :descricao, :status, :tipo_pagamento, :gateway, :device_id, :external_reference, :metadados, :link_entregavel)");
                    $stmt->execute([
                        ':nome' => $safeName,
                        ':sobrenome' => $safeLastName,
                        ':email' => $safeEmail,
                        ':telefone' => $safePhoneFull,
                        ':cpf' => !empty($safeDocNumber) ? $safeDocNumber : null,
                        ':device_ip' => isset($data['client_ip']) ? $data['client_ip'] : null,
                        ':valor' => round((float)$data['transaction_amount'], 2),
                        ':descricao' => $data['description'],
                        ':status' => 'Pendente',
                        ':tipo_pagamento' => 'Cartão de Crédito',
                        ':gateway' => 'mercadopago',
                        ':device_id' => isset($data['device_id']) ? $data['device_id'] : null,
                        ':external_reference' => $external_reference,
                        ':metadados' => $safeMetaData,
                        ':link_entregavel' => $safeLinkEntregavel
                    ]);
                } else {
                    throw $e2;
                }
            }
        } else {
            throw $e;
        }
    }
    
    // Obtém o último ID inserido no banco de dados
    $transaction_id = $pdo->lastInsertId();
    
    // ============================================================
    // ETAPA 3: LOOP DE PRODUTOS ADICIONAIS (PROTEGIDO)
    // ============================================================
    if (isset($safeAdditionalProducts) && is_array($safeAdditionalProducts) && !empty($safeAdditionalProducts)) {
        foreach ($safeAdditionalProducts as $produto) {
            // Validar estrutura do produto antes de inserir
            if (isset($produto['id']) && isset($produto['nome']) && isset($produto['preco'])) {
                try {
                    $stmt = $pdo->prepare("INSERT INTO transacoes_adicionais (transacao_id, produto_id, nome, preco) 
                                           VALUES (:transacao_id, :produto_id, :nome, :preco)");
                    $stmt->execute([
                        ':transacao_id' => $transaction_id,
                        ':produto_id' => (int)$produto['id'],
                        ':nome' => trim($produto['nome']),
                        ':preco' => round((float)$produto['preco'], 2)
                    ]);
                } catch (PDOException $e) {
                    error_log("Erro ao inserir produto adicional: " . $e->getMessage());
                    // Continuar processamento mesmo se houver erro em produto adicional
                }
            } else {
                error_log("Produto adicional com estrutura inválida: " . json_encode($produto));
            }
        }
    }
    
    // ============================================================
    // ETAPA 4: MONTAGEM DO ARRAY MERCADO PAGO (USANDO VARIÁVEIS SEGURAS)
    // ============================================================
    
    // VALIDAÇÃO DE CPF VAZIO (Impede envio de string vazia)
    if (empty($safeDocNumber) || trim($safeDocNumber) === '') {
        throw new Exception("Erro: CPF do pagador não foi informado ou é inválido.");
    }
    
    $client = new PaymentClient();
    
    // Criar request options com idempotency key
    $requestOptions = new RequestOptions();
    $idempotencyKey = uniqid('mp_', true) . '_' . time();
    $requestOptions->setCustomHeaders(["X-Idempotency-Key: {$idempotencyKey}"]);
    
    // Montar objeto de pagamento usando APENAS variáveis seguras da ETAPA 1
    $paymentData = [
        "transaction_amount" => round((float)$data['transaction_amount'], 2),
        "token" => $data['token'],
        "description" => $data['description'],
        "installments" => $safeInstallments,
        "payment_method_id" => $data['payment_method_id'],
        "external_reference" => $external_reference,
        "notification_url" => "https://" . $_SERVER['HTTP_HOST'] . "/backend/webhook.php",
        "payer" => [
            "email" => $safeEmail,
            "first_name" => $safeName,
            "last_name" => $safeLastName,
            "identification" => [
                "type" => $safeDocType,
                "number" => $safeDocNumber
            ],
            "phone" => [
                "area_code" => $safeAreaCode,
                "number" => $safePhoneNumber
            ]
        ]
    ];
    
    // ============================================================
    // ESTRUTURA OBRIGATÓRIA PARA PRODUTOS FÍSICOS: additional_info -> shipments -> receiver_address
    // ============================================================
    if (!empty($safeEnderecoJson)) {
        $endereco_array = json_decode($safeEnderecoJson, true);
        if (json_last_error() === JSON_ERROR_NONE && is_array($endereco_array)) {
            // Sanitização rigorosa dos dados de endereço
            $cep = preg_replace('/[^0-9]/', '', $endereco_array['cep'] ?? '');
            $numero = (int) preg_replace('/[^0-9]/', '', $endereco_array['numero'] ?? 0);
            if ($numero === 0 || $numero < 1) $numero = 1; // Fallback se não tiver número ou for inválido
            $numero = (string)$numero; // Mercado Pago exige string para street_number
            
            // Buscar informações do produto para items
            $produto_nome = $data['description'] ?? 'Produto';
            $produto_preco = round((float)$data['transaction_amount'], 2);
            
            // Montar items: produto principal + produtos adicionais
            $items = [
                [
                    'id' => (string) ($produto_id ?? '1'),
                    'title' => $produto_nome,
                    'quantity' => 1,
                    'unit_price' => $produto_preco
                ]
            ];
            
            // Adicionar produtos adicionais aos items se existirem
            if (isset($safeAdditionalProducts) && is_array($safeAdditionalProducts) && !empty($safeAdditionalProducts)) {
                foreach ($safeAdditionalProducts as $produto_adicional) {
                    if (isset($produto_adicional['id']) && isset($produto_adicional['nome']) && isset($produto_adicional['preco'])) {
                        $items[] = [
                            'id' => (string) $produto_adicional['id'],
                            'title' => trim($produto_adicional['nome']),
                            'quantity' => 1,
                            'unit_price' => round((float)$produto_adicional['preco'], 2)
                        ];
                    }
                }
            }
            
            // Montar estrutura additional_info -> shipments -> receiver_address
            // IMPORTANTE: Para cartão, receiver_address NÃO aceita 'neighborhood' (diferente de outros métodos)
            // Campos aceitos: zip_code, street_name, street_number, city_name, state_name, floor (opcional), apartment (opcional)
            $receiver_address = [
                'zip_code' => $cep,
                'street_name' => $endereco_array['rua'] ?? 'Rua não informada',
                'street_number' => $numero,
                'city_name' => $endereco_array['cidade'] ?? '',
                'state_name' => strtoupper($endereco_array['estado'] ?? '')
            ];
            
            // Adicionar campos opcionais apenas se não estiverem vazios
            if (!empty(trim($endereco_array['complemento'] ?? ''))) {
                $receiver_address['floor'] = trim($endereco_array['complemento']);
            }
            
            $paymentData['additional_info'] = [
                'items' => $items,
                'shipments' => [
                    'receiver_address' => $receiver_address
                ]
            ];
            
            error_log("CARTÃO - additional_info montado: " . json_encode($paymentData['additional_info'], JSON_UNESCAPED_UNICODE));
        }
    }
    
    // Adicionar issuer_id se presente e válido
    if (isset($data['issuer']) && !empty($data['issuer']) && is_numeric($data['issuer'])) {
        $paymentData['issuer_id'] = (int)$data['issuer'];
    }
    
    // LOG ESPIÃO (Debug - Ver o que está sendo enviado)
    error_log("TENTATIVA MP - Nome: $safeName | CPF: $safeDocNumber | Valor: " . $data['transaction_amount']);
    
    // Criar pagamento via SDK v3
    $payment = $client->create($paymentData, $requestOptions);

    if ($payment->status == 'approved') {
        $stmt = $pdo->prepare("UPDATE transacoes SET status = 'Aprovado', payment_id = :payment_id WHERE id = :id");
        $stmt->execute([
            ':payment_id' => $payment->id,
            ':id' => $transaction_id
        ]);
        
        // Calcular e registrar comissões (verificando duplicidade)
        require_once __DIR__ . '/financeiro_helper.php';
        if ($produto_id && $produtor_id) {
            // Verificar se já existe comissão registrada para evitar duplicação
            try {
                $sql_check = "SELECT id FROM vendas_comissoes WHERE transacao_id = :transacao_id LIMIT 1";
                $stmt_check = $pdo->prepare($sql_check);
                $stmt_check->execute([':transacao_id' => $transaction_id]);
                $comissao_existe = $stmt_check->fetch(PDO::FETCH_ASSOC);
                
                if (!$comissao_existe) {
                    calcular_e_registrar_comissoes(
                        $transaction_id,
                        $produto_id,
                        $produtor_id,
                        $afiliado_id,
                        round((float)$data['transaction_amount'], 2)
                    );
                }
            } catch (PDOException $e) {
                error_log("Erro ao verificar comissão duplicada em process_payment: " . $e->getMessage());
            }
        }
        echo json_encode([
            'status' => 'success',
            'transaction_id' => $transaction_id,
            'payment_id' => $payment->id,
            'fbq_event' => [
                'value' => $data['transaction_amount'],
                'currency' => 'BRL'
            ]
        ]);
    } elseif ($payment->status == 'in_process' || $payment->status == 'pending') {
        // Pagamento pendente (aguardando confirmação)
        $stmt = $pdo->prepare("UPDATE transacoes SET status = 'Pendente', payment_id = :payment_id WHERE id = :id");
        $stmt->execute([
            ':payment_id' => $payment->id,
            ':id' => $transaction_id
        ]);
        echo json_encode([
            'status' => 'pending',
            'message' => 'Pagamento em processamento. Aguarde a confirmação.',
            'transaction_id' => $transaction_id,
            'payment_id' => $payment->id
        ]);
    } elseif ($payment->status == 'rejected') {
        // Pagamento recusado - Retorna motivo exato para debug
        $status_detail = property_exists($payment, 'status_detail') ? $payment->status_detail : 'Desconhecido';
        $error_message = getFriendlyErrorMessage($status_detail);
        
        // Log detalhado para debug
        error_log("=== PAGAMENTO RECUSADO ===");
        error_log("Status: " . $payment->status);
        error_log("Status Detail: " . $status_detail);
        error_log("Payment ID: " . ($payment->id ?? 'N/A'));
        
        $stmt = $pdo->prepare("UPDATE transacoes SET status = 'Falha', erro = :erro, payment_id = :payment_id WHERE id = :id");
        $stmt->execute([
            ':erro' => $status_detail,
            ':payment_id' => $payment->id ?? null,
            ':id' => $transaction_id
        ]);
        
        // Retorna mensagem completa com motivo técnico da recusa
        $mensagem_completa = "Pagamento Recusado pelo Banco. Motivo Técnico: " . $status_detail . " | Status: " . $payment->status;
        echo json_encode([
            'status' => 'failure',
            'message' => $mensagem_completa,
            'debug' => [
                'status_detail' => $status_detail,
                'status' => $payment->status,
                'payment_id' => $payment->id ?? null
            ]
        ]);
        exit;
    } else {
        // Status desconhecido
        $status_detail = property_exists($payment, 'status_detail') ? $payment->status_detail : 'Status desconhecido: ' . $payment->status;
        error_log("Status de pagamento não esperado: " . $payment->status . " - Detail: " . $status_detail);
        
        $stmt = $pdo->prepare("UPDATE transacoes SET status = 'Erro', erro = :erro, payment_id = :payment_id WHERE id = :id");
        $stmt->execute([
            ':erro' => $status_detail,
            ':payment_id' => $payment->id ?? null,
            ':id' => $transaction_id
        ]);
        
        echo json_encode([
            'status' => 'error',
            'message' => 'Status de pagamento não reconhecido: ' . $payment->status . '. Motivo: ' . $status_detail
        ]);
        exit;
    }
    
} catch (MPApiException $e) {
    // Log detalhado do erro
    error_log('=== ERRO DA API MERCADO PAGO CARTÃO ===');
    error_log('Mensagem: ' . $e->getMessage());
    error_log('Código: ' . ($e->getStatusCode() ?? 'N/A'));
    
    // Tentar extrair informações adicionais - SDK v3 usa getApiResponse()->getContent()
    $error_message = $e->getMessage();
    $api_response = null;
    
    // Tentar getApiResponse() -> getContent() (método correto do SDK v3)
    if (method_exists($e, 'getApiResponse')) {
        try {
            $mpResponse = $e->getApiResponse();
            if (method_exists($mpResponse, 'getContent')) {
                $api_response = $mpResponse->getContent();
                error_log('Resposta da API (getApiResponse()->getContent()): ' . json_encode($api_response, JSON_UNESCAPED_UNICODE));
            }
        } catch (Exception $ex) {
            error_log('Erro ao chamar getApiResponse()->getContent(): ' . $ex->getMessage());
        }
    }
    
    // Extrair mensagem mais específica da resposta
    if (!empty($api_response)) {
        if (is_array($api_response)) {
            // Tentar extrair mensagem principal
            if (isset($api_response['message'])) {
                $error_message = $api_response['message'];
            }
            
            // Tentar extrair causas específicas
            if (isset($api_response['cause']) && is_array($api_response['cause'])) {
                $causes = [];
                foreach ($api_response['cause'] as $cause) {
                    if (isset($cause['description'])) {
                        $causes[] = $cause['description'];
                    } elseif (isset($cause['code'])) {
                        $causes[] = 'Código: ' . $cause['code'];
                    }
                }
                if (!empty($causes)) {
                    $error_message = implode('. ', $causes);
                }
            }
            
            // Tentar extrair erros de validação
            if (isset($api_response['errors']) && is_array($api_response['errors'])) {
                $errors = [];
                foreach ($api_response['errors'] as $error) {
                    if (isset($error['message'])) {
                        $errors[] = $error['message'];
                    }
                }
                if (!empty($errors)) {
                    $error_message = implode('. ', $errors);
                }
            }
            
            // Tentar extrair status_detail para usar na função getFriendlyErrorMessage
            if (isset($api_response['status_detail'])) {
                $error_message = getFriendlyErrorMessage($api_response['status_detail']);
            }
        }
    }
    
    // Log do payload COMPLETO enviado para debug (sem dados sensíveis)
    if (isset($paymentData)) {
        $log_payload = $paymentData;
        if (isset($log_payload['payer']['identification']['number'])) {
            $cpf_log = $log_payload['payer']['identification']['number'];
            $log_payload['payer']['identification']['number'] = substr($cpf_log, 0, 3) . '***' . substr($cpf_log, -2);
        }
        if (isset($log_payload['token'])) {
            $log_payload['token'] = substr($log_payload['token'], 0, 10) . '***';
        }
        error_log('Payload COMPLETO enviado à API: ' . json_encode($log_payload, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT));
    }
    
    if (isset($transaction_id)) {
        try {
            $stmt = $pdo->prepare("UPDATE transacoes SET status = 'Erro', erro = :erro WHERE id = :id");
            $stmt->execute([
                ':erro' => $error_message,
                ':id' => $transaction_id
            ]);
        } catch (PDOException $db_error) {
            error_log("Erro ao atualizar transação após erro da API: " . $db_error->getMessage());
        }
    }
    
    http_response_code(400);
    echo json_encode([
        'status' => 'error',
        'message' => $error_message
    ]);
    exit;
} catch (Exception $e) {
    error_log('Erro no pagamento com cartão: ' . $e->getMessage());
    error_log('Stack trace: ' . $e->getTraceAsString());
    
    if (isset($transaction_id)) {
        try {
            $stmt = $pdo->prepare("UPDATE transacoes SET status = 'Erro', erro = :erro WHERE id = :id");
            $stmt->execute([
                ':erro' => $e->getMessage(),
                ':id' => $transaction_id
            ]);
        } catch (PDOException $db_error) {
            error_log("Erro ao atualizar transação após erro geral: " . $db_error->getMessage());
        }
    }
    
    http_response_code(500);
    echo json_encode(['status' => 'error', 'message' => 'Erro ao processar pagamento: ' . $e->getMessage()]);
    exit;
}
?>