<?php
declare(strict_types=1);

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

function mp_money(float $valor): float
{
    return round($valor, 2);
}

function mp_table_exists(PDO $pdo, string $table): bool
{
    $stmt = $pdo->prepare(
        'SELECT COUNT(*)
         FROM INFORMATION_SCHEMA.TABLES
         WHERE TABLE_SCHEMA = DATABASE()
           AND TABLE_NAME = ?'
    );
    $stmt->execute([$table]);

    return (int) $stmt->fetchColumn() > 0;
}

function mp_column_exists(PDO $pdo, string $table, string $column): bool
{
    $stmt = $pdo->prepare(
        'SELECT COUNT(*)
         FROM INFORMATION_SCHEMA.COLUMNS
         WHERE TABLE_SCHEMA = DATABASE()
           AND TABLE_NAME = ?
           AND COLUMN_NAME = ?'
    );
    $stmt->execute([$table, $column]);

    return (int) $stmt->fetchColumn() > 0;
}

class MercadoPagoApiException extends RuntimeException
{
    private int $httpStatus;
    private array $response;
    private string $publicMessage;

    public function __construct(string $message, int $httpStatus, array $response)
    {
        parent::__construct($message, $httpStatus);
        $this->httpStatus = $httpStatus;
        $this->response = $response;
        $this->publicMessage = $message;
    }

    public function httpStatus(): int
    {
        return $this->httpStatus;
    }

    public function response(): array
    {
        return $this->response;
    }

    public function publicMessage(): string
    {
        return $this->publicMessage;
    }
}

function mp_status_detail_descricao(string $statusDetail): string
{
    return match (strtolower(trim($statusDetail))) {
        'accredited' => 'Pagamento aprovado.',
        'pending_contingency' => 'Pagamento em processamento.',
        'pending_review_manual' => 'Pagamento em analise manual.',
        'pending_waiting_payment' => 'Pagamento aguardando confirmacao.',
        'cc_rejected_bad_filled_card_number' => 'Numero do cartao incorreto.',
        'cc_rejected_bad_filled_date' => 'Data de validade do cartao incorreta.',
        'cc_rejected_bad_filled_other' => 'Algum dado do cartao esta incorreto.',
        'cc_rejected_bad_filled_security_code' => 'Codigo de seguranca do cartao incorreto.',
        'cc_rejected_blacklist' => 'Pagamento recusado por seguranca.',
        'cc_rejected_call_for_authorize' => 'O banco pediu autorizacao previa para esse pagamento.',
        'cc_rejected_card_disabled' => 'Cartao desativado ou bloqueado.',
        'cc_rejected_card_error' => 'O cartao recusou a transacao.',
        'cc_rejected_duplicated_payment' => 'Pagamento duplicado.',
        'cc_rejected_high_risk' => 'Pagamento recusado por analise de risco.',
        'cc_rejected_insufficient_amount' => 'Cartao sem limite suficiente.',
        'cc_rejected_invalid_installments' => 'Quantidade de parcelas invalida.',
        'cc_rejected_max_attempts' => 'Limite de tentativas excedido para esse cartao.',
        'cc_rejected_other_reason' => 'Pagamento recusado pelo emissor do cartao.',
        default => '',
    };
}

function mp_gateway_public_message(array $response, string $fallback = 'Erro ao comunicar com o provedor de pagamento.'): string
{
    $messages = [];
    $add = static function ($value) use (&$messages): void {
        $text = trim((string) $value);
        if ($text !== '' && !in_array($text, $messages, true)) {
            $messages[] = $text;
        }
    };

    foreach (['message', 'error', 'error_message', 'gateway_message'] as $key) {
        if (isset($response[$key])) {
            $add($response[$key]);
        }
    }

    $statusDetail = trim((string) ($response['status_detail'] ?? ''));
    if ($statusDetail !== '') {
        $descricao = mp_status_detail_descricao($statusDetail);
        $add($descricao !== '' ? $descricao . ' (' . $statusDetail . ')' : $statusDetail);
    }

    $cause = $response['cause'] ?? null;
    if (is_array($cause)) {
        foreach ($cause as $item) {
            if (is_array($item)) {
                foreach (['description', 'message', 'code'] as $key) {
                    if (isset($item[$key])) {
                        $add($item[$key]);
                    }
                }
            } else {
                $add($item);
            }
        }
    }

    $details = $response['details'] ?? $response['errors'] ?? null;
    if (is_array($details)) {
        foreach ($details as $item) {
            if (is_array($item)) {
                foreach (['description', 'message', 'code'] as $key) {
                    if (isset($item[$key])) {
                        $add($item[$key]);
                    }
                }
            } else {
                $add($item);
            }
        }
    } elseif ($details !== null) {
        $add($details);
    }

    if (!$messages && isset($response['raw'])) {
        $add($response['raw']);
    }

    return $messages ? implode(' ', array_slice($messages, 0, 4)) : $fallback;
}

