<?php

/**
 * OperacionCompleta.php - Manejo de operaciones unificadas
 * Procesa ventas, devoluciones, cambios y promociones en una sola transacción
 */

// Función para enviar respuesta JSON
if (!function_exists('sendResponse')) {
    function sendResponse($success, $message = '', $data = null)
    {
        echo json_encode([
            "success" => $success,
            "message" => $message,
            "data" => $data
        ]);
        exit;
    }
}

// === REGISTRAR OPERACIÓN COMPLETA ===
if ($tipo === 'registrarOperacionCompleta') {
    error_log("=== REGISTRANDO OPERACIÓN COMPLETA ===");

    // Obtener token del repartidor
    $authHeader = $_SERVER['HTTP_AUTHORIZATION'] ?? '';
    if (empty($authHeader)) {
        $headers = getallheaders();
        $authHeader = $headers['Authorization'] ?? $headers['X-Auth-Token'] ?? '';
    }
    if (empty($authHeader)) {
        $authHeader = $_SERVER['HTTP_X_AUTH_TOKEN'] ?? '';
    }

    if (empty($authHeader)) {
        sendResponse(false, "Token de autenticación requerido");
    }

    $token = str_replace('Bearer ', '', $authHeader);

    // Verificar token y obtener repartidor_id
    require_once __DIR__ . '/../../modelos/Auth.php';
    $auth = new Auth($conn);
    $payload = $auth->verificarJWT($token);

    if (!$payload) {
        sendResponse(false, "Token inválido o expirado");
    }

    $repartidorId = $payload['repartidor_id'] ?? null;
    if (!$repartidorId) {
        sendResponse(false, "Token no válido para repartidor");
    }

    // Obtener parámetros
    $clienteId = isset($datapost['cliente_id']) ? (int)$datapost['cliente_id'] : 0;
    $visitaId = isset($datapost['visita_id']) ? (int)$datapost['visita_id'] : null;
    $productosVenta = isset($datapost['productos_venta']) ? $datapost['productos_venta'] : [];
    $productosDevolucion = isset($datapost['productos_devolucion']) ? $datapost['productos_devolucion'] : [];
    $productosCambio = isset($datapost['productos_cambio']) ? $datapost['productos_cambio'] : [];
    $productosPromocion = isset($datapost['productos_promocion']) ? $datapost['productos_promocion'] : [];
    $totalVenta = isset($datapost['total_venta']) ? (float)$datapost['total_venta'] : 0;
    $totalDevolucion = isset($datapost['total_devolucion']) ? (float)$datapost['total_devolucion'] : 0;
    $totalNeto = isset($datapost['total_neto']) ? (float)$datapost['total_neto'] : 0;
    $formaPago = isset($datapost['forma_pago']) ? $datapost['forma_pago'] : 'efectivo';
    $notas = isset($datapost['notas']) ? $datapost['notas'] : '';

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

    // Verificar que haya al menos una operación
    if (empty($productosVenta) && empty($productosDevolucion) && empty($productosCambio) && empty($productosPromocion)) {
        sendResponse(false, "Debe incluir al menos una operación");
    }

    try {
        error_log("Registrando operación completa para Cliente ID=$clienteId");
        error_log("Ventas: " . count($productosVenta) . ", Devoluciones: " . count($productosDevolucion) .
                  ", Cambios: " . count($productosCambio) . ", Promociones: " . count($productosPromocion));

        // Iniciar transacción
        $conn->beginTransaction();

        // Generar folio único para la operación
        $fechaHoy = date('Ymd');
        $queryFolio = "SELECT COUNT(*) + 1 as siguiente FROM operaciones_completas WHERE DATE(fecha_operacion) = CURDATE()";
        $stmtFolio = $conn->prepare($queryFolio);
        $stmtFolio->execute();
        $siguiente = $stmtFolio->fetch(PDO::FETCH_ASSOC)['siguiente'];
        $folioOperacion = "OP-{$fechaHoy}-" . str_pad($siguiente, 4, '0', STR_PAD_LEFT);

        // Crear registro principal de operación
        $queryOperacion = "INSERT INTO operaciones_completas (
                            folio,
                            repartidor_id,
                            cliente_id,
                            visita_id,
                            fecha_operacion,
                            hora_operacion,
                            total_venta,
                            total_devolucion,
                            total_neto,
                            forma_pago,
                            estado,
                            notas,
                            created_at
                        ) VALUES (
                            :folio,
                            :repartidor_id,
                            :cliente_id,
                            :visita_id,
                            CURDATE(),
                            CURTIME(),
                            :total_venta,
                            :total_devolucion,
                            :total_neto,
                            :forma_pago,
                            'completado',
                            :notas,
                            NOW()
                        )";

        $stmtOperacion = $conn->prepare($queryOperacion);
        $stmtOperacion->bindParam(':folio', $folioOperacion);
        $stmtOperacion->bindParam(':repartidor_id', $repartidorId);
        $stmtOperacion->bindParam(':cliente_id', $clienteId);
        $stmtOperacion->bindParam(':visita_id', $visitaId);
        $stmtOperacion->bindParam(':total_venta', $totalVenta);
        $stmtOperacion->bindParam(':total_devolucion', $totalDevolucion);
        $stmtOperacion->bindParam(':total_neto', $totalNeto);
        $stmtOperacion->bindParam(':forma_pago', $formaPago);
        $stmtOperacion->bindParam(':notas', $notas);
        $stmtOperacion->execute();

        $operacionId = $conn->lastInsertId();
        error_log("Operación creada con ID: $operacionId, Folio: $folioOperacion");

        $ventaId = null;
        $devolucionId = null;
        $cambioId = null;
        $promocionId = null;

        // ============================================
        // PROCESAR VENTAS
        // ============================================
        if (!empty($productosVenta)) {
            error_log("Procesando " . count($productosVenta) . " productos de venta");

            // Crear venta
            $queryVenta = "INSERT INTO ventas (
                            repartidor_id, cliente_id, visita_id, operacion_id,
                            fecha_venta, hora_venta, subtotal, descuento, total,
                            forma_pago, estado, notas, created_at
                        ) VALUES (
                            :repartidor_id, :cliente_id, :visita_id, :operacion_id,
                            CURDATE(), CURTIME(), :subtotal, 0, :total,
                            :forma_pago, 'completada', :notas, NOW()
                        )";

            $stmtVenta = $conn->prepare($queryVenta);
            $stmtVenta->bindParam(':repartidor_id', $repartidorId);
            $stmtVenta->bindParam(':cliente_id', $clienteId);
            $stmtVenta->bindParam(':visita_id', $visitaId);
            $stmtVenta->bindParam(':operacion_id', $operacionId);
            $stmtVenta->bindParam(':subtotal', $totalVenta);
            $stmtVenta->bindParam(':total', $totalVenta);
            $stmtVenta->bindParam(':forma_pago', $formaPago);
            $notaVenta = "Venta desde operación $folioOperacion";
            $stmtVenta->bindParam(':notas', $notaVenta);
            $stmtVenta->execute();

            $ventaId = $conn->lastInsertId();

            // Insertar detalle de venta y actualizar inventario
            foreach ($productosVenta as $producto) {
                $productoId = (int)$producto['producto_id'];
                $cantidad = (int)$producto['cantidad'];
                $precioUnitario = (float)$producto['precio_unitario'];
                $subtotal = (float)$producto['subtotal'];

                // Insertar detalle
                $queryDetalle = "INSERT INTO ventas_detalle (
                                    venta_id, producto_id, cantidad, precio_unitario, subtotal, created_at
                                ) VALUES (
                                    :venta_id, :producto_id, :cantidad, :precio_unitario, :subtotal, NOW()
                                )";
                $stmtDetalle = $conn->prepare($queryDetalle);
                $stmtDetalle->bindParam(':venta_id', $ventaId);
                $stmtDetalle->bindParam(':producto_id', $productoId);
                $stmtDetalle->bindParam(':cantidad', $cantidad);
                $stmtDetalle->bindParam(':precio_unitario', $precioUnitario);
                $stmtDetalle->bindParam(':subtotal', $subtotal);
                $stmtDetalle->execute();

                // Descontar del inventario del repartidor
                $queryDescuento = "UPDATE inventarios_repartidor
                                  SET cantidad = cantidad - :cantidad, updated_at = NOW()
                                  WHERE repartidor_id = :repartidor_id AND producto_id = :producto_id";
                $stmtDescuento = $conn->prepare($queryDescuento);
                $stmtDescuento->bindParam(':cantidad', $cantidad);
                $stmtDescuento->bindParam(':repartidor_id', $repartidorId);
                $stmtDescuento->bindParam(':producto_id', $productoId);
                $stmtDescuento->execute();

                // Registrar movimiento
                $queryMov = "INSERT INTO movimientos_inventario_repartidor
                            (repartidor_id, producto_id, tipo_movimiento, cantidad, venta_id, notas, created_at)
                            VALUES (:repartidor_id, :producto_id, 'venta', :cantidad, :venta_id, :notas, NOW())";
                $stmtMov = $conn->prepare($queryMov);
                $notaMov = "Venta - Folio: $folioOperacion";
                $stmtMov->bindParam(':repartidor_id', $repartidorId);
                $stmtMov->bindParam(':producto_id', $productoId);
                $stmtMov->bindParam(':cantidad', $cantidad);
                $stmtMov->bindParam(':venta_id', $ventaId);
                $stmtMov->bindParam(':notas', $notaMov);
                $stmtMov->execute();
            }
        }

        // ============================================
        // PROCESAR DEVOLUCIONES
        // ============================================
        if (!empty($productosDevolucion)) {
            error_log("Procesando " . count($productosDevolucion) . " productos de devolución");

            // Generar folio de devolución
            $folioDev = "DEV-" . date('Ymd') . "-" . str_pad($operacionId, 4, '0', STR_PAD_LEFT);

            // Crear devolución
            $queryDev = "INSERT INTO devoluciones (
                            folio, repartidor_id, cliente_id, visita_id, operacion_id,
                            fecha_devolucion, hora_devolucion, subtotal, impuestos, total,
                            estado, notas, created_at
                        ) VALUES (
                            :folio, :repartidor_id, :cliente_id, :visita_id, :operacion_id,
                            CURDATE(), CURTIME(), :subtotal, 0, :total,
                            'procesada', :notas, NOW()
                        )";

            $stmtDev = $conn->prepare($queryDev);
            $stmtDev->bindParam(':folio', $folioDev);
            $stmtDev->bindParam(':repartidor_id', $repartidorId);
            $stmtDev->bindParam(':cliente_id', $clienteId);
            $stmtDev->bindParam(':visita_id', $visitaId);
            $stmtDev->bindParam(':operacion_id', $operacionId);
            $stmtDev->bindParam(':subtotal', $totalDevolucion);
            $stmtDev->bindParam(':total', $totalDevolucion);
            $notaDev = "Devolución desde operación $folioOperacion";
            $stmtDev->bindParam(':notas', $notaDev);
            $stmtDev->execute();

            $devolucionId = $conn->lastInsertId();

            // Insertar detalle de devolución
            foreach ($productosDevolucion as $producto) {
                $productoId = (int)$producto['producto_id'];
                $cantidad = (int)$producto['cantidad'];
                $precioUnitario = (float)$producto['precio_unitario'];
                $subtotal = (float)$producto['subtotal'];
                $motivo = $producto['motivo'] ?? 'otro';

                $queryDetDev = "INSERT INTO devoluciones_detalle (
                                    devolucion_id, producto_id, cantidad, precio_unitario, subtotal, motivo, created_at
                                ) VALUES (
                                    :devolucion_id, :producto_id, :cantidad, :precio_unitario, :subtotal, :motivo, NOW()
                                )";
                $stmtDetDev = $conn->prepare($queryDetDev);
                $stmtDetDev->bindParam(':devolucion_id', $devolucionId);
                $stmtDetDev->bindParam(':producto_id', $productoId);
                $stmtDetDev->bindParam(':cantidad', $cantidad);
                $stmtDetDev->bindParam(':precio_unitario', $precioUnitario);
                $stmtDetDev->bindParam(':subtotal', $subtotal);
                $stmtDetDev->bindParam(':motivo', $motivo);
                $stmtDetDev->execute();

                // Agregar al inventario de devoluciones del repartidor
                $queryAddInv = "INSERT INTO inventarios_devoluciones_repartidor (repartidor_id, producto_id, cantidad, ultimo_motivo, tipo_origen, fecha_ultima_devolucion, created_at)
                               VALUES (:repartidor_id, :producto_id, :cantidad, :motivo, 'devolucion', NOW(), NOW())
                               ON DUPLICATE KEY UPDATE cantidad = cantidad + :cantidad2, ultimo_motivo = :motivo2, tipo_origen = 'devolucion', fecha_ultima_devolucion = NOW(), updated_at = NOW()";
                $stmtAddInv = $conn->prepare($queryAddInv);
                $stmtAddInv->bindParam(':repartidor_id', $repartidorId);
                $stmtAddInv->bindParam(':producto_id', $productoId);
                $stmtAddInv->bindParam(':cantidad', $cantidad);
                $stmtAddInv->bindParam(':motivo', $motivo);
                $stmtAddInv->bindParam(':cantidad2', $cantidad);
                $stmtAddInv->bindParam(':motivo2', $motivo);
                $stmtAddInv->execute();
            }
        }

        // ============================================
        // PROCESAR CAMBIOS
        // ============================================
        if (!empty($productosCambio)) {
            error_log("Procesando " . count($productosCambio) . " productos de cambio");

            // Generar folio de cambio
            $folioCambio = "CAM-" . date('Ymd') . "-" . str_pad($operacionId, 4, '0', STR_PAD_LEFT);

            // Crear cambio
            $queryCambio = "INSERT INTO cambios (
                                folio, repartidor_id, cliente_id, visita_id, operacion_id,
                                fecha_cambio, hora_cambio, estado, notas, created_at
                            ) VALUES (
                                :folio, :repartidor_id, :cliente_id, :visita_id, :operacion_id,
                                CURDATE(), CURTIME(), 'completado', :notas, NOW()
                            )";

            $stmtCambio = $conn->prepare($queryCambio);
            $stmtCambio->bindParam(':folio', $folioCambio);
            $stmtCambio->bindParam(':repartidor_id', $repartidorId);
            $stmtCambio->bindParam(':cliente_id', $clienteId);
            $stmtCambio->bindParam(':visita_id', $visitaId);
            $stmtCambio->bindParam(':operacion_id', $operacionId);
            $notaCambio = "Cambio desde operación $folioOperacion";
            $stmtCambio->bindParam(':notas', $notaCambio);
            $stmtCambio->execute();

            $cambioId = $conn->lastInsertId();

            // Insertar detalle de cambio
            foreach ($productosCambio as $producto) {
                $productoId = (int)$producto['producto_id'];
                $cantidad = (int)$producto['cantidad'];
                $motivo = $producto['motivo'] ?? 'defectuoso';

                $queryDetCambio = "INSERT INTO cambios_detalle (
                                        cambio_id, producto_id, cantidad, motivo, created_at
                                    ) VALUES (
                                        :cambio_id, :producto_id, :cantidad, :motivo, NOW()
                                    )";
                $stmtDetCambio = $conn->prepare($queryDetCambio);
                $stmtDetCambio->bindParam(':cambio_id', $cambioId);
                $stmtDetCambio->bindParam(':producto_id', $productoId);
                $stmtDetCambio->bindParam(':cantidad', $cantidad);
                $stmtDetCambio->bindParam(':motivo', $motivo);
                $stmtDetCambio->execute();

                // Descontar del inventario (se entrega producto nuevo)
                $queryDescCambio = "UPDATE inventarios_repartidor
                                   SET cantidad = cantidad - :cantidad, updated_at = NOW()
                                   WHERE repartidor_id = :repartidor_id AND producto_id = :producto_id";
                $stmtDescCambio = $conn->prepare($queryDescCambio);
                $stmtDescCambio->bindParam(':cantidad', $cantidad);
                $stmtDescCambio->bindParam(':repartidor_id', $repartidorId);
                $stmtDescCambio->bindParam(':producto_id', $productoId);
                $stmtDescCambio->execute();

                // Registrar producto defectuoso en inventario de devoluciones
                $queryAddDef = "INSERT INTO inventarios_devoluciones_repartidor (repartidor_id, producto_id, cantidad, ultimo_motivo, tipo_origen, fecha_ultima_devolucion, created_at)
                               VALUES (:repartidor_id, :producto_id, :cantidad, :motivo, 'cambio', NOW(), NOW())
                               ON DUPLICATE KEY UPDATE cantidad = cantidad + :cantidad2, ultimo_motivo = :motivo2, tipo_origen = 'cambio', fecha_ultima_devolucion = NOW(), updated_at = NOW()";
                $stmtAddDef = $conn->prepare($queryAddDef);
                $stmtAddDef->bindParam(':repartidor_id', $repartidorId);
                $stmtAddDef->bindParam(':producto_id', $productoId);
                $stmtAddDef->bindParam(':cantidad', $cantidad);
                $stmtAddDef->bindParam(':motivo', $motivo);
                $stmtAddDef->bindParam(':cantidad2', $cantidad);
                $stmtAddDef->bindParam(':motivo2', $motivo);
                $stmtAddDef->execute();
            }
        }

        // ============================================
        // PROCESAR PROMOCIONES
        // ============================================
        if (!empty($productosPromocion)) {
            error_log("Procesando " . count($productosPromocion) . " productos de promoción");

            $totalItemsPromo = array_sum(array_column($productosPromocion, 'cantidad'));

            // Crear promoción
            $queryPromo = "INSERT INTO promociones (
                                folio, repartidor_id, cliente_id, visita_id, operacion_id,
                                fecha_promocion, hora_promocion, total_items,
                                estado, notas, created_at
                            ) VALUES (
                                :folio, :repartidor_id, :cliente_id, :visita_id, :operacion_id,
                                CURDATE(), CURTIME(), :total_items,
                                'completado', :notas, NOW()
                            )";

            $folioPromo = "PROMO-" . date('Ymd') . "-" . str_pad($operacionId, 4, '0', STR_PAD_LEFT);
            $stmtPromo = $conn->prepare($queryPromo);
            $stmtPromo->bindParam(':folio', $folioPromo);
            $stmtPromo->bindParam(':repartidor_id', $repartidorId);
            $stmtPromo->bindParam(':cliente_id', $clienteId);
            $stmtPromo->bindParam(':visita_id', $visitaId);
            $stmtPromo->bindParam(':operacion_id', $operacionId);
            $stmtPromo->bindParam(':total_items', $totalItemsPromo);
            $notaPromo = "Promoción desde operación $folioOperacion";
            $stmtPromo->bindParam(':notas', $notaPromo);
            $stmtPromo->execute();

            $promocionId = $conn->lastInsertId();

            // Insertar detalle de promoción
            foreach ($productosPromocion as $producto) {
                $productoId = (int)$producto['producto_id'];
                $cantidad = (int)$producto['cantidad'];
                $tipoPromocion = $producto['tipo_promocion'] ?? 'degustacion';
                $descripcion = $producto['descripcion'] ?? '';

                $queryDetPromo = "INSERT INTO promociones_detalle (
                                        promocion_id, producto_id, cantidad, tipo_promocion, descripcion, created_at
                                    ) VALUES (
                                        :promocion_id, :producto_id, :cantidad, :tipo_promocion, :descripcion, NOW()
                                    )";
                $stmtDetPromo = $conn->prepare($queryDetPromo);
                $stmtDetPromo->bindParam(':promocion_id', $promocionId);
                $stmtDetPromo->bindParam(':producto_id', $productoId);
                $stmtDetPromo->bindParam(':cantidad', $cantidad);
                $stmtDetPromo->bindParam(':tipo_promocion', $tipoPromocion);
                $stmtDetPromo->bindParam(':descripcion', $descripcion);
                $stmtDetPromo->execute();

                // Descontar del inventario del repartidor
                $queryDescPromo = "UPDATE inventarios_repartidor
                                  SET cantidad = cantidad - :cantidad, updated_at = NOW()
                                  WHERE repartidor_id = :repartidor_id AND producto_id = :producto_id";
                $stmtDescPromo = $conn->prepare($queryDescPromo);
                $stmtDescPromo->bindParam(':cantidad', $cantidad);
                $stmtDescPromo->bindParam(':repartidor_id', $repartidorId);
                $stmtDescPromo->bindParam(':producto_id', $productoId);
                $stmtDescPromo->execute();
            }
        }

        // Confirmar transacción
        $conn->commit();

        error_log("✅ Operación completa registrada exitosamente: $folioOperacion");

        sendResponse(true, "Operación registrada exitosamente", [
            'operacion_id' => $operacionId,
            'folio' => $folioOperacion,
            'venta_id' => $ventaId,
            'devolucion_id' => $devolucionId,
            'cambio_id' => $cambioId,
            'promocion_id' => $promocionId,
            'total_venta' => $totalVenta,
            'total_devolucion' => $totalDevolucion,
            'total_neto' => $totalNeto,
            'fecha' => date('Y-m-d H:i:s')
        ]);

    } catch (Exception $e) {
        $conn->rollBack();
        error_log("❌ Error registrando operación completa: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error al registrar la operación: " . $e->getMessage());
    }
}
