<?php
declare(strict_types=1);
require_once dirname(__FILE__) . '/../config.php';

/**
 * POST /voucher/apply.php
 * Aplica una lista de vouchers a una transacción ya creada.
 *
 * Por cada voucher:
 *  - Descuenta el monto_aplicado del campo 'restante'
 *  - Si restante queda en 0 → status = 1 (agotado)
 *  - Si restante queda > 0  → status = 0 (sigue activo)
 *  - Agrega el id de la transacción en 'observaciones'
 *  - Registra el pago en depositos_transaccion con tipo=5
 *
 * Body JSON:
 * {
 *   "idtransacciones": 380835,
 *   "vouchers": [
 *     { "idv": 123, "monto_aplicado": 200 },
 *     { "idv": 124, "monto_aplicado": 150 }
 *   ]
 * }
 *
 * Respuesta OK:
 * { "success": true, "data": { "aplicados": 2 } }
 */

if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
    jsonErr(405, 'Método no permitido.');
}

$body          = json_decode(file_get_contents('php://input'), true) ?? [];
$idTransaccion = isset($body['idtransacciones']) ? (int)$body['idtransacciones'] : 0;
$vouchers      = $body['vouchers'] ?? [];

if ($idTransaccion <= 0) jsonErr(400, 'idtransacciones inválido.');
if (empty($vouchers))    jsonErr(400, 'No se proporcionaron vouchers.');

try {
    $db = getDB();
    $aplicados = 0;

    foreach ($vouchers as $v) {
        $idv         = isset($v['idv'])            ? (int)$v['idv']            : 0;
        $montoAplica = isset($v['monto_aplicado']) ? (float)$v['monto_aplicado'] : 0;

        if ($idv <= 0 || $montoAplica <= 0) continue;

        $db->beginTransaction();

        // Leer el voucher con bloqueo para evitar condiciones de carrera
        $stmtRead = $db->prepare(
            'SELECT idv, restante, status, observaciones
             FROM voucher
             WHERE idv = ? AND status = 0 AND restante > 0
             FOR UPDATE'
        );
        $stmtRead->execute([$idv]);
        $row = $stmtRead->fetch();

        if (!$row) {
            $db->rollBack();
            continue; // Voucher ya no válido — saltar
        }

        $restanteActual = (float)$row['restante'];
        $nuevoRestante  = round(max(0, $restanteActual - $montoAplica), 2);
        $nuevoStatus    = ($nuevoRestante <= 0) ? 1 : 0;

        // Construir observaciones: agregar id de transacción
        $obsActual = trim((string)($row['observaciones'] ?? ''));
        $obsNueva  = $obsActual !== ''
            ? $obsActual . ', TX' . $idTransaccion
            : 'TX' . $idTransaccion;
        // Truncar a 50 chars (límite de la columna)
        if (strlen($obsNueva) > 50) {
            $obsNueva = substr($obsNueva, -50);
        }

        // 1. Actualizar el voucher
        $stmtUpd = $db->prepare(
            'UPDATE voucher
             SET restante = ?, status = ?, observaciones = ?, fecha_mod = NOW()
             WHERE idv = ?'
        );
        $stmtUpd->execute([$nuevoRestante, $nuevoStatus, $obsNueva, $idv]);

        // 2. Registrar el pago en depositos_transaccion (tipo=4 = voucher)
        $stmtDep = $db->prepare(
            'INSERT INTO depositos_transaccion
             (idtransacciones, id_voucher, tipo, monto, folio, idbanco, fecha)
             VALUES (?, ?, 4, ?, ?, 0, NOW())'
        );
        $stmtDep->execute([$idTransaccion, $idv, $montoAplica, (string)$idv]);

        // 3. Registrar en asignavoucher
        $stmtAsig = $db->prepare(
            'INSERT INTO asignavoucher (idv, idtransacciones, efectivo) VALUES (?, ?, ?)'
        );
        $stmtAsig->execute([$idv, $idTransaccion, $montoAplica]);

        $db->commit();
        $aplicados++;
    }

    jsonOk(['aplicados' => $aplicados]);

} catch (Throwable $e) {
    if (isset($db) && $db->inTransaction()) {
        $db->rollBack();
    }
    http_response_code(500);
    echo json_encode(['success' => false, 'message' => 'Error interno: ' . $e->getMessage()], JSON_UNESCAPED_UNICODE);
    exit;
}
