<?php
if (!defined('BASEPATH')) exit('No direct script access allowed');

$user = requireAuth();

switch ($tipo) {
    case 'getPedidos':
        try {
            $page = max(1, intval($datapost['page'] ?? $_GET['page'] ?? 1));
            $limit = max(1, min(100, intval($datapost['limit'] ?? $_GET['limit'] ?? 20)));
            $offset = ($page - 1) * $limit;

            $estado = trim($datapost['estado'] ?? $_GET['estado'] ?? '');
            $fecha_inicio = $datapost['fecha_inicio'] ?? $_GET['fecha_inicio'] ?? '';
            $fecha_fin = $datapost['fecha_fin'] ?? $_GET['fecha_fin'] ?? '';

            $where = "WHERE v.usuario_id = ?";
            $params = [$user['id']];
            $types = "i";

            if (!empty($estado)) {
                $where .= " AND v.estado = ?";
                $params[] = $estado;
                $types .= "s";
            }

            if (!empty($fecha_inicio)) {
                $where .= " AND DATE(v.fecha_creacion) >= ?";
                $params[] = $fecha_inicio;
                $types .= "s";
            }

            if (!empty($fecha_fin)) {
                $where .= " AND DATE(v.fecha_creacion) <= ?";
                $params[] = $fecha_fin;
                $types .= "s";
            }

            // Contar total
            $countQuery = "SELECT COUNT(*) as total FROM ventas v $where";
            $countStmt = $conn->prepare($countQuery);
            $countStmt->bind_param($types, ...$params);
            $countStmt->execute();
            $total = $countStmt->get_result()->fetch_assoc()['total'];

            // Obtener pedidos
            $query = "SELECT
                v.id,
                v.folio,
                v.cliente_id,
                v.cliente_nombre,
                v.subtotal,
                v.impuesto,
                v.descuento,
                v.total,
                v.metodo_pago,
                v.estatus_pago,
                v.saldo_pendiente,
                v.tipo_entrega,
                v.direccion_entrega,
                v.estado,
                v.observaciones,
                v.fecha_creacion,
                COUNT(vd.id) as total_productos
            FROM ventas v
            LEFT JOIN venta_detalles vd ON v.id = vd.venta_id
            $where
            GROUP BY v.id
            ORDER BY v.fecha_creacion DESC
            LIMIT ? OFFSET ?";

            $params[] = $limit;
            $params[] = $offset;
            $types .= "ii";

            $stmt = $conn->prepare($query);
            $stmt->bind_param($types, ...$params);
            $stmt->execute();
            $result = $stmt->get_result();

            $pedidos = [];
            while ($row = $result->fetch_assoc()) {
                $pedidos[] = [
                    'id' => intval($row['id']),
                    'folio' => $row['folio'],
                    'cliente_id' => $row['cliente_id'] ? intval($row['cliente_id']) : null,
                    'cliente_nombre' => $row['cliente_nombre'] ?? 'Cliente General',
                    'subtotal' => floatval($row['subtotal']),
                    'impuesto' => floatval($row['impuesto']),
                    'descuento' => floatval($row['descuento']),
                    'total' => floatval($row['total']),
                    'metodo_pago' => $row['metodo_pago'],
                    'estatus_pago' => $row['estatus_pago'],
                    'saldo_pendiente' => floatval($row['saldo_pendiente'] ?? 0),
                    'tipo_entrega' => $row['tipo_entrega'],
                    'direccion_entrega' => $row['direccion_entrega'],
                    'estado' => $row['estado'],
                    'observaciones' => $row['observaciones'],
                    'total_productos' => intval($row['total_productos']),
                    'fecha_creacion' => $row['fecha_creacion']
                ];
            }

            sendPaginatedResponse(true, "Pedidos obtenidos", $pedidos, $total, $page, $limit);

        } catch (Exception $e) {
            sendResponse(false, "Error al obtener pedidos: " . $e->getMessage());
        }
        break;

    case 'getPedido':
        $id = intval($datapost['id'] ?? $_GET['id'] ?? 0);

        if ($id <= 0) {
            sendResponse(false, "ID de pedido requerido");
        }

        try {
            $query = "SELECT
                v.id, v.folio, v.cliente_id, v.cliente_nombre, v.usuario_id, v.usuario_nombre,
                v.subtotal, v.impuesto, v.descuento, v.total, v.metodo_pago, v.estatus_pago,
                v.saldo_pendiente, v.tipo_entrega, v.direccion_entrega, v.estado, v.observaciones,
                v.aplica_comision, v.comision_porcentaje, v.comision_monto,
                v.fecha_creacion, v.fecha_actualizacion
            FROM ventas v WHERE v.id = ?";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("i", $id);
            $stmt->execute();
            $result = $stmt->get_result();

            if ($row = $result->fetch_assoc()) {
                // Obtener detalles
                $detallesQuery = "SELECT
                    vd.id, vd.producto_id, vd.producto_nombre, vd.cantidad,
                    vd.precio_unitario, vd.subtotal, vd.impuesto, vd.descuento, vd.total,
                    vd.precio_tipo, vd.cantidad_escaneada, vd.estatus_preparacion,
                    p.codigo_corto, p.codigo_barras, p.almacen_id, a.nombre as almacen_nombre
                FROM venta_detalles vd
                LEFT JOIN productos p ON vd.producto_id = p.id
                LEFT JOIN almacenes a ON p.almacen_id = a.id
                WHERE vd.venta_id = ?
                ORDER BY vd.id ASC";

                $detStmt = $conn->prepare($detallesQuery);
                $detStmt->bind_param("i", $id);
                $detStmt->execute();
                $detResult = $detStmt->get_result();

                $detalles = [];
                while ($det = $detResult->fetch_assoc()) {
                    $detalles[] = [
                        'id' => intval($det['id']),
                        'producto_id' => intval($det['producto_id']),
                        'producto_nombre' => $det['producto_nombre'],
                        'codigo_corto' => $det['codigo_corto'],
                        'codigo_barras' => $det['codigo_barras'],
                        'almacen_id' => $det['almacen_id'] ? intval($det['almacen_id']) : null,
                        'almacen_nombre' => $det['almacen_nombre'],
                        'cantidad' => floatval($det['cantidad']),
                        'precio_unitario' => floatval($det['precio_unitario']),
                        'subtotal' => floatval($det['subtotal']),
                        'impuesto' => floatval($det['impuesto']),
                        'descuento' => floatval($det['descuento']),
                        'total' => floatval($det['total']),
                        'precio_tipo' => $det['precio_tipo'],
                        'cantidad_escaneada' => intval($det['cantidad_escaneada']),
                        'estatus_preparacion' => $det['estatus_preparacion']
                    ];
                }

                // Obtener pagos registrados
                $pagos = [];
                $pagosQuery = "SELECT id, monto, metodo_pago, referencia, fecha_creacion
                              FROM venta_pagos WHERE venta_id = ? ORDER BY fecha_creacion ASC";
                $pagosStmt = $conn->prepare($pagosQuery);
                if ($pagosStmt) {
                    $pagosStmt->bind_param("i", $id);
                    $pagosStmt->execute();
                    $pagosResult = $pagosStmt->get_result();
                    while ($pago = $pagosResult->fetch_assoc()) {
                        $pagos[] = [
                            'id' => intval($pago['id']),
                            'monto' => floatval($pago['monto']),
                            'metodo_pago' => $pago['metodo_pago'],
                            'referencia' => $pago['referencia'],
                            'fecha_creacion' => $pago['fecha_creacion']
                        ];
                    }
                }

                $pedido = [
                    'id' => intval($row['id']),
                    'folio' => $row['folio'],
                    'cliente_id' => $row['cliente_id'] ? intval($row['cliente_id']) : null,
                    'cliente_nombre' => $row['cliente_nombre'] ?? 'Cliente General',
                    'usuario_id' => intval($row['usuario_id']),
                    'usuario_nombre' => $row['usuario_nombre'],
                    'subtotal' => floatval($row['subtotal']),
                    'impuesto' => floatval($row['impuesto']),
                    'descuento' => floatval($row['descuento']),
                    'total' => floatval($row['total']),
                    'metodo_pago' => $row['metodo_pago'],
                    'estatus_pago' => $row['estatus_pago'],
                    'saldo_pendiente' => floatval($row['saldo_pendiente'] ?? 0),
                    'tipo_entrega' => $row['tipo_entrega'],
                    'direccion_entrega' => $row['direccion_entrega'],
                    'estado' => $row['estado'],
                    'observaciones' => $row['observaciones'],
                    'aplica_comision' => intval($row['aplica_comision'] ?? 0),
                    'comision_porcentaje' => floatval($row['comision_porcentaje'] ?? 0),
                    'comision_monto' => floatval($row['comision_monto'] ?? 0),
                    'detalles' => $detalles,
                    'pagos' => $pagos,
                    'fecha_creacion' => $row['fecha_creacion'],
                    'fecha_actualizacion' => $row['fecha_actualizacion']
                ];

                sendResponse(true, "Pedido obtenido exitosamente", $pedido);
            } else {
                sendResponse(false, "Pedido no encontrado");
            }

        } catch (Exception $e) {
            sendResponse(false, "Error al obtener pedido: " . $e->getMessage());
        }
        break;

    case 'crearPedido':
        $cliente_id = isset($datapost['cliente_id']) && $datapost['cliente_id'] ? intval($datapost['cliente_id']) : null;
        $cliente_nombre = trim($datapost['cliente_nombre'] ?? 'Cliente General');
        $metodo_pago = isset($datapost['metodo_pago']) ? $datapost['metodo_pago'] : null;
        $estatus_pago = $datapost['estatus_pago'] ?? 'pendiente';
        $tipo_entrega = $datapost['tipo_entrega'] ?? 'domicilio';
        $direccion_entrega = trim($datapost['direccion_entrega'] ?? '');
        $observaciones = trim($datapost['observaciones'] ?? '');
        $productos = $datapost['productos'] ?? [];

        $aplica_comision = isset($datapost['aplica_comision']) ? intval($datapost['aplica_comision']) : 0;
        $comision_porcentaje = floatval($datapost['comision_porcentaje'] ?? 0);
        $comision_monto = floatval($datapost['comision_monto'] ?? 0);

        if (empty($productos) || !is_array($productos)) {
            sendResponse(false, "Debe agregar al menos un producto");
        }

        // Validar crédito
        if ($metodo_pago === 'credito') {
            if (!$cliente_id) {
                sendResponse(false, "Se requiere un cliente para ventas a crédito");
            }

            $creditoStmt = $conn->prepare("SELECT tiene_credito, monto_credito_maximo, saldo_credito_usado FROM clientes WHERE id = ?");
            $creditoStmt->bind_param("i", $cliente_id);
            $creditoStmt->execute();
            $creditoResult = $creditoStmt->get_result();

            if ($creditoResult->num_rows === 0) {
                sendResponse(false, "Cliente no encontrado");
            }

            $clienteData = $creditoResult->fetch_assoc();
            if (!$clienteData['tiene_credito']) {
                sendResponse(false, "El cliente no tiene crédito activado");
            }

            $credito_disponible = floatval($clienteData['monto_credito_maximo']) - floatval($clienteData['saldo_credito_usado']);
        }

        try {
            $conn->begin_transaction();

            // Calcular totales
            $subtotal = 0;
            $descuento = 0;
            $impuesto = 0;

            foreach ($productos as $prod) {
                $cantidad = floatval($prod['cantidad'] ?? 0);
                $precio = floatval($prod['precio_unitario'] ?? 0);
                $descProd = floatval($prod['descuento'] ?? 0);
                $impProd = floatval($prod['impuesto'] ?? 0);

                $subtotal += $cantidad * $precio;
                $descuento += $descProd;
                $impuesto += $impProd;
            }

            $total = $subtotal - $descuento + $impuesto;

            if ($aplica_comision && $comision_monto > 0) {
                $total += $comision_monto;
            }

            // Validar crédito disponible
            if ($metodo_pago === 'credito' && isset($credito_disponible) && $total > $credito_disponible) {
                $conn->rollback();
                sendResponse(false, "El total (\$" . number_format($total, 2) . ") excede el crédito disponible (\$" . number_format($credito_disponible, 2) . ")");
            }

            // Generar folio único
            $folio = 'VTA-' . date('Ymd') . '-' . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
            $checkStmt = $conn->prepare("SELECT id FROM ventas WHERE folio = ?");
            $checkStmt->bind_param("s", $folio);
            $checkStmt->execute();
            while ($checkStmt->get_result()->num_rows > 0) {
                $folio = 'VTA-' . date('Ymd') . '-' . str_pad(rand(1, 9999), 4, '0', STR_PAD_LEFT);
                $checkStmt->bind_param("s", $folio);
                $checkStmt->execute();
            }

            $saldo_pendiente = null;
            if ($metodo_pago === 'credito' && $estatus_pago === 'pendiente') {
                $saldo_pendiente = $total;
            }

            $usuario_id = $user['id'];
            $usuario_nombre = $user['nombre'];

            $insertQuery = "INSERT INTO ventas (
                folio, cliente_id, cliente_nombre, usuario_id, usuario_nombre,
                subtotal, impuesto, descuento, total, metodo_pago, estatus_pago, saldo_pendiente,
                tipo_entrega, direccion_entrega, estado, observaciones,
                aplica_comision, comision_porcentaje, comision_monto
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, '', ?, ?, ?, ?)";

            $stmt = $conn->prepare($insertQuery);
            $stmt->bind_param(
                "sisisddddssdsssidd",
                $folio,
                $cliente_id,
                $cliente_nombre,
                $usuario_id,
                $usuario_nombre,
                $subtotal,
                $impuesto,
                $descuento,
                $total,
                $metodo_pago,
                $estatus_pago,
                $saldo_pendiente,
                $tipo_entrega,
                $direccion_entrega,
                $observaciones,
                $aplica_comision,
                $comision_porcentaje,
                $comision_monto
            );

            if (!$stmt->execute()) {
                $conn->rollback();
                sendResponse(false, "Error al crear el pedido: " . $stmt->error);
            }

            $venta_id = $conn->insert_id;

            // Insertar detalles
            $detalleQuery = "INSERT INTO venta_detalles (
                venta_id, producto_id, producto_nombre, cantidad,
                precio_unitario, subtotal, impuesto, descuento, total,
                precio_tipo, aplica_comision
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            $detalleStmt = $conn->prepare($detalleQuery);

            foreach ($productos as $prod) {
                $producto_id = intval($prod['producto_id']);
                $producto_nombre = trim($prod['producto_nombre']);
                $cantidad = floatval($prod['cantidad']);
                $precio_unitario = floatval($prod['precio_unitario']);
                $desc_prod = floatval($prod['descuento'] ?? 0);
                $imp_prod = floatval($prod['impuesto'] ?? 0);
                $precio_tipo_prod = trim($prod['precio_tipo'] ?? 'precio1');
                $aplica_comision_prod = isset($prod['aplica_comision']) ? intval($prod['aplica_comision']) : 0;

                $subtotal_prod = $cantidad * $precio_unitario;
                $total_prod = $subtotal_prod - $desc_prod + $imp_prod;

                $detalleStmt->bind_param(
                    "iisddddddsi",
                    $venta_id,
                    $producto_id,
                    $producto_nombre,
                    $cantidad,
                    $precio_unitario,
                    $subtotal_prod,
                    $imp_prod,
                    $desc_prod,
                    $total_prod,
                    $precio_tipo_prod,
                    $aplica_comision_prod
                );

                if (!$detalleStmt->execute()) {
                    $conn->rollback();
                    sendResponse(false, "Error al guardar detalle de producto");
                }

                // Descontar stock
                $stockStmt = $conn->prepare("UPDATE productos SET stock = stock - ? WHERE id = ?");
                $stockStmt->bind_param("di", $cantidad, $producto_id);
                $stockStmt->execute();
            }

            // Actualizar crédito si aplica
            if ($metodo_pago === 'credito' && $estatus_pago === 'pendiente' && $cliente_id) {
                $creditoUpdateStmt = $conn->prepare("UPDATE clientes SET saldo_credito_usado = saldo_credito_usado + ? WHERE id = ?");
                $creditoUpdateStmt->bind_param("di", $total, $cliente_id);
                if (!$creditoUpdateStmt->execute()) {
                    $conn->rollback();
                    sendResponse(false, "Error al actualizar crédito del cliente");
                }
            }

            $conn->commit();
            sendResponse(true, "Pedido creado exitosamente", ['id' => $venta_id, 'folio' => $folio]);

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al crear pedido: " . $e->getMessage());
        }
        break;

    case 'actualizarPedido':
        $id = intval($datapost['id'] ?? 0);
        $observaciones = isset($datapost['observaciones']) ? trim($datapost['observaciones']) : null;
        $direccion_entrega = isset($datapost['direccion_entrega']) ? trim($datapost['direccion_entrega']) : null;
        $tipo_entrega = isset($datapost['tipo_entrega']) ? $datapost['tipo_entrega'] : null;

        if ($id <= 0) {
            sendResponse(false, "ID de pedido requerido");
        }

        try {
            // Verificar que existe y no está confirmada/cancelada
            $checkStmt = $conn->prepare("SELECT estado FROM ventas WHERE id = ?");
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();

            if ($checkResult->num_rows === 0) {
                sendResponse(false, "Pedido no encontrado");
            }

            $venta = $checkResult->fetch_assoc();
            if (in_array($venta['estado'], ['cancelada'])) {
                sendResponse(false, "No se puede editar un pedido cancelado");
            }

            $updates = [];
            $params = [];
            $types = "";

            if ($observaciones !== null) {
                $updates[] = "observaciones = ?";
                $params[] = $observaciones;
                $types .= "s";
            }
            if ($direccion_entrega !== null) {
                $updates[] = "direccion_entrega = ?";
                $params[] = $direccion_entrega;
                $types .= "s";
            }
            if ($tipo_entrega !== null) {
                $updates[] = "tipo_entrega = ?";
                $params[] = $tipo_entrega;
                $types .= "s";
            }

            if (empty($updates)) {
                sendResponse(false, "No hay datos para actualizar");
            }

            $params[] = $id;
            $types .= "i";

            $query = "UPDATE ventas SET " . implode(", ", $updates) . " WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param($types, ...$params);

            if ($stmt->execute()) {
                sendResponse(true, "Pedido actualizado exitosamente");
            } else {
                sendResponse(false, "Error al actualizar pedido");
            }

        } catch (Exception $e) {
            sendResponse(false, "Error al actualizar pedido: " . $e->getMessage());
        }
        break;

    case 'confirmarPedido':
        $id = intval($datapost['id'] ?? 0);

        if ($id <= 0) {
            sendResponse(false, "ID de pedido requerido");
        }

        try {
            $checkStmt = $conn->prepare("SELECT estado FROM ventas WHERE id = ?");
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();

            if ($checkResult->num_rows === 0) {
                sendResponse(false, "Pedido no encontrado");
            }

            $venta = $checkResult->fetch_assoc();
            if ($venta['estado'] === 'cancelada') {
                sendResponse(false, "No se puede confirmar un pedido cancelado");
            }

            $stmt = $conn->prepare("UPDATE ventas SET estado = 'confirmado' WHERE id = ?");
            $stmt->bind_param("i", $id);

            if ($stmt->execute()) {
                sendResponse(true, "Pedido confirmado exitosamente");
            } else {
                sendResponse(false, "Error al confirmar pedido");
            }

        } catch (Exception $e) {
            sendResponse(false, "Error al confirmar pedido: " . $e->getMessage());
        }
        break;

    case 'cancelarPedido':
        $id = intval($datapost['id'] ?? 0);
        $motivo = trim($datapost['motivo'] ?? '');

        if ($id <= 0) {
            sendResponse(false, "ID de pedido requerido");
        }

        try {
            $checkStmt = $conn->prepare("SELECT estado, observaciones, cliente_id, metodo_pago, estatus_pago, total FROM ventas WHERE id = ?");
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();

            if ($checkResult->num_rows === 0) {
                sendResponse(false, "Pedido no encontrado");
            }

            $venta = $checkResult->fetch_assoc();
            if ($venta['estado'] === 'cancelada') {
                sendResponse(false, "El pedido ya está cancelado");
            }

            $conn->begin_transaction();

            // Devolver stock
            $detStmt = $conn->prepare("SELECT producto_id, cantidad FROM venta_detalles WHERE venta_id = ?");
            $detStmt->bind_param("i", $id);
            $detStmt->execute();
            $detResult = $detStmt->get_result();

            while ($det = $detResult->fetch_assoc()) {
                $stockStmt = $conn->prepare("UPDATE productos SET stock = stock + ? WHERE id = ?");
                $cantidad = floatval($det['cantidad']);
                $producto_id = intval($det['producto_id']);
                $stockStmt->bind_param("di", $cantidad, $producto_id);
                $stockStmt->execute();
            }

            // Devolver crédito si aplica
            if ($venta['metodo_pago'] === 'credito' && $venta['estatus_pago'] === 'pendiente' && $venta['cliente_id']) {
                $total = floatval($venta['total']);
                $creditoStmt = $conn->prepare("UPDATE clientes SET saldo_credito_usado = saldo_credito_usado - ? WHERE id = ?");
                $creditoStmt->bind_param("di", $total, $venta['cliente_id']);
                $creditoStmt->execute();
            }

            // Cancelar venta
            $obs = $venta['observaciones'];
            if (!empty($motivo)) {
                $obs .= "\nCANCELADA: " . $motivo;
            }

            $updateStmt = $conn->prepare("UPDATE ventas SET estado = 'cancelada', observaciones = ? WHERE id = ?");
            $updateStmt->bind_param("si", $obs, $id);

            if ($updateStmt->execute()) {
                $conn->commit();
                sendResponse(true, "Pedido cancelado exitosamente");
            } else {
                $conn->rollback();
                sendResponse(false, "Error al cancelar pedido");
            }

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al cancelar pedido: " . $e->getMessage());
        }
        break;

    case 'actualizarEstadoPedido':
        $id = intval($datapost['id'] ?? 0);
        $nuevo_estado = trim($datapost['estado'] ?? '');

        if ($id <= 0) {
            sendResponse(false, "ID de pedido requerido");
        }

        $estados_validos = ['pendiente', 'confirmado', 'preparado', 'en_ruta', 'entregado'];
        if (!in_array($nuevo_estado, $estados_validos)) {
            sendResponse(false, "Estado no válido. Valores permitidos: " . implode(', ', $estados_validos));
        }

        try {
            $checkStmt = $conn->prepare("SELECT estado FROM ventas WHERE id = ?");
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();

            if ($checkResult->num_rows === 0) {
                sendResponse(false, "Pedido no encontrado");
            }

            $venta = $checkResult->fetch_assoc();
            if ($venta['estado'] === 'cancelada') {
                sendResponse(false, "No se puede actualizar un pedido cancelado");
            }

            $stmt = $conn->prepare("UPDATE ventas SET estado = ? WHERE id = ?");
            $stmt->bind_param("si", $nuevo_estado, $id);

            if ($stmt->execute()) {
                sendResponse(true, "Estado actualizado exitosamente", ['id' => $id, 'estado' => $nuevo_estado]);
            } else {
                sendResponse(false, "Error al actualizar estado");
            }

        } catch (Exception $e) {
            sendResponse(false, "Error al actualizar estado: " . $e->getMessage());
        }
        break;

    case 'registrarPagoPedido':
        $venta_id = intval($datapost['venta_id'] ?? 0);
        $monto = floatval($datapost['monto'] ?? 0);
        $metodo_pago = trim($datapost['metodo_pago'] ?? 'efectivo');
        $referencia = trim($datapost['referencia'] ?? '');

        if ($venta_id <= 0) {
            sendResponse(false, "ID de venta requerido");
        }

        if ($monto <= 0) {
            sendResponse(false, "El monto debe ser mayor a 0");
        }

        try {
            // Obtener datos de la venta
            $ventaStmt = $conn->prepare("SELECT total, saldo_pendiente, estatus_pago, cliente_id, metodo_pago FROM ventas WHERE id = ? AND estado != 'cancelada'");
            $ventaStmt->bind_param("i", $venta_id);
            $ventaStmt->execute();
            $ventaResult = $ventaStmt->get_result();

            if ($ventaResult->num_rows === 0) {
                sendResponse(false, "Venta no encontrada o cancelada");
            }

            $venta = $ventaResult->fetch_assoc();
            $saldo_actual = floatval($venta['saldo_pendiente'] ?? $venta['total']);

            if ($monto > $saldo_actual + 0.01) {
                sendResponse(false, "El monto (\$" . number_format($monto, 2) . ") excede el saldo pendiente (\$" . number_format($saldo_actual, 2) . ")");
            }

            $conn->begin_transaction();

            // Registrar pago
            $pagoStmt = $conn->prepare("INSERT INTO venta_pagos (venta_id, monto, metodo_pago, referencia, usuario_id) VALUES (?, ?, ?, ?, ?)");
            $pagoStmt->bind_param("idssi", $venta_id, $monto, $metodo_pago, $referencia, $user['id']);

            if (!$pagoStmt->execute()) {
                // Si la tabla no existe, crear el pago directamente en la venta
                $conn->rollback();
                $conn->begin_transaction();
            }

            // Actualizar saldo pendiente
            $nuevo_saldo = max(0, $saldo_actual - $monto);
            $nuevo_estatus = $nuevo_saldo <= 0.01 ? 'pagado' : 'pendiente';

            $updateStmt = $conn->prepare("UPDATE ventas SET saldo_pendiente = ?, estatus_pago = ? WHERE id = ?");
            $updateStmt->bind_param("dsi", $nuevo_saldo, $nuevo_estatus, $venta_id);

            if (!$updateStmt->execute()) {
                $conn->rollback();
                sendResponse(false, "Error al actualizar saldo");
            }

            // Si se pagó completo y era crédito, actualizar saldo del cliente
            if ($nuevo_estatus === 'pagado' && $venta['metodo_pago'] === 'credito' && $venta['cliente_id']) {
                $totalVenta = floatval($venta['total']);
                $creditoStmt = $conn->prepare("UPDATE clientes SET saldo_credito_usado = GREATEST(0, saldo_credito_usado - ?) WHERE id = ?");
                $creditoStmt->bind_param("di", $totalVenta, $venta['cliente_id']);
                $creditoStmt->execute();
            }

            $conn->commit();
            sendResponse(true, "Pago registrado exitosamente", [
                'venta_id' => $venta_id,
                'monto_pagado' => $monto,
                'saldo_pendiente' => round($nuevo_saldo, 2),
                'estatus_pago' => $nuevo_estatus
            ]);

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al registrar pago: " . $e->getMessage());
        }
        break;

    case 'eliminarLineaPedido':
        $detalle_id = intval($datapost['detalle_id'] ?? 0);

        if ($detalle_id <= 0) {
            sendResponse(false, "ID de línea requerido");
        }

        try {
            // Obtener datos de la línea
            $detStmt = $conn->prepare("SELECT vd.venta_id, vd.producto_id, vd.cantidad, vd.total, v.estado
                                       FROM venta_detalles vd
                                       JOIN ventas v ON vd.venta_id = v.id
                                       WHERE vd.id = ?");
            $detStmt->bind_param("i", $detalle_id);
            $detStmt->execute();
            $detResult = $detStmt->get_result();

            if ($detResult->num_rows === 0) {
                sendResponse(false, "Línea no encontrada");
            }

            $detalle = $detResult->fetch_assoc();

            if (in_array($detalle['estado'], ['confirmado', 'entregado', 'cancelada'])) {
                sendResponse(false, "No se puede eliminar líneas de un pedido " . $detalle['estado']);
            }

            $conn->begin_transaction();

            // Devolver stock
            $stockStmt = $conn->prepare("UPDATE productos SET stock = stock + ? WHERE id = ?");
            $cantidad = floatval($detalle['cantidad']);
            $producto_id = intval($detalle['producto_id']);
            $stockStmt->bind_param("di", $cantidad, $producto_id);
            $stockStmt->execute();

            // Eliminar línea
            $deleteStmt = $conn->prepare("DELETE FROM venta_detalles WHERE id = ?");
            $deleteStmt->bind_param("i", $detalle_id);
            $deleteStmt->execute();

            // Recalcular totales de la venta
            $recalcStmt = $conn->prepare("SELECT COALESCE(SUM(subtotal),0) as subtotal, COALESCE(SUM(impuesto),0) as impuesto, COALESCE(SUM(descuento),0) as descuento, COALESCE(SUM(total),0) as total FROM venta_detalles WHERE venta_id = ?");
            $recalcStmt->bind_param("i", $detalle['venta_id']);
            $recalcStmt->execute();
            $totales = $recalcStmt->get_result()->fetch_assoc();

            $updateVentaStmt = $conn->prepare("UPDATE ventas SET subtotal = ?, impuesto = ?, descuento = ?, total = ? WHERE id = ?");
            $updateVentaStmt->bind_param("ddddi", $totales['subtotal'], $totales['impuesto'], $totales['descuento'], $totales['total'], $detalle['venta_id']);
            $updateVentaStmt->execute();

            $conn->commit();
            sendResponse(true, "Línea eliminada exitosamente");

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al eliminar línea: " . $e->getMessage());
        }
        break;

    case 'cobroGlobal':
        $cliente_id = intval($datapost['cliente_id'] ?? 0);
        $monto_total = floatval($datapost['monto'] ?? 0);
        $metodo_pago = trim($datapost['metodo_pago'] ?? 'efectivo');
        $referencia = trim($datapost['referencia'] ?? '');
        $venta_ids = $datapost['venta_ids'] ?? []; // Opcional: IDs específicos

        if ($cliente_id <= 0) {
            sendResponse(false, "ID de cliente requerido");
        }

        if ($monto_total <= 0) {
            sendResponse(false, "El monto debe ser mayor a 0");
        }

        try {
            $conn->begin_transaction();

            // Obtener ventas pendientes del cliente (ordenadas por antigüedad)
            $where_ventas = "WHERE cliente_id = ? AND estatus_pago = 'pendiente' AND saldo_pendiente > 0 AND estado != 'cancelada'";
            $params_ventas = [$cliente_id];
            $types_ventas = "i";

            if (!empty($venta_ids) && is_array($venta_ids)) {
                $placeholders = implode(',', array_fill(0, count($venta_ids), '?'));
                $where_ventas .= " AND id IN ($placeholders)";
                foreach ($venta_ids as $vid) {
                    $params_ventas[] = intval($vid);
                    $types_ventas .= "i";
                }
            }

            $ventasQuery = "SELECT id, folio, total, saldo_pendiente, metodo_pago FROM ventas $where_ventas ORDER BY fecha_creacion ASC";
            $ventasStmt = $conn->prepare($ventasQuery);
            $ventasStmt->bind_param($types_ventas, ...$params_ventas);
            $ventasStmt->execute();
            $ventasResult = $ventasStmt->get_result();

            $monto_restante = $monto_total;
            $pagos_aplicados = [];

            while ($venta = $ventasResult->fetch_assoc()) {
                if ($monto_restante <= 0.01) break;

                $saldo = floatval($venta['saldo_pendiente']);
                $pago_aplicar = min($monto_restante, $saldo);
                $nuevo_saldo = max(0, $saldo - $pago_aplicar);
                $nuevo_estatus = $nuevo_saldo <= 0.01 ? 'pagado' : 'pendiente';

                // Registrar pago individual
                $pagoStmt = $conn->prepare("INSERT INTO venta_pagos (venta_id, monto, metodo_pago, referencia, usuario_id) VALUES (?, ?, ?, ?, ?)");
                if ($pagoStmt) {
                    $pagoStmt->bind_param("idssi", $venta['id'], $pago_aplicar, $metodo_pago, $referencia, $user['id']);
                    $pagoStmt->execute();
                }

                // Actualizar venta
                $updateStmt = $conn->prepare("UPDATE ventas SET saldo_pendiente = ?, estatus_pago = ? WHERE id = ?");
                $updateStmt->bind_param("dsi", $nuevo_saldo, $nuevo_estatus, $venta['id']);
                $updateStmt->execute();

                $pagos_aplicados[] = [
                    'venta_id' => intval($venta['id']),
                    'folio' => $venta['folio'],
                    'monto_aplicado' => round($pago_aplicar, 2),
                    'saldo_restante' => round($nuevo_saldo, 2),
                    'estatus' => $nuevo_estatus
                ];

                $monto_restante -= $pago_aplicar;
            }

            // Actualizar saldo de crédito del cliente
            $total_cobrado = $monto_total - max(0, $monto_restante);
            if ($total_cobrado > 0) {
                $creditoStmt = $conn->prepare("UPDATE clientes SET saldo_credito_usado = GREATEST(0, saldo_credito_usado - ?) WHERE id = ?");
                $creditoStmt->bind_param("di", $total_cobrado, $cliente_id);
                $creditoStmt->execute();
            }

            $conn->commit();

            sendResponse(true, "Cobro global registrado exitosamente", [
                'monto_recibido' => $monto_total,
                'monto_aplicado' => round($total_cobrado, 2),
                'cambio' => round(max(0, $monto_restante), 2),
                'ventas_abonadas' => count($pagos_aplicados),
                'detalle_pagos' => $pagos_aplicados
            ]);

        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al procesar cobro global: " . $e->getMessage());
        }
        break;

    default:
        sendResponse(false, "Operación no válida para pedidos");
        break;
}
