<?php
/**
 * TechShop Perú - Endpoint: Confirmar pago PayPal (server-side)
 *
 * SEGURIDAD (Crítico):
 * Antes de crear el pedido, la orden se CAPTURA y VERIFICA contra la API de
 * PayPal (Orders v2 / capture). Si PayPal no confirma el pago, o el monto no
 * coincide con el total calculado en el servidor, el pedido NO se crea y se
 * devuelve un error genérico (sin exponer detalles internos).
 *
 * @package TechShop Perú
 * @version 2.0
 */

define('SECURE_ACCESS', true);
require_once __DIR__ . '/../includes/config.php';
require_once __DIR__ . '/../includes/database.php';
require_once __DIR__ . '/../includes/functions.php';
require_once __DIR__ . '/../includes/paypal.php';
require_once __DIR__ . '/../includes/mail_functions.php';

header('Content-Type: application/json; charset=utf-8');

/** Devuelve JSON y termina la ejecución. */
function paypal_json(array $data): void
{
    echo json_encode($data);
    exit;
}

// ── Validaciones básicas ───────────────────────────────────────────────
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    paypal_json(['success' => false, 'message' => 'Método no permitido.']);
}

if (!is_logged_in()) {
    paypal_json(['success' => false, 'message' => 'No autorizado.']);
}

// Verificación CSRF (el token viaja en el JSON del body)
$input = json_decode(file_get_contents('php://input'), true);
if (!is_array($input) || empty($input['csrf_token']) || !hash_equals($_SESSION['csrf_token'] ?? '', (string) $input['csrf_token'])) {
    paypal_json(['success' => false, 'message' => 'Token de seguridad inválido. Recarga la página e inténtalo de nuevo.']);
}

$orderId = trim((string) ($input['paypal_order_id'] ?? ''));
// Los IDs de orden de PayPal son alfanuméricos (aprox. 17 caracteres)
if (!preg_match('/^[A-Za-z0-9]+$/', $orderId) || strlen($orderId) < 10 || strlen($orderId) > 40) {
    paypal_json(['success' => false, 'message' => 'Identificador de orden de PayPal inválido.']);
}

// ── Configuración de PayPal ────────────────────────────────────────────
$paypalClientId = defined('PAYPAL_CLIENT_ID') ? PAYPAL_CLIENT_ID : '';
$paypalClientSecret = defined('PAYPAL_CLIENT_SECRET') ? PAYPAL_CLIENT_SECRET : '';

if ($paypalClientId === '' || $paypalClientSecret === '') {
    paypal_json(['success' => false, 'message' => 'El pago con PayPal no está configurado. Contacta al administrador.']);
}

$paypalMode = (defined('PAYPAL_MODE') && in_array(strtolower((string) PAYPAL_MODE), ['live', 'sandbox'], true))
    ? strtolower((string) PAYPAL_MODE)
    : 'sandbox';

$db = db();
$usuario_id = (int) $_SESSION['usuario_id'];

