<?php
// Archivo: VentasMostrador.php
// Descripción: API para gestionar ventas de mostrador

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

switch ($tipo) {
    case 'crearVentaMostrador':
        $usuario_id = intval($datapost['usuario_id'] ?? 0);
        $usuario_nombre = trim($datapost['usuario_nombre'] ?? '');
        $cliente_id = isset($datapost['cliente_id']) ? intval($datapost['cliente_id']) : null;
        $metodo_pago = isset($datapost['metodo_pago']) ? $datapost['metodo_pago'] : null;
        $estatus_pago = $datapost['estatus_pago'] ?? 'pagado';
        $observaciones = trim($datapost['observaciones'] ?? '');
        $productos = $datapost['productos'] ?? [];
        $pagos_detalle = $datapost['pagos_detalle'] ?? null;
        $nombre_pc = isset($datapost['nombre_pc']) ? trim($datapost['nombre_pc']) : null;

        // Datos de comisión por tarjeta
        $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);

        // Obtener caja_id desde nombre_pc
        $caja_id = null;
        if ($nombre_pc) {
            $cajaStmt = $conn->prepare("SELECT id FROM cajas WHERE nombre_pc = ?");
            $cajaStmt->bind_param("s", $nombre_pc);
            $cajaStmt->execute();
            $cajaResult = $cajaStmt->get_result();
            if ($cajaRow = $cajaResult->fetch_assoc()) {
                $caja_id = intval($cajaRow['id']);
            }
        }

        // Validaciones
        if ($usuario_id <= 0) {
            sendResponse(false, "Usuario requerido");
        }

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

        try {
            // Iniciar transacción
            $conn->begin_transaction();

            // Obtener campo de costo configurado (precio_compra o costo_precios)
            $campoCosto = 'precio_compra'; // default
            $stmtCosto = $conn->prepare("SELECT valor FROM configuraciones WHERE clave = 'empresa_campo_costo' LIMIT 1");
            if ($stmtCosto) {
                $stmtCosto->execute();
                $resCosto = $stmtCosto->get_result();
                if ($rowCosto = $resCosto->fetch_assoc()) {
                    $campoCostoVal = trim($rowCosto['valor']);
                    if (in_array($campoCostoVal, ['precio_compra', 'costo_precios'])) {
                        $campoCosto = $campoCostoVal;
                    }
                }
                $stmtCosto->close();
            }

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

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

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

                $subtotal += $subtotal_prod;
                $descuento += $desc_prod;
                $impuesto += $imp_prod;
                $total += $total_prod;
            }

            // Generar folio único
            $folio_prefix = 'VM'; // Venta Mostrador
            $fecha = date('Ymd');

            // Obtener el último folio del día
            $checkFolio = "SELECT folio FROM ventas_mostrador WHERE folio LIKE ? ORDER BY id DESC LIMIT 1";
            $stmtFolio = $conn->prepare($checkFolio);
            $folioPattern = $folio_prefix . $fecha . '%';
            $stmtFolio->bind_param("s", $folioPattern);
            $stmtFolio->execute();
            $resultFolio = $stmtFolio->get_result();

            $consecutivo = 1;
            if ($resultFolio->num_rows > 0) {
                $lastFolio = $resultFolio->fetch_assoc()['folio'];
                // Extraer el número consecutivo del último folio
                $lastNumber = intval(substr($lastFolio, -4));
                $consecutivo = $lastNumber + 1;
            }

            $folio = $folio_prefix . $fecha . str_pad($consecutivo, 4, '0', STR_PAD_LEFT);

            // Determinar método de pago final
            $metodoPagoFinal = $metodo_pago;
            if ($pagos_detalle && is_array($pagos_detalle) && count($pagos_detalle) > 1) {
                $metodoPagoFinal = 'mixto';
            }

            // Si aplica comisión, sumar al total
            if ($aplica_comision && $comision_monto > 0) {
                $total += $comision_monto;
            }

            // Insertar venta de mostrador
            $insertVenta = "INSERT INTO ventas_mostrador (
                folio, usuario_id, usuario_nombre, caja_id, cliente_id,
                subtotal, impuesto, descuento, total, metodo_pago, estatus_pago, observaciones,
                aplica_comision, comision_porcentaje, comision_monto
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

            $stmt = $conn->prepare($insertVenta);
            $stmt->bind_param(
                "sisiiddddsssidd",
                $folio,
                $usuario_id,
                $usuario_nombre,
                $caja_id,
                $cliente_id,
                $subtotal,
                $impuesto,
                $descuento,
                $total,
                $metodoPagoFinal,
                $estatus_pago,
                $observaciones,
                $aplica_comision,
                $comision_porcentaje,
                $comision_monto
            );

            if (!$stmt->execute()) {
                $conn->rollback();
                sendResponse(false, "Error al crear la venta de mostrador");
            }

            $venta_id = $conn->insert_id;

            // Insertar detalles de la venta
            $insertDetalle = "INSERT INTO ventas_mostrador_detalles (
                venta_mostrador_id, producto_id, producto_nombre, cantidad,
                precio_unitario, subtotal, impuesto, descuento, total,
                precio_tipo, aplica_comision, costo, costo_tipo
            ) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)";

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

            // Preparar query para obtener costo del producto
            $costoQuery = "SELECT precio_compra, costo_precios FROM productos WHERE id = ?";
            $costoStmt = $conn->prepare($costoQuery);

            // Tipos de precio que aplican comisión (mayoreo)
            $preciosMayoreo = ['precio2', 'precio3', 'precio4', 'precio5', 'precio6'];

            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 = trim($prod['precio_tipo'] ?? 'precio_lista');
                $prod_aplica_comision = in_array($precio_tipo, $preciosMayoreo) ? 1 : 0;

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

                // Obtener costo del producto desde la BD
                $costoProducto = 0;
                $costoStmt->bind_param("i", $producto_id);
                $costoStmt->execute();
                $costoResult = $costoStmt->get_result();
                if ($costoRow = $costoResult->fetch_assoc()) {
                    $costoProducto = floatval($costoRow[$campoCosto] ?? 0);
                }

                $detalleStmt->bind_param(
                    "iisddddddsids",
                    $venta_id,
                    $producto_id,
                    $producto_nombre,
                    $cantidad,
                    $precio_unitario,
                    $subtotal_prod,
                    $imp_prod,
                    $desc_prod,
                    $total_prod,
                    $precio_tipo,
                    $prod_aplica_comision,
                    $costoProducto,
                    $campoCosto
                );

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

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

            // Si hay pagos múltiples, guardarlos
            if ($metodoPagoFinal === 'mixto' && $pagos_detalle) {
                $insertPago = "INSERT INTO ventas_mostrador_pagos (venta_mostrador_id, metodo_pago, monto) VALUES (?, ?, ?)";
                $pagoStmt = $conn->prepare($insertPago);

                foreach ($pagos_detalle as $pago) {
                    $metodo = $pago['metodo'];
                    $monto = floatval($pago['monto']);

                    $pagoStmt->bind_param("isd", $venta_id, $metodo, $monto);
                    if (!$pagoStmt->execute()) {
                        $conn->rollback();
                        sendResponse(false, "Error al guardar detalle de pagos");
                    }
                }
            }

            // Confirmar transacción
            $conn->commit();
            sendResponse(true, "Venta de mostrador creada exitosamente", ['id' => $venta_id, 'folio' => $folio]);
        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al crear venta de mostrador: " . $e->getMessage());
        }
        break;

    case 'getVentasMostrador':
        try {
            $query = "SELECT
                vm.id,
                vm.folio,
                vm.usuario_id,
                vm.usuario_nombre,
                vm.subtotal,
                vm.impuesto,
                vm.descuento,
                vm.total,
                vm.metodo_pago,
                vm.estatus_pago,
                vm.observaciones,
                vm.fecha_creacion,
                COUNT(vmd.id) as total_productos
            FROM ventas_mostrador vm
            LEFT JOIN ventas_mostrador_detalles vmd ON vm.id = vmd.venta_mostrador_id
            GROUP BY vm.id
            ORDER BY vm.fecha_creacion DESC
            LIMIT 500";

            $result = $conn->query($query);

            if (!$result) {
                sendResponse(false, "Error al obtener ventas de mostrador");
            }

            $ventas = [];
            while ($row = $result->fetch_assoc()) {
                $ventas[] = [
                    'id' => intval($row['id']),
                    'folio' => $row['folio'],
                    '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'],
                    'observaciones' => $row['observaciones'],
                    'fecha_creacion' => $row['fecha_creacion'],
                    'total_productos' => intval($row['total_productos'])
                ];
            }

            sendResponse(true, "Ventas de mostrador obtenidas exitosamente", $ventas);
        } catch (Exception $e) {
            sendResponse(false, "Error al obtener ventas de mostrador: " . $e->getMessage());
        }
        break;

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

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

        try {
            // Obtener datos de la venta
            $query = "SELECT * FROM ventas_mostrador WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("i", $id);
            $stmt->execute();
            $result = $stmt->get_result();

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

            $venta = $result->fetch_assoc();

            // Obtener detalles
            $queryDetalles = "SELECT * FROM ventas_mostrador_detalles WHERE venta_mostrador_id = ?";
            $stmtDetalles = $conn->prepare($queryDetalles);
            $stmtDetalles->bind_param("i", $id);
            $stmtDetalles->execute();
            $resultDetalles = $stmtDetalles->get_result();

            $detalles = [];
            while ($row = $resultDetalles->fetch_assoc()) {
                $detalles[] = [
                    'id' => intval($row['id']),
                    'producto_id' => intval($row['producto_id']),
                    'producto_nombre' => $row['producto_nombre'],
                    'cantidad' => floatval($row['cantidad']),
                    'precio_unitario' => floatval($row['precio_unitario']),
                    'subtotal' => floatval($row['subtotal']),
                    'impuesto' => floatval($row['impuesto']),
                    'descuento' => floatval($row['descuento']),
                    'total' => floatval($row['total'])
                ];
            }

            // Obtener pagos si es mixto
            $pagos = [];
            if ($venta['metodo_pago'] === 'mixto') {
                $queryPagos = "SELECT * FROM ventas_mostrador_pagos WHERE venta_mostrador_id = ?";
                $stmtPagos = $conn->prepare($queryPagos);
                $stmtPagos->bind_param("i", $id);
                $stmtPagos->execute();
                $resultPagos = $stmtPagos->get_result();

                while ($row = $resultPagos->fetch_assoc()) {
                    $pagos[] = [
                        'metodo_pago' => $row['metodo_pago'],
                        'monto' => floatval($row['monto'])
                    ];
                }
            }

            $ventaCompleta = [
                'id' => intval($venta['id']),
                'folio' => $venta['folio'],
                'usuario_id' => intval($venta['usuario_id']),
                'usuario_nombre' => $venta['usuario_nombre'],
                'subtotal' => floatval($venta['subtotal']),
                'impuesto' => floatval($venta['impuesto']),
                'descuento' => floatval($venta['descuento']),
                'total' => floatval($venta['total']),
                'metodo_pago' => $venta['metodo_pago'],
                'estatus_pago' => $venta['estatus_pago'],
                'observaciones' => $venta['observaciones'],
                'fecha_creacion' => $venta['fecha_creacion'],
                'detalles' => $detalles,
                'pagos' => $pagos
            ];

            sendResponse(true, "Venta de mostrador obtenida exitosamente", $ventaCompleta);
        } catch (Exception $e) {
            sendResponse(false, "Error al obtener venta de mostrador: " . $e->getMessage());
        }
        break;

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

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

        try {
            $W = 36; // Ancho del ticket en caracteres

            // Leer configuraciones de impresión
            $desgloseIva = false;
            $totalEnLetra = false;
            $stmtConf = $conn->prepare("SELECT clave, valor FROM configuraciones WHERE clave IN ('impresion_desglose_iva', 'impresion_total_en_letra')");
            if ($stmtConf) {
                $stmtConf->execute();
                $resConf = $stmtConf->get_result();
                while ($rowConf = $resConf->fetch_assoc()) {
                    if ($rowConf['clave'] === 'impresion_desglose_iva') {
                        $desgloseIva = ($rowConf['valor'] === 'true' || $rowConf['valor'] === '1');
                    }
                    if ($rowConf['clave'] === 'impresion_total_en_letra') {
                        $totalEnLetra = ($rowConf['valor'] === 'true' || $rowConf['valor'] === '1');
                    }
                }
                $stmtConf->close();
            }

            // Función para centrar texto
            $centrar = function ($texto) use ($W) {
                $len = mb_strlen($texto);
                if ($len >= $W) return $texto;
                $pad = intval(($W - $len) / 2);
                return str_repeat(' ', $pad) . $texto;
            };

            // Función para alinear label a la izq y monto a la derecha
            $lineaMonto = function ($label, $monto) use ($W) {
                $montoStr = '$' . number_format($monto, 2);
                $espacios = $W - mb_strlen($label) - strlen($montoStr);
                if ($espacios < 1) $espacios = 1;
                return $label . str_repeat(' ', $espacios) . $montoStr;
            };

            $linea = str_repeat('=', $W);
            $lineaGuion = str_repeat('-', $W);

            // Obtener datos de la venta con cliente
            $query = "SELECT vm.*, c.nombre as cliente_nombre
                      FROM ventas_mostrador vm
                      LEFT JOIN clientes c ON vm.cliente_id = c.id
                      WHERE vm.id = ?";

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

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

            $venta = $result->fetch_assoc();

            // Obtener detalles de productos
            $queryDet = "SELECT vmd.cantidad, vmd.producto_nombre, vmd.precio_unitario,
                                p.codigo_corto, p.unidad_medida
                         FROM ventas_mostrador_detalles vmd
                         LEFT JOIN productos p ON vmd.producto_id = p.id
                         WHERE vmd.venta_mostrador_id = ?";
            $stmtDet = $conn->prepare($queryDet);
            $stmtDet->bind_param("i", $id);
            $stmtDet->execute();
            $resultDet = $stmtDet->get_result();

            $detalles = [];
            while ($row = $resultDet->fetch_assoc()) {
                $detalles[] = $row;
            }

            // Determinar nombre del cliente
            $nombreCliente = $venta['cliente_nombre'] ? $venta['cliente_nombre'] : 'Público General';

            // Generar ticket (36 chars monospace)
            $ticket = $linea . "\n";
            $ticket .= $centrar("VENTA DE MOSTRADOR") . "\n";
            $ticket .= $linea . "\n";
            $ticket .= "Folio: " . $venta['folio'] . "\n";
            $ticket .= "Fecha: " . date('d/m/Y H:i', strtotime($venta['fecha_creacion'])) . "\n";
            $ticket .= "Cliente: " . $nombreCliente . "\n";
            $ticket .= "Atendió: " . $venta['usuario_nombre'] . "\n";
            $ticket .= $linea . "\n";

            // Header de productos alineado con datos
            $hIzq = '  CANT/UNID';
            $hCentro = 'P.U';
            $hDer = 'IMPORTE';
            $hEspacio = $W - mb_strlen($hIzq) - mb_strlen($hCentro) - mb_strlen($hDer);
            if ($hEspacio < 2) $hEspacio = 2;
            $hEspIzq = intval($hEspacio / 2);
            $hEspDer = $hEspacio - $hEspIzq;
            $ticket .= $hIzq . str_repeat(' ', $hEspIzq) . $hCentro . str_repeat(' ', $hEspDer) . $hDer . "\n";
            $ticket .= $lineaGuion . "\n";

            // Productos en 2 líneas por artículo
            foreach ($detalles as $det) {
                $codigo = $det['codigo_corto'] ?? '';
                $nombre = $det['producto_nombre'];
                $cant = rtrim(rtrim(number_format($det['cantidad'], 2), '0'), '.');
                $unidad = $det['unidad_medida'] ?? 'pz';
                $precioUnit = '$' . number_format($det['precio_unitario'], 2);
                $subtotal = '$' . number_format($det['cantidad'] * $det['precio_unitario'], 2);

                // Línea 1: [codigo] descripcion
                $linea1 = '';
                if ($codigo) {
                    $linea1 = '[' . $codigo . '] ';
                }
                $espacioDesc = $W - mb_strlen($linea1);
                if (mb_strlen($nombre) > $espacioDesc) {
                    $nombre = mb_substr($nombre, 0, $espacioDesc - 1) . '.';
                }
                $linea1 .= $nombre;

                // Línea 2: cant unidad | p.u. centrado | subtotal derecha
                $izq = '  ' . $cant . ' ' . $unidad;
                $centro = $precioUnit;
                $der = $subtotal;
                $lenIzq = mb_strlen($izq);
                $lenCentro = mb_strlen($centro);
                $lenDer = mb_strlen($der);
                $espacioTotal = $W - $lenIzq - $lenCentro - $lenDer;
                if ($espacioTotal < 2) $espacioTotal = 2;
                $espIzq = intval($espacioTotal / 2);
                $espDer = $espacioTotal - $espIzq;
                $linea2 = $izq . str_repeat(' ', $espIzq) . $centro . str_repeat(' ', $espDer) . $der;
                // Asegurar que no exceda el ancho
                if (mb_strlen($linea2) > $W) {
                    $linea2 = mb_substr($linea2, 0, $W);
                }

                $ticket .= $linea1 . "\n";
                $ticket .= $linea2 . "\n";
            }

            $ticket .= $lineaGuion . "\n";
            $ticket .= "\n";

            // Totales con montos alineados a la derecha
            if ($desgloseIva) {
                $totalNum = floatval($venta['total']);
                $subtSinIva = $totalNum / 1.16;
                $iva = $totalNum - $subtSinIva;
                $ticket .= $lineaMonto("Subtotal:", $subtSinIva) . "\n";
                if ($venta['descuento'] > 0) {
                    $ticket .= $lineaMonto("Descuento:", -$venta['descuento']) . "\n";
                }
                $ticket .= $lineaMonto("IVA (16%):", $iva) . "\n";
            } else {
                $ticket .= $lineaMonto("Subtotal:", $venta['subtotal']) . "\n";
                if ($venta['descuento'] > 0) {
                    $ticket .= $lineaMonto("Descuento:", -$venta['descuento']) . "\n";
                }
                if ($venta['impuesto'] > 0) {
                    $ticket .= $lineaMonto("Impuesto:", $venta['impuesto']) . "\n";
                }
            }
            $ticket .= $linea . "\n";
            $ticket .= $lineaMonto("TOTAL:", $venta['total']) . "\n";
            $ticket .= $linea . "\n";
            if ($totalEnLetra) {
                $ticket .= numeroALetraPHP(floatval($venta['total'])) . "\n";
            }
            if ($venta['metodo_pago']) {
                $ticket .= "Método de Pago: " . strtoupper($venta['metodo_pago']) . "\n";
            }

            sendResponse(true, "Ticket generado exitosamente", [
                'ticket' => $ticket,
                'folio' => $venta['folio']
            ]);
        } catch (Exception $e) {
            sendResponse(false, "Error al generar ticket: " . $e->getMessage());
        }
        break;

    case 'buscarVentaPorFolio':
        $folio = trim($datapost['folio'] ?? '');

        if (empty($folio)) {
            sendResponse(false, "Folio de venta requerido");
        }

        try {
            // Buscar la venta por folio
            $query = "SELECT
                v.id,
                v.folio,
                v.usuario_id,
                v.usuario_nombre,
                v.cliente_id,
                v.caja_id,
                v.subtotal,
                v.descuento,
                v.impuesto,
                v.total,
                v.metodo_pago,
                v.estatus_pago,
                v.observaciones,
                v.fecha_creacion,
                c.nombre as cliente_nombre,
                ca.nombre_pc
            FROM ventas_mostrador v
            LEFT JOIN clientes c ON v.cliente_id = c.id
            LEFT JOIN cajas ca ON v.caja_id = ca.id
            WHERE v.folio = ?";

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

            if ($result->num_rows === 0) {
                sendResponse(false, "No se encontró la venta con folio: " . $folio);
            }

            $venta = $result->fetch_assoc();

            // Obtener detalles de la venta
            $queryDetalles = "SELECT
                d.id,
                d.producto_id,
                d.cantidad,
                d.precio_unitario,
                d.subtotal,
                d.descuento,
                COALESCE(d.cantidad_devuelta, 0) as cantidad_devuelta,
                p.nombre as producto_nombre,
                p.codigo_barras,
                p.codigo_corto
            FROM ventas_mostrador_detalles d
            INNER JOIN productos p ON d.producto_id = p.id
            WHERE d.venta_mostrador_id = ?";

            $stmtDet = $conn->prepare($queryDetalles);
            $stmtDet->bind_param("i", $venta['id']);
            $stmtDet->execute();
            $resultDet = $stmtDet->get_result();

            $detalles = [];
            while ($row = $resultDet->fetch_assoc()) {
                $detalles[] = [
                    'id' => intval($row['id']),
                    'producto_id' => intval($row['producto_id']),
                    'producto_nombre' => $row['producto_nombre'],
                    'codigo_barras' => $row['codigo_barras'],
                    'codigo_corto' => $row['codigo_corto'],
                    'cantidad' => floatval($row['cantidad']),
                    'precio_unitario' => floatval($row['precio_unitario']),
                    'subtotal' => floatval($row['subtotal']),
                    'descuento' => floatval($row['descuento']),
                    'cantidad_devuelta' => floatval($row['cantidad_devuelta'])
                ];
            }

            $venta['detalles'] = $detalles;

            sendResponse(true, "Venta encontrada", $venta);
        } catch (Exception $e) {
            sendResponse(false, "Error al buscar venta: " . $e->getMessage());
        }
        break;

    case 'procesarDevolucion':
        $venta_id = intval($datapost['venta_id'] ?? 0);
        $usuario_id = intval($datapost['usuario_id'] ?? 0);
        $articulos = $datapost['articulos'] ?? [];

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

        if (empty($articulos) || !is_array($articulos)) {
            sendResponse(false, "Debe seleccionar al menos un artículo para devolver");
        }

        try {
            $conn->begin_transaction();

            $totalDevolucion = 0;

            foreach ($articulos as $articulo) {
                $detalle_id = intval($articulo['detalle_id'] ?? 0);
                $producto_id = intval($articulo['producto_id'] ?? 0);
                $cantidad = floatval($articulo['cantidad'] ?? 0);
                $precio_unitario = floatval($articulo['precio_unitario'] ?? 0);

                if ($detalle_id <= 0 || $cantidad <= 0) {
                    continue;
                }

                // Verificar que no se devuelva más de lo vendido
                $checkQuery = "SELECT cantidad, COALESCE(cantidad_devuelta, 0) as cantidad_devuelta
                               FROM ventas_mostrador_detalles WHERE id = ?";
                $checkStmt = $conn->prepare($checkQuery);
                $checkStmt->bind_param("i", $detalle_id);
                $checkStmt->execute();
                $checkResult = $checkStmt->get_result();
                $detalleActual = $checkResult->fetch_assoc();

                if (!$detalleActual) {
                    throw new Exception("Detalle de venta no encontrado");
                }

                $maxDevolver = $detalleActual['cantidad'] - $detalleActual['cantidad_devuelta'];
                if ($cantidad > $maxDevolver) {
                    throw new Exception("No se puede devolver más de lo vendido");
                }

                // Actualizar cantidad devuelta en el detalle
                $updateQuery = "UPDATE ventas_mostrador_detalles
                                SET cantidad_devuelta = COALESCE(cantidad_devuelta, 0) + ?
                                WHERE id = ?";
                $updateStmt = $conn->prepare($updateQuery);
                $updateStmt->bind_param("di", $cantidad, $detalle_id);
                $updateStmt->execute();

                // Devolver stock al producto
                $stockQuery = "UPDATE productos SET stock = stock + ? WHERE id = ?";
                $stockStmt = $conn->prepare($stockQuery);
                $stockStmt->bind_param("di", $cantidad, $producto_id);
                $stockStmt->execute();

                $totalDevolucion += $cantidad * $precio_unitario;
            }

            // Registrar la devolución en una tabla de devoluciones (si existe)
            // Por ahora solo actualizamos el total de la venta
            $updateVentaQuery = "UPDATE ventas_mostrador
                                 SET total = total - ?,
                                     subtotal = subtotal - ?
                                 WHERE id = ?";
            $updateVentaStmt = $conn->prepare($updateVentaQuery);
            $updateVentaStmt->bind_param("ddi", $totalDevolucion, $totalDevolucion, $venta_id);
            $updateVentaStmt->execute();

            $conn->commit();

            sendResponse(true, "Devolución procesada correctamente", [
                'total_devolucion' => $totalDevolucion
            ]);
        } catch (Exception $e) {
            $conn->rollback();
            sendResponse(false, "Error al procesar devolución: " . $e->getMessage());
        }
        break;

    case 'getReporteVentasMostrador':
        $fecha_inicio = trim($datapost['fecha_inicio'] ?? date('Y-m-d'));
        $fecha_fin = trim($datapost['fecha_fin'] ?? date('Y-m-d'));
        $metodo_pago = trim($datapost['metodo_pago'] ?? '');
        $usuario_id = isset($datapost['usuario_id']) ? intval($datapost['usuario_id']) : null;
        $caja_id = isset($datapost['caja_id']) ? intval($datapost['caja_id']) : null;

        try {
            // Query base para ventas
            $query = "SELECT
                vm.id,
                vm.folio,
                vm.fecha_creacion,
                vm.usuario_id,
                vm.usuario_nombre,
                vm.caja_id,
                c.identificador as caja_nombre,
                vm.cliente_id,
                cl.nombre as cliente_nombre,
                vm.subtotal,
                vm.impuesto,
                vm.descuento,
                vm.total,
                vm.metodo_pago,
                vm.estatus_pago,
                vm.observaciones
            FROM ventas_mostrador vm
            LEFT JOIN cajas c ON vm.caja_id = c.id
            LEFT JOIN clientes cl ON vm.cliente_id = cl.id
            WHERE DATE(vm.fecha_creacion) BETWEEN ? AND ?";

            $params = [$fecha_inicio, $fecha_fin];
            $types = "ss";

            if (!empty($metodo_pago)) {
                $query .= " AND vm.metodo_pago = ?";
                $params[] = $metodo_pago;
                $types .= "s";
            }

            if ($usuario_id) {
                $query .= " AND vm.usuario_id = ?";
                $params[] = $usuario_id;
                $types .= "i";
            }

            if ($caja_id) {
                $query .= " AND vm.caja_id = ?";
                $params[] = $caja_id;
                $types .= "i";
            }

            $query .= " ORDER BY vm.fecha_creacion DESC";

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

            $ventas = [];
            while ($row = $result->fetch_assoc()) {
                $ventas[] = $row;
            }

            // Calcular resumen
            $resumenQuery = "SELECT
                COUNT(*) as total_ventas,
                COALESCE(SUM(total), 0) as total_monto,
                COALESCE(SUM(subtotal), 0) as total_subtotal,
                COALESCE(SUM(descuento), 0) as total_descuento,
                COALESCE(SUM(impuesto), 0) as total_impuesto,
                COALESCE(SUM(CASE WHEN metodo_pago = 'efectivo' THEN total ELSE 0 END), 0) as total_efectivo,
                COALESCE(SUM(CASE WHEN metodo_pago IN ('tarjeta', 'tarjeta_credito', 'tarjeta_debito') THEN total ELSE 0 END), 0) as total_tarjeta,
                COALESCE(SUM(CASE WHEN metodo_pago = 'tarjeta_credito' THEN total ELSE 0 END), 0) as total_tarjeta_credito,
                COALESCE(SUM(CASE WHEN metodo_pago = 'tarjeta_debito' THEN total ELSE 0 END), 0) as total_tarjeta_debito,
                COALESCE(SUM(CASE WHEN metodo_pago = 'transferencia' THEN total ELSE 0 END), 0) as total_transferencia,
                COALESCE(SUM(CASE WHEN metodo_pago = 'mixto' THEN total ELSE 0 END), 0) as total_mixto
            FROM ventas_mostrador vm
            WHERE DATE(vm.fecha_creacion) BETWEEN ? AND ?";

            $resumenParams = [$fecha_inicio, $fecha_fin];
            $resumenTypes = "ss";

            if (!empty($metodo_pago)) {
                $resumenQuery .= " AND vm.metodo_pago = ?";
                $resumenParams[] = $metodo_pago;
                $resumenTypes .= "s";
            }

            if ($usuario_id) {
                $resumenQuery .= " AND vm.usuario_id = ?";
                $resumenParams[] = $usuario_id;
                $resumenTypes .= "i";
            }

            if ($caja_id) {
                $resumenQuery .= " AND vm.caja_id = ?";
                $resumenParams[] = $caja_id;
                $resumenTypes .= "i";
            }

            $resumenStmt = $conn->prepare($resumenQuery);
            $resumenStmt->bind_param($resumenTypes, ...$resumenParams);
            $resumenStmt->execute();
            $resumen = $resumenStmt->get_result()->fetch_assoc();

            sendResponse(true, "Reporte generado correctamente", [
                'ventas' => $ventas,
                'resumen' => $resumen
            ]);
        } catch (Exception $e) {
            sendResponse(false, "Error al generar reporte: " . $e->getMessage());
        }
        break;

    case 'getReporteVentasMostradorPorUsuario':
        $fecha_inicio = trim($datapost['fecha_inicio'] ?? date('Y-m-d'));
        $fecha_fin = trim($datapost['fecha_fin'] ?? date('Y-m-d'));

        try {
            $query = "SELECT
                vm.usuario_id,
                vm.usuario_nombre,
                COUNT(*) as total_ventas,
                COALESCE(SUM(vm.total), 0) as total_monto,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'efectivo' THEN vm.total ELSE 0 END), 0) as total_efectivo,
                COALESCE(SUM(CASE WHEN vm.metodo_pago IN ('tarjeta', 'tarjeta_credito', 'tarjeta_debito') THEN vm.total ELSE 0 END), 0) as total_tarjeta,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'tarjeta_credito' THEN vm.total ELSE 0 END), 0) as total_tarjeta_credito,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'tarjeta_debito' THEN vm.total ELSE 0 END), 0) as total_tarjeta_debito,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'transferencia' THEN vm.total ELSE 0 END), 0) as total_transferencia
            FROM ventas_mostrador vm
            WHERE DATE(vm.fecha_creacion) BETWEEN ? AND ?
            GROUP BY vm.usuario_id, vm.usuario_nombre
            ORDER BY total_monto DESC";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("ss", $fecha_inicio, $fecha_fin);
            $stmt->execute();
            $result = $stmt->get_result();

            $reporte = [];
            while ($row = $result->fetch_assoc()) {
                $reporte[] = $row;
            }

            sendResponse(true, "Reporte por usuario generado", $reporte);
        } catch (Exception $e) {
            sendResponse(false, "Error: " . $e->getMessage());
        }
        break;

    case 'getReporteVentasMostradorPorCaja':
        $fecha_inicio = trim($datapost['fecha_inicio'] ?? date('Y-m-d'));
        $fecha_fin = trim($datapost['fecha_fin'] ?? date('Y-m-d'));

        try {
            $query = "SELECT
                vm.caja_id,
                COALESCE(c.identificador, 'Sin caja') as caja_nombre,
                COUNT(*) as total_ventas,
                COALESCE(SUM(vm.total), 0) as total_monto,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'efectivo' THEN vm.total ELSE 0 END), 0) as total_efectivo,
                COALESCE(SUM(CASE WHEN vm.metodo_pago IN ('tarjeta', 'tarjeta_credito', 'tarjeta_debito') THEN vm.total ELSE 0 END), 0) as total_tarjeta,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'tarjeta_credito' THEN vm.total ELSE 0 END), 0) as total_tarjeta_credito,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'tarjeta_debito' THEN vm.total ELSE 0 END), 0) as total_tarjeta_debito,
                COALESCE(SUM(CASE WHEN vm.metodo_pago = 'transferencia' THEN vm.total ELSE 0 END), 0) as total_transferencia
            FROM ventas_mostrador vm
            LEFT JOIN cajas c ON vm.caja_id = c.id
            WHERE DATE(vm.fecha_creacion) BETWEEN ? AND ?
            GROUP BY vm.caja_id, c.identificador
            ORDER BY total_monto DESC";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("ss", $fecha_inicio, $fecha_fin);
            $stmt->execute();
            $result = $stmt->get_result();

            $reporte = [];
            while ($row = $result->fetch_assoc()) {
                $reporte[] = $row;
            }

            sendResponse(true, "Reporte por caja generado", $reporte);
        } catch (Exception $e) {
            sendResponse(false, "Error: " . $e->getMessage());
        }
        break;

    case 'getReporteProductosMostradorMasVendidos':
        $fecha_inicio = trim($datapost['fecha_inicio'] ?? date('Y-m-d'));
        $fecha_fin = trim($datapost['fecha_fin'] ?? date('Y-m-d'));
        $limite = intval($datapost['limite'] ?? 20);

        try {
            $query = "SELECT
                vmd.producto_id,
                vmd.producto_nombre,
                SUM(vmd.cantidad) as total_cantidad,
                SUM(vmd.total) as total_vendido,
                COUNT(DISTINCT vmd.venta_mostrador_id) as veces_vendido
            FROM ventas_mostrador_detalles vmd
            INNER JOIN ventas_mostrador vm ON vmd.venta_mostrador_id = vm.id
            WHERE DATE(vm.fecha_creacion) BETWEEN ? AND ?
            GROUP BY vmd.producto_id, vmd.producto_nombre
            ORDER BY total_cantidad DESC
            LIMIT ?";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("ssi", $fecha_inicio, $fecha_fin, $limite);
            $stmt->execute();
            $result = $stmt->get_result();

            $productos = [];
            while ($row = $result->fetch_assoc()) {
                $productos[] = $row;
            }

            sendResponse(true, "Productos más vendidos", $productos);
        } catch (Exception $e) {
            sendResponse(false, "Error: " . $e->getMessage());
        }
        break;

    case 'getVentasMostradorDetalle':
        $venta_id = intval($datapost['venta_id'] ?? 0);

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

        try {
            // Obtener venta
            $ventaQuery = "SELECT
                vm.*,
                c.identificador as caja_nombre,
                cl.nombre as cliente_nombre
            FROM ventas_mostrador vm
            LEFT JOIN cajas c ON vm.caja_id = c.id
            LEFT JOIN clientes cl ON vm.cliente_id = cl.id
            WHERE vm.id = ?";

            $ventaStmt = $conn->prepare($ventaQuery);
            $ventaStmt->bind_param("i", $venta_id);
            $ventaStmt->execute();
            $venta = $ventaStmt->get_result()->fetch_assoc();

            if (!$venta) {
                sendResponse(false, "Venta no encontrada");
            }

            // Obtener detalles
            $detallesQuery = "SELECT
                vmd.*,
                p.codigo_barras,
                p.codigo_corto
            FROM ventas_mostrador_detalles vmd
            LEFT JOIN productos p ON vmd.producto_id = p.id
            WHERE vmd.venta_mostrador_id = ?";

            $detallesStmt = $conn->prepare($detallesQuery);
            $detallesStmt->bind_param("i", $venta_id);
            $detallesStmt->execute();
            $detallesResult = $detallesStmt->get_result();

            $detalles = [];
            while ($row = $detallesResult->fetch_assoc()) {
                $detalles[] = $row;
            }

            $venta['detalles'] = $detalles;

            sendResponse(true, "Detalle de venta", $venta);
        } catch (Exception $e) {
            sendResponse(false, "Error: " . $e->getMessage());
        }
        break;

    case 'getHistorialProductoCliente':
        $producto_id = intval($datapost['producto_id'] ?? 0);
        $cliente_id = intval($datapost['cliente_id'] ?? 0);
        $limite = intval($datapost['limite'] ?? 5);

        if ($producto_id <= 0 || $cliente_id <= 0) {
            sendResponse(false, "Producto y cliente son requeridos");
        }

        try {
            // Obtener campo de costo configurado
            $campoCosto = 'precio_compra';
            $stmtConf = $conn->prepare("SELECT valor FROM configuraciones WHERE clave = 'empresa_campo_costo' LIMIT 1");
            if ($stmtConf) {
                $stmtConf->execute();
                $resConf = $stmtConf->get_result();
                if ($rowConf = $resConf->fetch_assoc()) {
                    $val = trim($rowConf['valor']);
                    if (in_array($val, ['precio_compra', 'costo_precios'])) {
                        $campoCosto = $val;
                    }
                }
                $stmtConf->close();
            }

            // Obtener costo actual del producto
            $costoActual = 0;
            $stmtProd = $conn->prepare("SELECT precio_compra, costo_precios FROM productos WHERE id = ?");
            $stmtProd->bind_param("i", $producto_id);
            $stmtProd->execute();
            $resProd = $stmtProd->get_result();
            if ($rowProd = $resProd->fetch_assoc()) {
                $costoActual = floatval($rowProd[$campoCosto] ?? 0);
            }
            $stmtProd->close();

            $query = "(SELECT
                vm.folio,
                vm.fecha_creacion,
                vmd.cantidad,
                vmd.precio_unitario,
                vmd.precio_tipo,
                vmd.total,
                vmd.costo,
                vmd.costo_tipo
            FROM ventas_mostrador_detalles vmd
            INNER JOIN ventas_mostrador vm ON vmd.venta_mostrador_id = vm.id
            WHERE vmd.producto_id = ?
              AND vm.cliente_id = ?)
            UNION ALL
            (SELECT
                v.folio,
                v.fecha_creacion,
                vd.cantidad,
                vd.precio_unitario,
                vd.precio_tipo,
                vd.total,
                vd.costo,
                vd.costo_tipo
            FROM venta_detalles vd
            INNER JOIN ventas v ON vd.venta_id = v.id
            WHERE vd.producto_id = ?
              AND v.cliente_id = ?)
            ORDER BY fecha_creacion DESC
            LIMIT ?";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("iiiii", $producto_id, $cliente_id, $producto_id, $cliente_id, $limite);
            $stmt->execute();
            $result = $stmt->get_result();

            $historial = [];
            while ($row = $result->fetch_assoc()) {
                $historial[] = [
                    'folio' => $row['folio'],
                    'fecha' => $row['fecha_creacion'],
                    'cantidad' => floatval($row['cantidad']),
                    'precio_unitario' => floatval($row['precio_unitario']),
                    'precio_tipo' => $row['precio_tipo'],
                    'total' => floatval($row['total']),
                    'costo' => floatval($row['costo'] ?? 0),
                    'costo_tipo' => $row['costo_tipo'] ?? null
                ];
            }

            sendResponse(true, "Historial obtenido", [
                'historial' => $historial,
                'costo_actual' => $costoActual,
                'costo_tipo_actual' => $campoCosto
            ]);
        } catch (Exception $e) {
            sendResponse(false, "Error al obtener historial: " . $e->getMessage());
        }
        break;

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