function mp_gateway_exception_message(Throwable $e, string $fallback): string
{
    if ($e instanceof MercadoPagoApiException) {
        return $e->publicMessage();
    }

    $message = trim($e->getMessage());
    return $message !== '' ? $message : $fallback;
}

function mp_gateway_exception_payload(Throwable $e): array
{
    if (!$e instanceof MercadoPagoApiException) {
        return ['error' => $e->getMessage()];
    }

    $response = $e->response();
    $public = [
        'gateway_message' => $e->publicMessage(),
        'gateway_http_status' => $e->httpStatus(),
    ];
    foreach (['message', 'error', 'status', 'status_detail', 'cause'] as $key) {
        if (array_key_exists($key, $response)) {
            $public['gateway'][$key] = $response[$key];
        }
    }

    return $public;
}

function mp_config(PDO $pdo): array
{
    if (!mp_table_exists($pdo, 'configuracoes')) {
        return [
            'ambiente' => 'sandbox',
            'marketplace_ativo' => false,
            'taxa_gateway_percentual' => 0.0,
        ];
    }

    $stmt = $pdo->query(
        'SELECT chave, valor
         FROM configuracoes
         WHERE chave IN ("mp_ambiente_sandbox", "mp_marketplace_ativo", "mp_taxa_gateway_percentual")'
    );
    $rows = $stmt->fetchAll(PDO::FETCH_KEY_PAIR) ?: [];

    return [
        'ambiente' => ((float) ($rows['mp_ambiente_sandbox'] ?? 1)) > 0 ? 'sandbox' : 'producao',
        'marketplace_ativo' => ((float) ($rows['mp_marketplace_ativo'] ?? 0)) > 0,
        'taxa_gateway_percentual' => (float) ($rows['mp_taxa_gateway_percentual'] ?? 0),
    ];
}

function mp_config_textual(PDO $pdo): array
{
    $defaults = [
        'mp_client_id' => ['valor' => '', 'descricao' => 'Client ID do aplicativo Mercado Pago', 'sensivel' => false],
        'mp_client_secret' => ['valor' => '', 'descricao' => 'Client Secret do aplicativo Mercado Pago', 'sensivel' => true],
        'mp_public_key' => ['valor' => '', 'descricao' => 'Public Key da plataforma para Checkout Transparente', 'sensivel' => false],
        'mp_access_token_plataforma' => ['valor' => '', 'descricao' => 'Access Token da conta plataforma', 'sensivel' => true],
        'mp_redirect_uri' => ['valor' => 'http://localhost/bulo_backend/auth/mercado_pago_callback.php', 'descricao' => 'URL de retorno OAuth cadastrada no Mercado Pago', 'sensivel' => false],
        'mp_webhook_url' => ['valor' => 'http://localhost/bulo_backend/pagamentos/mercado_pago_webhook.php', 'descricao' => 'URL de webhook cadastrada no Mercado Pago', 'sensivel' => false],
    ];

    if (!mp_table_exists($pdo, 'mercado_pago_configuracoes')) {
        return $defaults;
    }

    $stmt = $pdo->query('SELECT chave, valor, descricao, sensivel, atualizado_por, atualizado_em FROM mercado_pago_configuracoes');
    foreach ($stmt->fetchAll() as $row) {
        $chave = (string) $row['chave'];
        $defaults[$chave] = [
            'valor' => (string) ($row['valor'] ?? ''),
            'descricao' => (string) ($row['descricao'] ?? ($defaults[$chave]['descricao'] ?? '')),
            'sensivel' => (bool) ($row['sensivel'] ?? false),
            'atualizado_por' => $row['atualizado_por'] ?? null,
            'atualizado_em' => $row['atualizado_em'] ?? null,
        ];
    }

    return $defaults;
}

