<?php
declare(strict_types=1);

require_once __DIR__ . '/../config/helpers.php';
require_once __DIR__ . '/../config/mercado_pago_helpers.php';

$data = input_json() + $_GET;
require_fields($data, ['id_corrida', 'id_motorista']);

$idCorrida = (int) $data['id_corrida'];
$idMotorista = (int) $data['id_motorista'];

if ($idCorrida <= 0 || $idMotorista <= 0) {
    json_fail('Dados invalidos para gerar Pix da corrida.');
}

function pix_finalizacao_row_payload(array $row): array
{
    $raw = json_decode((string) ($row['raw_response'] ?? ''), true);
    if (!is_array($raw)) {
        $raw = [];
    }

    return mp_pix_payload_publico($raw, $row);
}

try {
    $pdo = db();
    if (!mp_table_exists($pdo, 'pagamentos_corridas')) {
        json_fail('Tabela pagamentos_corridas nao existe. Rode a atualizacao do banco.', 500);
    }

    $stmt = $pdo->prepare(
        'SELECT c.id, c.id_passageiro, c.id_motorista, c.status, c.valor,
                COALESCE(c.saldo_negativo_cobrado, 0) AS saldo_negativo_cobrado,
                COALESCE(c.forma_pagamento, "dinheiro") AS forma_pagamento,
                COALESCE(c.forma_pagamento_detalhe, "dinheiro_pix") AS forma_pagamento_detalhe,
                p.nome AS passageiro_nome, p.email AS passageiro_email
         FROM corridas c
         LEFT JOIN usuarios p ON p.id = c.id_passageiro
         WHERE c.id = ?
         LIMIT 1'
    );
    $stmt->execute([$idCorrida]);
    $corrida = $stmt->fetch();
    if (!$corrida) {
        json_fail('Corrida nao encontrada.', 404);
    }
    if ((int) ($corrida['id_motorista'] ?? 0) !== $idMotorista) {
        json_fail('Essa corrida nao pertence a este motorista.', 403);
    }
    if (($corrida['status'] ?? '') !== 'em_andamento') {
        json_fail('Pix disponivel somente com a viagem em andamento.', 409);
    }

    $externalReference = 'BULO-CORRIDA-PIX-FINAL-' . $idCorrida;
    $existing = $pdo->prepare(
        'SELECT *
         FROM pagamentos_corridas
         WHERE external_reference = ?
            OR (id_corrida = ? AND metodo = "pix_online" AND status IN ("criado", "pendente", "autorizado", "aprovado"))
         ORDER BY id DESC
         LIMIT 1'
    );
    $existing->execute([$externalReference, $idCorrida]);
    $row = $existing->fetch();
    if ($row && in_array((string) $row['status'], ['pendente', 'autorizado', 'aprovado'], true)) {
        json_ok(['pagamento' => pix_finalizacao_row_payload($row)]);
    }

    $accessToken = mp_access_token_plataforma($pdo);
    $config = mp_config($pdo);
    $valor = mp_money((float) ($corrida['valor'] ?? 0));
    if ($valor <= 0) {
        json_fail('Valor da corrida invalido para Pix.');
    }

    $payerEmail = trim((string) ($corrida['passageiro_email'] ?? ''));
    if ($payerEmail === '') {
        $payerEmail = 'passageiro' . (int) $corrida['id_passageiro'] . '@bulo.local';
    }

    $request = [
        'transaction_amount' => $valor,
        'description' => 'Bulo - corrida #' . $idCorrida,
        'payment_method_id' => 'pix',
        'external_reference' => $externalReference,
        'payer' => [
            'email' => $payerEmail,
            'first_name' => trim((string) ($corrida['passageiro_nome'] ?? 'Passageiro')) ?: 'Passageiro',
        ],
    ];

    $webhookUrl = trim(mp_config_valor($pdo, 'mp_webhook_url'));
    $webhookHost = parse_url($webhookUrl, PHP_URL_HOST);
    $webhookPrivado = !$webhookHost
        || in_array($webhookHost, ['localhost', '127.0.0.1'], true)
        || str_starts_with((string) $webhookHost, '192.168.')
        || str_starts_with((string) $webhookHost, '10.')
        || preg_match('/^172\.(1[6-9]|2\d|3[0-1])\./', (string) $webhookHost);
    if ($webhookUrl !== '' && !$webhookPrivado) {
        $request['notification_url'] = $webhookUrl;
    }

    $response = mp_http_json_request(
        'POST',
        'https://api.mercadopago.com/v1/payments',
        ['Authorization: Bearer ' . $accessToken],
        $request,
        'bulo-corrida-pix-final-' . $idCorrida
    );

    $status = mp_status_pagamento_local((string) ($response['status'] ?? 'pending'));
    $mpPaymentId = (string) ($response['id'] ?? '');
    $valores = mp_corrida_valores(
        $valor,
        (float) ($corrida['saldo_negativo_cobrado'] ?? 0),
        mp_taxa_gateway_de_pagamento($response)
    );

    $ins = $pdo->prepare(
        'INSERT INTO pagamentos_corridas
          (id_corrida, id_passageiro, id_motorista, ambiente, external_reference, mp_payment_id, metodo, status,
           valor_total, valor_motorista, valor_plataforma, taxa_gateway, application_fee, raw_request, raw_response)
         VALUES (?, ?, ?, ?, ?, ?, "pix_online", ?, ?, ?, ?, ?, ?, ?, ?)
         ON DUPLICATE KEY UPDATE
           mp_payment_id = VALUES(mp_payment_id),
           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),
           raw_response = VALUES(raw_response),
           atualizado_em = CURRENT_TIMESTAMP'
    );
    $ins->execute([
        $idCorrida,
        (int) $corrida['id_passageiro'],
        $idMotorista,
        $config['ambiente'],
        $externalReference,
        $mpPaymentId !== '' ? $mpPaymentId : null,
        $status,
        $valores['valor_total'],
        $valores['valor_motorista'],
        $valores['valor_plataforma'],
        $valores['taxa_gateway'],
        $valores['application_fee'],
        json_encode($request, JSON_UNESCAPED_UNICODE),
        json_encode($response, 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();
    }

    $up = $pdo->prepare(
        'UPDATE corridas
         SET id_pagamento_gateway = ?,
             status_pagamento = ?,
             mp_payment_id = ?,
             mp_external_reference = ?,
             valor_motorista_liquido = ?,
             valor_plataforma_bruto = ?,
             taxa_gateway = ?
         WHERE id = ?'
    );
    $up->execute([
        $idPagamento ?: null,
        $status,
        $mpPaymentId !== '' ? $mpPaymentId : null,
        $externalReference,
        $valores['valor_motorista'],
        $valores['valor_plataforma_bruto'],
        $valores['taxa_gateway'],
        $idCorrida,
    ]);

    $row = [
        'id' => $idPagamento,
        'external_reference' => $externalReference,
        'mp_payment_id' => $mpPaymentId,
        'valor_total' => $valores['valor_total'],
        'status' => $status,
    ];

    json_ok(['pagamento' => mp_pix_payload_publico($response, $row)]);
} catch (Throwable $e) {
    json_fail(
        mp_gateway_exception_message($e, 'Erro ao gerar Pix da corrida.'),
        $e instanceof MercadoPagoApiException ? 422 : 500,
        mp_gateway_exception_payload($e)
    );
}