// Función para convertir número a letra en español
function numeroALetraPHP($num) {
    $unidades = ['', 'UN', 'DOS', 'TRES', 'CUATRO', 'CINCO', 'SEIS', 'SIETE', 'OCHO', 'NUEVE'];
    $especiales = ['DIEZ', 'ONCE', 'DOCE', 'TRECE', 'CATORCE', 'QUINCE'];
    $decenas = ['', 'DIEZ', 'VEINTE', 'TREINTA', 'CUARENTA', 'CINCUENTA', 'SESENTA', 'SETENTA', 'OCHENTA', 'NOVENTA'];
    $centenas = ['', 'CIENTO', 'DOSCIENTOS', 'TRESCIENTOS', 'CUATROCIENTOS', 'QUINIENTOS', 'SEISCIENTOS', 'SETECIENTOS', 'OCHOCIENTOS', 'NOVECIENTOS'];

    $convertirGrupo = function($n) use ($unidades, $especiales, $decenas, $centenas) {
        if ($n == 0) return '';
        if ($n == 100) return 'CIEN';
        $resultado = '';
        if ($n >= 100) { $resultado .= $centenas[intval($n / 100)] . ' '; $n %= 100; }
        if ($n >= 10 && $n <= 15) return $resultado . $especiales[$n - 10];
        if ($n >= 16 && $n <= 19) return $resultado . 'DIECI' . $unidades[$n - 10];
        if ($n >= 21 && $n <= 29) return $resultado . 'VEINTI' . $unidades[$n - 20];
        if ($n >= 10) { $resultado .= $decenas[intval($n / 10)]; $n %= 10; if ($n > 0) $resultado .= ' Y '; }
        $resultado .= $unidades[$n];
        return trim($resultado);
    };

    $entero = intval(floor(abs($num)));
    $centavos = round((abs($num) - $entero) * 100);

    if ($entero == 0) return "CERO PESOS " . str_pad($centavos, 2, '0', STR_PAD_LEFT) . "/100 M.N.";

    $texto = '';
    if ($entero >= 1000000) {
        $millones = intval($entero / 1000000);
        $texto .= ($millones == 1 ? 'UN MILLON' : $convertirGrupo($millones) . ' MILLONES') . ' ';
    }
    $resto = $entero % 1000000;
    if ($resto >= 1000) {
        $miles = intval($resto / 1000);
        $texto .= ($miles == 1 ? 'MIL' : $convertirGrupo($miles) . ' MIL') . ' ';
    }
    $unidad = $resto % 1000;
    if ($unidad > 0) $texto .= $convertirGrupo($unidad);

    return trim($texto) . " PESOS " . str_pad($centavos, 2, '0', STR_PAD_LEFT) . "/100 M.N.";
}