function mp_config_valor(PDO $pdo, string $chave): string
{
    $config = mp_config_textual($pdo);
    return (string) ($config[$chave]['valor'] ?? '');
}

function mp_config_salvar(PDO $pdo, string $chave, ?string $valor, string $descricao, bool $sensivel, string $admin): void
{
    if (!mp_table_exists($pdo, 'mercado_pago_configuracoes')) {
        throw new RuntimeException('Tabela mercado_pago_configuracoes nao existe. Rode a atualizacao do banco.');
    }

    $stmt = $pdo->prepare(
        'INSERT INTO mercado_pago_configuracoes (chave, valor, descricao, sensivel, atualizado_por)
         VALUES (?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           valor = VALUES(valor),
           descricao = VALUES(descricao),
           sensivel = VALUES(sensivel),
           atualizado_por = VALUES(atualizado_por)'
    );
    $stmt->execute([$chave, $valor, $descricao, $sensivel ? 1 : 0, $admin]);
}

function mp_pkce_b64url(string $bytes): string
{
    return rtrim(strtr(base64_encode($bytes), '+/', '-_'), '=');
}

function mp_pkce_code_verifier(): string
{
    return mp_pkce_b64url(random_bytes(64));
}

function mp_pkce_code_challenge(string $codeVerifier): string
{
    return mp_pkce_b64url(hash('sha256', $codeVerifier, true));
}

function mp_oauth_authorization_host(PDO $pdo): string
{
    return 'https://auth.mercadopago.com/authorization';
}

function mp_oauth_state_criar(PDO $pdo, int $idUsuario, string $tipoUsuario, string $redirectUri): array
{
    if (!mp_table_exists($pdo, 'mercado_pago_oauth_states')) {
        throw new RuntimeException('Tabela mercado_pago_oauth_states nao existe. Rode a atualizacao do banco.');
    }

    $state = bin2hex(random_bytes(24));
    $codeVerifier = mp_pkce_code_verifier();

    if (mp_column_exists($pdo, 'mercado_pago_oauth_states', 'code_verifier')) {
        $stmt = $pdo->prepare(
            'INSERT INTO mercado_pago_oauth_states (state, id_usuario, tipo_usuario, redirect_uri, code_verifier, expira_em)
             VALUES (?, ?, ?, ?, ?, DATE_ADD(NOW(), INTERVAL 20 MINUTE))'
        );
        $stmt->execute([$state, $idUsuario, $tipoUsuario, $redirectUri, $codeVerifier]);
    } else {
        $stmt = $pdo->prepare(
            'INSERT INTO mercado_pago_oauth_states (state, id_usuario, tipo_usuario, redirect_uri, expira_em)
             VALUES (?, ?, ?, ?, DATE_ADD(NOW(), INTERVAL 20 MINUTE))'
        );
        $stmt->execute([$state, $idUsuario, $tipoUsuario, $redirectUri]);
    }

    return [
        'state' => $state,
        'code_verifier' => $codeVerifier,
        'code_challenge' => mp_pkce_code_challenge($codeVerifier),
    ];
}

function mp_oauth_authorization_url(PDO $pdo, int $idUsuario, string $tipoUsuario = 'motorista'): string
{
    $clientId = trim(mp_config_valor($pdo, 'mp_client_id'));
    $redirectUri = trim(mp_config_valor($pdo, 'mp_redirect_uri'));
    if ($clientId === '' || $redirectUri === '') {
        throw new RuntimeException('Configure as credenciais OAuth no painel.');
    }

    $statePayload = mp_oauth_state_criar($pdo, $idUsuario, $tipoUsuario, $redirectUri);
    $query = http_build_query([
        'client_id' => $clientId,
        'response_type' => 'code',
        'platform_id' => 'mp',
        'state' => $statePayload['state'],
        'redirect_uri' => $redirectUri,
        'code_challenge' => $statePayload['code_challenge'],
        'code_challenge_method' => 'S256',
    ]);

    return mp_oauth_authorization_host($pdo) . '?' . $query;
}

function mp_http_request(string $method, string $url, array $headers = [], ?array $payload = null): array
{
    if (!function_exists('curl_init')) {
        throw new RuntimeException('Extensao cURL do PHP nao esta ativa.');
    }

    $ch = curl_init($url);
    $defaultHeaders = ['Accept: application/json'];
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_HTTPHEADER => array_merge($defaultHeaders, $headers),
        CURLOPT_TIMEOUT => 25,
    ]);
    if ($payload !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, http_build_query($payload));
    }

    $body = curl_exec($ch);
    $errno = curl_errno($ch);
    $error = curl_error($ch);
    $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($errno !== 0) {
        throw new RuntimeException('Erro ao comunicar com o provedor de pagamento: ' . $error);
    }

    $decoded = json_decode((string) $body, true);
    if (!is_array($decoded)) {
        $decoded = ['raw' => (string) $body];
    }
    $decoded['_http_status'] = $status;

    if ($status < 200 || $status >= 300) {
        throw new MercadoPagoApiException(
            mp_gateway_public_message($decoded),
            $status,
            $decoded
        );
    }

    return $decoded;
}

