<?php
declare(strict_types=1);

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

const CORRIDA_PERCENTUAL_MOTORISTA = 0.85;

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

$idCorrida = (int) $data['id_corrida'];
$idMotorista = (int) $data['id_motorista'];
$pagamentoPixFinalizacao = !empty($data['pagamento_pix_finalizacao']);

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

try {
    $pdo = db();
    $pdo->beginTransaction();

    $selectSaldoNegativo = corrida_schema_column_exists($pdo, 'corridas', 'saldo_negativo_cobrado')
        ? 'saldo_negativo_cobrado'
        : '0 AS saldo_negativo_cobrado';
    $selectFormaPagamento = corrida_schema_column_exists($pdo, 'corridas', 'forma_pagamento')
        ? 'forma_pagamento'
        : '"dinheiro" AS forma_pagamento';
    $selectFormaPagamentoDetalhe = corrida_schema_column_exists($pdo, 'corridas', 'forma_pagamento_detalhe')
        ? 'forma_pagamento_detalhe'
        : 'NULL AS forma_pagamento_detalhe';
    $selectPagamentoGateway = corrida_schema_column_exists($pdo, 'corridas', 'id_pagamento_gateway')
        ? 'id_pagamento_gateway'
        : 'NULL AS id_pagamento_gateway';
    $selectStatusPagamento = corrida_schema_column_exists($pdo, 'corridas', 'status_pagamento')
        ? 'status_pagamento'
        : '"nao_aplicavel" AS status_pagamento';
    $selectMpPayment = corrida_schema_column_exists($pdo, 'corridas', 'mp_payment_id')
        ? 'mp_payment_id'
        : 'NULL AS mp_payment_id';
    $selectMpExternal = corrida_schema_column_exists($pdo, 'corridas', 'mp_external_reference')
        ? 'mp_external_reference'
        : 'NULL AS mp_external_reference';
    $stmt = $pdo->prepare(
        'SELECT id, id_passageiro, id_motorista, status, valor, ' . $selectSaldoNegativo . ',
                ' . $selectFormaPagamento . ', ' . $selectFormaPagamentoDetalhe . ',
                ' . $selectPagamentoGateway . ', ' . $selectStatusPagamento . ',
                ' . $selectMpPayment . ', ' . $selectMpExternal . '
         FROM corridas
         WHERE id = ?
         LIMIT 1
         FOR UPDATE'
    );
    $stmt->execute([$idCorrida]);
    $corrida = $stmt->fetch();

    if (!$corrida) {
        $pdo->rollBack();
        json_fail('Corrida nao encontrada.', 404);
    }

    if ((int) ($corrida['id_motorista'] ?? 0) !== $idMotorista) {
        $pdo->rollBack();
        json_fail('Essa corrida nao pertence a este motorista.', 403);
    }

    if (($corrida['status'] ?? '') === 'finalizada') {
        $pdo->commit();
        json_ok(['already_finalizada' => true]);
    }

    if (($corrida['status'] ?? '') !== 'em_andamento') {
        $pdo->rollBack();
        json_fail('Corrida nao pode ser finalizada neste estado.', 409);
    }

    $pagamentoPix = null;
    if ($pagamentoPixFinalizacao) {
        $pixStmt = $pdo->prepare(
            'SELECT *
             FROM pagamentos_corridas
             WHERE id_corrida = ?
               AND metodo = "pix_online"
               AND status = "aprovado"
             ORDER BY id DESC
             LIMIT 1'
        );
        $pixStmt->execute([$idCorrida]);
        $pagamentoPix = $pixStmt->fetch();
        if (!$pagamentoPix) {
            $pdo->rollBack();
            json_fail('Pagamento Pix ainda nao aprovado para finalizar a corrida.', 409);
        }
    }

    $sets = ['status = "finalizada"', 'finalizada_em = NOW()'];
    $params = [];
    if ($pagamentoPixFinalizacao && $pagamentoPix) {
        if (corrida_schema_column_exists($pdo, 'corridas', 'forma_pagamento')) {
            $sets[] = 'forma_pagamento = "online"';
        }
        if (corrida_schema_column_exists($pdo, 'corridas', 'forma_pagamento_detalhe')) {
            $sets[] = 'forma_pagamento_detalhe = "pix_online"';
        }
        if (corrida_schema_column_exists($pdo, 'corridas', 'id_pagamento_gateway')) {
            $sets[] = 'id_pagamento_gateway = ?';
            $params[] = (int) $pagamentoPix['id'];
        }
        if (corrida_schema_column_exists($pdo, 'corridas', 'status_pagamento')) {
            $sets[] = 'status_pagamento = "aprovado"';
        }
        if (corrida_schema_column_exists($pdo, 'corridas', 'mp_payment_id')) {
            $sets[] = 'mp_payment_id = ?';
            $params[] = $pagamentoPix['mp_payment_id'] ?: null;
        }
        if (corrida_schema_column_exists($pdo, 'corridas', 'mp_external_reference')) {
            $sets[] = 'mp_external_reference = ?';
            $params[] = $pagamentoPix['external_reference'] ?: null;
        }
    }
    $params[] = $idCorrida;
    $up = $pdo->prepare('UPDATE corridas SET ' . implode(', ', $sets) . ' WHERE id = ?');
    $up->execute($params);

    $valor = (float) ($corrida['valor'] ?? 0);
    $saldoNegativoCobrado = round((float) ($corrida['saldo_negativo_cobrado'] ?? 0), 2);
    $valorBaseMotorista = max(0.0, $valor - $saldoNegativoCobrado);
    $valorMotorista = round($valorBaseMotorista * CORRIDA_PERCENTUAL_MOTORISTA, 2);
    $formaPagamentoFinal = $pagamentoPixFinalizacao ? 'online' : (string) ($corrida['forma_pagamento'] ?? 'dinheiro');
    $formaPagamentoDetalheFinal = $pagamentoPixFinalizacao ? 'pix_online' : (string) ($corrida['forma_pagamento_detalhe'] ?? '');
    mp_registrar_pagamento_corrida($pdo, [
        'id' => $idCorrida,
        'id_passageiro' => (int) $corrida['id_passageiro'],
        'id_motorista' => $idMotorista,
        'valor' => $valor,
        'saldo_negativo_cobrado' => $saldoNegativoCobrado,
        'forma_pagamento' => $formaPagamentoFinal,
        'forma_pagamento_detalhe' => $formaPagamentoDetalheFinal,
        'mp_external_reference' => $pagamentoPix['external_reference'] ?? (string) ($corrida['mp_external_reference'] ?? ''),
        'taxa_gateway' => (float) ($pagamentoPix['taxa_gateway'] ?? 0),
        'raw_response' => $pagamentoPix['raw_response'] ?? null,
    ], $pagamentoPixFinalizacao ? 'aprovado' : 'pendente');
    $ins = $pdo->prepare(
        'INSERT INTO ganhos_diarios (id_motorista, data_ref, total_corridas, total_valor)
         VALUES (?, CURDATE(), 1, ?)
         ON DUPLICATE KEY UPDATE
           total_corridas = total_corridas + 1,
           total_valor = total_valor + VALUES(total_valor),
           atualizado_em = CURRENT_TIMESTAMP'
    );
    $ins->execute([$idMotorista, $valorMotorista]);

    if ($saldoNegativoCobrado > 0 && corrida_table_exists($pdo, 'passageiro_carteira_movimentos')) {
        $carteira = $pdo->prepare(
            'INSERT INTO passageiro_carteira_movimentos
              (id_passageiro, id_corrida, tipo, origem, valor, descricao, status)
             VALUES (?, ?, "credito", "corrida", ?, ?, "confirmado")'
        );
        $carteira->execute([
            (int) $corrida['id_passageiro'],
            $idCorrida,
            $saldoNegativoCobrado,
            'Cobranca de saldo negativo na corrida #' . $idCorrida,
        ]);
    }

    corrida_evento_registrar($pdo, $idCorrida, 'viagem_finalizada', $idMotorista, 'motorista', 'em_andamento', 'finalizada', null, null, [
        'valor' => $valor,
        'valor_motorista' => $valorMotorista,
        'saldo_negativo_cobrado' => $saldoNegativoCobrado,
        'pagamento_pix_finalizacao' => $pagamentoPixFinalizacao,
    ]);
    motorista_metricas_corridas_recalcular($pdo, $idMotorista);

    $pdo->commit();
    json_ok([
        'valor' => $valor,
        'valor_motorista' => $valorMotorista,
        'saldo_negativo_cobrado' => $saldoNegativoCobrado,
        'finalizada_em' => date('Y-m-d H:i:s'),
    ]);
} catch (Throwable $e) {
    if (isset($pdo) && $pdo->inTransaction()) {
        $pdo->rollBack();
    }
    json_fail('Erro ao finalizar corrida.', 500, ['error' => $e->getMessage()]);
}