// ── Obtener ítems del carrito ──────────────────────────────────────────
$stmt = $db->prepare('
    SELECT c.cantidad, p.id AS producto_id, p.nombre, p.precio, p.precio_oferta, p.stock
    FROM carrito c
    JOIN productos p ON c.producto_id = p.id
    WHERE c.usuario_id = ? AND p.activo = 1
');
$stmt->execute([$usuario_id]);
$items = $stmt->fetchAll();

if (empty($items)) {
    paypal_json(['success' => false, 'message' => 'El carrito está vacío.']);
}

// ── Calcular totales (mismo criterio que checkout.php) ────────────────
$subtotal = 0;
foreach ($items as $it) {
    $subtotal += precio_final($it) * (int) $it['cantidad'];
}

$cuponDescuento = 0;
$cuponCodigo = null;
if (!empty($_SESSION['cupon']) && $subtotal > 0) {
    $cupon = $_SESSION['cupon'];
    $cuponCodigo = $cupon['codigo'];
    $cuponDescuento = $cupon['tipo'] === 'porcentaje'
        ? round(($subtotal * $cupon['valor']) / 100, 2)
        : min((float) $cupon['valor'], $subtotal);
}
$subtotalConDescuento = max(0, $subtotal - $cuponDescuento);

$departamento = sanitize($input['departamento'] ?? 'Lima');
$ciudad       = sanitize($input['ciudad'] ?? 'Lima');
$direccion    = sanitize($input['direccion'] ?? 'Dirección no especificada');
$tipo_comprobante = in_array($input['tipo_comprobante'] ?? 'boleta', ['boleta', 'factura'], true) ? $input['tipo_comprobante'] : 'boleta';
$num_documento = sanitize($input['num_documento'] ?? '12345678');
$razon_social = sanitize($input['razon_social'] ?? '');
$notas        = sanitize($input['notas'] ?? '');

// El frontend cobra envío fijo de 15.00 (equivalente USD) — mantener coherencia
$envio = 15.00;
$igv_porcentaje = defined('IGV_PORCENTAJE') ? (float) IGV_PORCENTAJE : 18;
$igv = round($subtotalConDescuento * ($igv_porcentaje / 100), 2);
$total = $subtotalConDescuento + $envio;

// Monto esperado en USD (mismo cálculo que el frontend: soles / 3.75)
$expectedUsd = paypal_usd_amount($subtotalConDescuento + $envio);

// ── VERIFICAR EL PAGO CON PAYPAL ANTES DE CREAR EL PEDIDO ─────────────
try {
    $paypal = new PayPalClient(PAYPAL_CLIENT_ID, PAYPAL_CLIENT_SECRET, $paypalMode);

    try {
        // Intento de captura server-side.
        $capture = $paypal->verifyCapture($paypal->captureOrder($orderId));
    } catch (Throwable $captureEx) {
        // Defensa en profundidad: si la captura directa no fue posible (p. ej.
        // la orden ya fue capturada antes por un reintento), verificar la orden
        // existente en PayPal para confirmar que SÍ hay un cobro completado.
        error_log('PayPal: captura directa falló, verificando orden existente: ' . $captureEx->getMessage());
        $capture = $paypal->verifyOrder($orderId);
    }

    if ($capture['currency'] !== 'USD' || !paypal_amount_matches($capture['amount'], $expectedUsd)) {
        error_log("PayPal: monto no coincide. Esperado USD {$expectedUsd}, capturado {$capture['amount']} {$capture['currency']} (orden {$orderId}, usuario {$usuario_id})");
        paypal_json(['success' => false, 'message' => 'El monto confirmado por PayPal no coincide con el total del pedido. Contacta a soporte.']);
    }
} catch (Throwable $e) {
    error_log('PayPal verify error: ' . $e->getMessage());
    paypal_json(['success' => false, 'message' => 'No pudimos confirmar el pago con PayPal. Inténtalo nuevamente o usa otro método de pago.']);
}

// ── Crear pedido (solo si PayPal confirmó el pago) ─────────────────────
$numero_pedido = 'PED-' . strtoupper(bin2hex(random_bytes(4)));

try {
    $db->beginTransaction();

    $stmt = $db->prepare('
        INSERT INTO pedidos
        (usuario_id, numero_pedido, estado, tipo_comprobante, num_documento, razon_social, subtotal, descuento, igv, envio, total, direccion_envio, ciudad_envio, departamento_envio, metodo_pago, voucher_imagen, cupon_codigo, notas)
        VALUES (?, ?, "confirmado", ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, "paypal", ?, ?, ?)
    ');
    $stmt->execute([
        $usuario_id,
        $numero_pedido,
        $tipo_comprobante,
        $num_documento,
        $razon_social,
        $subtotal,
        $cuponDescuento,
        $igv,
        $envio,
        $total,
        $direccion,
        $ciudad,
        $departamento,
        'PayPal Capture: ' . $capture['capture_id'],
        $cuponCodigo,
        $notas
    ]);

    $pedido_id = $db->lastInsertId();

    $stmtDetalle = $db->prepare('
        INSERT INTO detalles_pedido
        (pedido_id, producto_id, nombre_producto, precio_unitario, cantidad, subtotal)
        VALUES (?, ?, ?, ?, ?, ?)
    ');

    foreach ($items as $it) {
        $precioFinal = precio_final($it);
        $subTotalItem = $precioFinal * (int) $it['cantidad'];
        $stmtDetalle->execute([
            $pedido_id,
            $it['producto_id'],
            $it['nombre'],
            $precioFinal,
            $it['cantidad'],
            $subTotalItem
        ]);

        $db->prepare('UPDATE productos SET stock = GREATEST(0, stock - ?) WHERE id = ?')->execute([$it['cantidad'], $it['producto_id']]);
    }

    $db->prepare('DELETE FROM carrito WHERE usuario_id = ?')->execute([$usuario_id]);
    unset($_SESSION['cupon']);

    if ($cuponCodigo) {
        $db->prepare('UPDATE cupones SET usos_actuales = usos_actuales + 1 WHERE codigo = ?')->execute([$cuponCodigo]);
    }

    $db->commit();

    // Enviar correo de confirmación (no bloqueante / no crítico)
    try {
        send_order_confirmation_email($pedido_id);
    } catch (Throwable $mailEx) {
        error_log('Error no crítico al enviar correo PayPal: ' . $mailEx->getMessage());
    }

    paypal_json([
        'success'   => true,
        'pedido_id' => $pedido_id,
        'redirect'  => url('pages/checkout.php?exito=' . $numero_pedido)
    ]);

} catch (Throwable $e) {
    if ($db->inTransaction()) {
        $db->rollBack();
    }
    error_log('Error al registrar pedido PayPal (usuario ' . $usuario_id . '): ' . $e->getMessage());
    paypal_json(['success' => false, 'message' => 'Ocurrió un error al registrar el pedido. No se ha cobrado nada adicional. Contacta a soporte.']);
}