function mp_http_json_request(
    string $method,
    string $url,
    array $headers = [],
    ?array $payload = null,
    ?string $idempotencyKey = null
): array {
    if (!function_exists('curl_init')) {
        throw new RuntimeException('Extensao cURL do PHP nao esta ativa.');
    }

    $defaultHeaders = ['Accept: application/json'];
    if ($payload !== null) {
        $defaultHeaders[] = 'Content-Type: application/json';
    }
    if ($idempotencyKey !== null && trim($idempotencyKey) !== '') {
        $defaultHeaders[] = 'X-Idempotency-Key: ' . trim($idempotencyKey);
    }

    $ch = curl_init($url);
    curl_setopt_array($ch, [
        CURLOPT_RETURNTRANSFER => true,
        CURLOPT_CUSTOMREQUEST => $method,
        CURLOPT_HTTPHEADER => array_merge($defaultHeaders, $headers),
        CURLOPT_TIMEOUT => 30,
    ]);
    if ($payload !== null) {
        curl_setopt($ch, CURLOPT_POSTFIELDS, json_encode($payload, JSON_UNESCAPED_UNICODE));
    }

    $body = curl_exec($ch);
    $errno = curl_errno($ch);
    $error = curl_error($ch);
    $status = (int) curl_getinfo($ch, CURLINFO_HTTP_CODE);
    curl_close($ch);

    if ($errno !== 0) {
        throw new RuntimeException('Erro ao comunicar com o provedor de pagamento: ' . $error);
    }

    $decoded = json_decode((string) $body, true);
    if (!is_array($decoded)) {
        $decoded = ['raw' => (string) $body];
    }
    $decoded['_http_status'] = $status;

    if ($status < 200 || $status >= 300) {
        throw new MercadoPagoApiException(
            mp_gateway_public_message($decoded),
            $status,
            $decoded
        );
    }

    return $decoded;
}

function mp_access_token_plataforma(PDO $pdo): string
{
    $token = trim(mp_config_valor($pdo, 'mp_access_token_plataforma'));
    if ($token === '') {
        throw new RuntimeException('Pagamento online nao configurado no painel.');
    }

    return $token;
}

function mp_reembolsar_pagamento(PDO $pdo, string $mpPaymentId, ?float $valor = null, ?string $idempotencyKey = null): array
{
    $mpPaymentId = trim($mpPaymentId);
    if ($mpPaymentId === '') {
        throw new RuntimeException('Pagamento online nao informado para estorno.');
    }

    $payload = [];
    if ($valor !== null) {
        $valor = mp_money($valor);
        if ($valor <= 0) {
            throw new RuntimeException('Valor de estorno invalido.');
        }
        $payload['amount'] = $valor;
    }

    return mp_http_json_request(
        'POST',
        'https://api.mercadopago.com/v1/payments/' . rawurlencode($mpPaymentId) . '/refunds',
        ['Authorization: Bearer ' . mp_access_token_plataforma($pdo)],
        $payload,
        $idempotencyKey ?: 'bulo-refund-' . $mpPaymentId . '-' . ($valor === null ? 'total' : number_format($valor, 2, '.', ''))
    );
}

function mp_status_pagamento_local(string $statusMercadoPago): string
{
    return match (strtolower(trim($statusMercadoPago))) {
        'approved', 'aprovado' => 'aprovado',
        'authorized', 'autorizado' => 'autorizado',
        'rejected', 'recusado' => 'recusado',
        'cancelled', 'canceled', 'cancelado' => 'cancelado',
        'refunded', 'charged_back', 'estornado' => 'estornado',
        'in_process', 'pending', 'pendente' => 'pendente',
        default => 'pendente',
    };
}

function mp_taxa_gateway_de_pagamento(array $pagamento): float
{
    $total = 0.0;
    foreach (($pagamento['fee_details'] ?? []) as $fee) {
        if (is_array($fee) && isset($fee['amount'])) {
            $total += (float) $fee['amount'];
        }
    }

    if ($total <= 0.0) {
        $valorTotal = (float) ($pagamento['transaction_amount'] ?? 0);
        $valorLiquido = (float) ($pagamento['transaction_details']['net_received_amount'] ?? 0);
        if ($valorTotal > 0 && $valorLiquido > 0 && $valorTotal > $valorLiquido) {
            $total = $valorTotal - $valorLiquido;
        }
    }

    return mp_money(max(0.0, $total));
}

function mp_pix_payload_publico(array $pagamento, array $row = []): array
{
    $transaction = $pagamento['point_of_interaction']['transaction_data'] ?? [];
    return [
        'id' => $row['id'] ?? null,
        'mp_payment_id' => (string) ($pagamento['id'] ?? $row['mp_payment_id'] ?? ''),
        'status' => mp_status_pagamento_local((string) ($pagamento['status'] ?? $row['status'] ?? 'pendente')),
        'status_mp' => (string) ($pagamento['status'] ?? ''),
        'external_reference' => (string) ($pagamento['external_reference'] ?? $row['external_reference'] ?? ''),
        'valor_total' => (float) ($row['valor_total'] ?? $pagamento['transaction_amount'] ?? 0),
        'valor_motorista' => (float) ($row['valor_motorista'] ?? 0),
        'valor_plataforma' => (float) ($row['valor_plataforma'] ?? 0),
        'taxa_gateway' => (float) ($row['taxa_gateway'] ?? 0),
        'qr_code' => (string) ($transaction['qr_code'] ?? ''),
        'qr_code_base64' => (string) ($transaction['qr_code_base64'] ?? ''),
        'ticket_url' => (string) ($transaction['ticket_url'] ?? ''),
        'gateway_message' => mp_gateway_public_message($pagamento, ''),
    ];
}

function mp_oauth_trocar_codigo(PDO $pdo, string $code, string $redirectUri, ?string $codeVerifier = null): array
{
    $clientId = trim(mp_config_valor($pdo, 'mp_client_id'));
    $clientSecret = trim(mp_config_valor($pdo, 'mp_client_secret'));
    if ($clientId === '' || $clientSecret === '') {
        throw new RuntimeException('Configure as credenciais OAuth no painel.');
    }

    $payload = [
        'client_secret' => $clientSecret,
        'client_id' => $clientId,
        'grant_type' => 'authorization_code',
        'code' => $code,
        'redirect_uri' => $redirectUri,
    ];
    if ($codeVerifier !== null && trim($codeVerifier) !== '') {
        $payload['code_verifier'] = trim($codeVerifier);
    }

    return mp_http_request(
        'POST',
        'https://api.mercadopago.com/oauth/token',
        ['Content-Type: application/x-www-form-urlencoded'],
        $payload
    );
}

function mp_oauth_usuario_me(string $accessToken): array
{
    return mp_http_request(
        'GET',
        'https://api.mercadopago.com/users/me',
        ['Authorization: Bearer ' . $accessToken]
    );
}

function mp_external_reference(string $tipo, int $id): string
{
    return 'BULO-' . strtoupper($tipo) . '-' . $id;
}

function mp_corrida_valores(float $valorTotal, float $saldoNegativoCobrado = 0.0, float $taxaGateway = 0.0): array
{
    $base = max(0.0, $valorTotal - $saldoNegativoCobrado);
    $valorMotorista = mp_money($base * CARTEIRA_PERCENTUAL_MOTORISTA_ONLINE);
    $valorPlataformaBruto = mp_money(max(0.0, $base - $valorMotorista));
    $taxaGateway = mp_money(max(0.0, $taxaGateway));
    $valorPlataforma = mp_money($valorPlataformaBruto - $taxaGateway);

    return [
        'valor_total' => mp_money($valorTotal),
        'valor_motorista' => $valorMotorista,
        'valor_plataforma' => $valorPlataforma,
        'valor_plataforma_bruto' => $valorPlataformaBruto,
        'taxa_gateway' => $taxaGateway,
        'application_fee' => $valorPlataformaBruto,
    ];
}

function mp_pagamento_metodo_corrida(array $corrida): string
{
    $detalhe = strtolower(trim((string) ($corrida['forma_pagamento_detalhe'] ?? '')));
    $forma = strtolower(trim((string) ($corrida['forma_pagamento'] ?? '')));
    if ($detalhe === 'cartao_credito') {
        return 'cartao_credito';
    }
    if ($detalhe === 'pix_online' || $forma === 'online') {
        return 'pix_online';
    }

    return 'dinheiro_pix';
}

function mp_corrida_deve_ter_pagamento_gateway(array $corrida): bool
{
    return mp_pagamento_metodo_corrida($corrida) !== 'dinheiro_pix';
}

function mp_registrar_pagamento_corrida(PDO $pdo, array $corrida, string $status = 'pendente'): ?int
{
    if (!mp_table_exists($pdo, 'pagamentos_corridas')) {
        return null;
    }

    $metodo = mp_pagamento_metodo_corrida($corrida);
    if ($metodo === 'dinheiro_pix') {
        return null;
    }

    $idCorrida = (int) ($corrida['id'] ?? 0);
    if ($idCorrida <= 0) {
        return null;
    }

    $config = mp_config($pdo);
    $externalReference = (string) ($corrida['mp_external_reference'] ?? '');
    if ($externalReference === '') {
        $externalReference = mp_external_reference('corrida', $idCorrida);
    }

    $taxaGateway = (float) ($corrida['taxa_gateway'] ?? 0);
    if ($taxaGateway <= 0 && isset($corrida['raw_response'])) {
        $rawResponse = is_array($corrida['raw_response'])
            ? $corrida['raw_response']
            : json_decode((string) $corrida['raw_response'], true);
        if (is_array($rawResponse)) {
            $taxaGateway = mp_taxa_gateway_de_pagamento($rawResponse);
        }
    }

    $valores = mp_corrida_valores(
        (float) ($corrida['valor'] ?? 0),
        (float) ($corrida['saldo_negativo_cobrado'] ?? 0),
        $taxaGateway
    );

    $stmt = $pdo->prepare(
        'INSERT INTO pagamentos_corridas
          (id_corrida, id_passageiro, id_motorista, ambiente, external_reference, metodo, status,
           valor_total, valor_motorista, valor_plataforma, taxa_gateway, application_fee, raw_request)
         VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           id_corrida = VALUES(id_corrida),
           id_passageiro = VALUES(id_passageiro),
           id_motorista = VALUES(id_motorista),
           ambiente = VALUES(ambiente),
           metodo = VALUES(metodo),
           status = IF(status IN ("aprovado", "cancelado", "estornado"), status, VALUES(status)),
           valor_total = VALUES(valor_total),
           valor_motorista = VALUES(valor_motorista),
           valor_plataforma = VALUES(valor_plataforma),
           taxa_gateway = VALUES(taxa_gateway),
           application_fee = VALUES(application_fee),
           raw_request = VALUES(raw_request)'
    );
    $stmt->execute([
        $idCorrida,
        (int) ($corrida['id_passageiro'] ?? 0) ?: null,
        (int) ($corrida['id_motorista'] ?? 0) ?: null,
        $config['ambiente'],
        $externalReference,
        $metodo,
        $status,
        $valores['valor_total'],
        $valores['valor_motorista'],
        $valores['valor_plataforma'],
        $valores['taxa_gateway'],
        $valores['application_fee'],
        json_encode([
            'observacao' => 'Registro local preparado para Mercado Pago Marketplace.',
            'marketplace_ativo' => $config['marketplace_ativo'],
        ], JSON_UNESCAPED_UNICODE),
    ]);

    $idPagamento = (int) $pdo->lastInsertId();
    if ($idPagamento <= 0) {
        $lookup = $pdo->prepare('SELECT id FROM pagamentos_corridas WHERE external_reference = ? LIMIT 1');
        $lookup->execute([$externalReference]);
        $idPagamento = (int) $lookup->fetchColumn();
    }

    $sets = [];
    $params = [];
    if (mp_column_exists($pdo, 'corridas', 'id_pagamento_gateway')) {
        $sets[] = 'id_pagamento_gateway = ?';
        $params[] = $idPagamento ?: null;
    }
    if (mp_column_exists($pdo, 'corridas', 'status_pagamento')) {
        $sets[] = 'status_pagamento = ?';
        $params[] = $status;
    }
    if (mp_column_exists($pdo, 'corridas', 'mp_external_reference')) {
        $sets[] = 'mp_external_reference = ?';
        $params[] = $externalReference;
    }
    if (mp_column_exists($pdo, 'corridas', 'valor_motorista_liquido')) {
        $sets[] = 'valor_motorista_liquido = ?';
        $params[] = $valores['valor_motorista'];
    }
    if (mp_column_exists($pdo, 'corridas', 'valor_plataforma_bruto')) {
        $sets[] = 'valor_plataforma_bruto = ?';
        $params[] = $valores['valor_plataforma_bruto'];
    }
    if (mp_column_exists($pdo, 'corridas', 'taxa_gateway')) {
        $sets[] = 'taxa_gateway = ?';
        $params[] = $valores['taxa_gateway'];
    }
    if ($sets) {
        $params[] = $idCorrida;
        $up = $pdo->prepare('UPDATE corridas SET ' . implode(', ', $sets) . ' WHERE id = ?');
        $up->execute($params);
    }

    return $idPagamento > 0 ? $idPagamento : null;
}

function mp_conta_usuario(PDO $pdo, int $idUsuario, string $tipoUsuario): ?array
{
    if (!mp_table_exists($pdo, 'mercado_pago_contas')) {
        return null;
    }

    $stmt = $pdo->prepare(
        'SELECT *
         FROM mercado_pago_contas
         WHERE id_usuario = ? AND tipo_usuario = ?
         LIMIT 1'
    );
    $stmt->execute([$idUsuario, $tipoUsuario]);
    $row = $stmt->fetch();

    return $row ?: null;
}

function mp_conta_publica(?array $conta): array
{
    if (!$conta) {
        return [
            'status' => 'nao_conectado',
            'modo' => 'sandbox',
            'conectado' => false,
        ];
    }

    return [
        'status' => (string) $conta['status'],
        'modo' => (string) $conta['modo'],
        'conectado' => (string) $conta['status'] === 'conectado',
        'mp_user_id' => (string) ($conta['mp_user_id'] ?? ''),
        'mp_email' => (string) ($conta['mp_email'] ?? ''),
        'mp_nickname' => (string) ($conta['mp_nickname'] ?? ''),
        'conectado_em' => $conta['conectado_em'] ?? null,
        'observacao' => (string) ($conta['observacao'] ?? ''),
    ];
}
