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

// Estados de la orden de compra
if (!defined('ESTADO_BORRADOR')) define('ESTADO_BORRADOR', 'borrador');
if (!defined('ESTADO_PENDIENTE')) define('ESTADO_PENDIENTE', 'pendiente');
if (!defined('ESTADO_APROBADA')) define('ESTADO_APROBADA', 'aprobada');
if (!defined('ESTADO_RECIBIDA_PARCIAL')) define('ESTADO_RECIBIDA_PARCIAL', 'recibida_parcial');
if (!defined('ESTADO_RECIBIDA')) define('ESTADO_RECIBIDA', 'recibida');
if (!defined('ESTADO_CANCELADA')) define('ESTADO_CANCELADA', 'cancelada');

// Función para generar folio único
function generarFolioOrden($conn) {
    $year = date('Y');
    $prefix = "OC-{$year}-";

    $query = "SELECT MAX(CAST(SUBSTRING(folio, " . (strlen($prefix) + 1) . ") AS UNSIGNED)) as ultimo
              FROM ordenes_compra WHERE folio LIKE ?";
    $stmt = $conn->prepare($query);
    $prefixLike = $prefix . '%';
    $stmt->bind_param("s", $prefixLike);
    $stmt->execute();
    $result = $stmt->get_result();
    $row = $result->fetch_assoc();

    $siguiente = ($row['ultimo'] ?? 0) + 1;
    return $prefix . str_pad($siguiente, 5, '0', STR_PAD_LEFT);
}

switch ($tipo) {
    // Obtener todas las órdenes de compra
    case 'getOrdenesCompra':
        try {
            $estado = isset($datapost['estado']) ? trim($datapost['estado']) : '';

            $query = "SELECT oc.*, p.nombre as proveedor_nombre,
                      (SELECT COUNT(*) FROM orden_compra_detalle WHERE orden_compra_id = oc.id) as total_productos,
                      u.nombre as usuario_nombre
                      FROM ordenes_compra oc
                      LEFT JOIN proveedores p ON oc.proveedor_id = p.id
                      LEFT JOIN usuarios u ON oc.usuario_id = u.id";

            if (!empty($estado)) {
                $query .= " WHERE oc.estado = ?";
            }

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

            if (!empty($estado)) {
                $stmt = $conn->prepare($query);
                $stmt->bind_param("s", $estado);
                $stmt->execute();
                $result = $stmt->get_result();
            } else {
                $result = $conn->query($query);
            }

            if (!$result) {
                sendResponse(false, "Error en consulta: " . $conn->error);
                break;
            }

            $ordenes = [];
            while ($row = $result->fetch_assoc()) {
                $row['id'] = (int)$row['id'];
                $row['proveedor_id'] = (int)$row['proveedor_id'];
                $row['subtotal'] = (float)$row['subtotal'];
                $row['impuesto'] = (float)$row['impuesto'];
                $row['total'] = (float)$row['total'];
                $row['total_productos'] = (int)$row['total_productos'];
                $ordenes[] = $row;
            }

            sendResponse(true, "Órdenes de compra obtenidas", $ordenes);
        } catch (Exception $e) {
            error_log("Error al obtener órdenes: " . $e->getMessage());
            sendResponse(false, "Error al obtener órdenes");
        }
        break;

    // Obtener una orden de compra con sus detalles
    case 'getOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            // Obtener la orden
            $query = "SELECT oc.*, p.nombre as proveedor_nombre, p.telefono as proveedor_telefono,
                      p.email as proveedor_email, u.nombre as usuario_nombre,
                      ua.nombre as aprobador_nombre, ur.nombre as receptor_nombre
                      FROM ordenes_compra oc
                      LEFT JOIN proveedores p ON oc.proveedor_id = p.id
                      LEFT JOIN usuarios u ON oc.usuario_id = u.id
                      LEFT JOIN usuarios ua ON oc.aprobado_por = ua.id
                      LEFT JOIN usuarios ur ON oc.recibido_por = ur.id
                      WHERE oc.id = ?";

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

            if (!$orden) {
                sendResponse(false, "Orden de compra no encontrada");
                break;
            }

            $orden['id'] = (int)$orden['id'];
            $orden['proveedor_id'] = (int)$orden['proveedor_id'];
            $orden['subtotal'] = (float)$orden['subtotal'];
            $orden['impuesto'] = (float)$orden['impuesto'];
            $orden['total'] = (float)$orden['total'];

            // Obtener los detalles
            $queryDetalle = "SELECT ocd.*, pr.nombre as producto_nombre, pr.codigo_barras,
                             pr.unidad_medida
                             FROM orden_compra_detalle ocd
                             LEFT JOIN productos pr ON ocd.producto_id = pr.id
                             WHERE ocd.orden_compra_id = ?";

            $stmtDetalle = $conn->prepare($queryDetalle);
            $stmtDetalle->bind_param("i", $id);
            $stmtDetalle->execute();
            $resultDetalle = $stmtDetalle->get_result();

            $detalles = [];
            while ($row = $resultDetalle->fetch_assoc()) {
                $row['id'] = (int)$row['id'];
                $row['producto_id'] = (int)$row['producto_id'];
                $row['cantidad'] = (float)$row['cantidad'];
                $row['cantidad_recibida'] = (float)($row['cantidad_recibida'] ?? 0);
                $row['precio_unitario'] = (float)$row['precio_unitario'];
                $row['subtotal'] = (float)$row['subtotal'];
                $detalles[] = $row;
            }

            $orden['detalles'] = $detalles;

            sendResponse(true, "Orden obtenida correctamente", $orden);
        } catch (Exception $e) {
            error_log("Error al obtener orden: " . $e->getMessage());
            sendResponse(false, "Error al obtener orden");
        }
        break;

    // Crear orden de compra
    case 'crearOrdenCompra':
        try {
            $proveedor_id = isset($datapost['proveedor_id']) ? intval($datapost['proveedor_id']) : 0;
            $usuario_id = isset($datapost['usuario_id']) && intval($datapost['usuario_id']) > 0 ? intval($datapost['usuario_id']) : null;
            $detalles = isset($datapost['detalles']) ? $datapost['detalles'] : [];
            $notas = isset($datapost['notas']) ? trim($datapost['notas']) : '';
            $subtotal = isset($datapost['subtotal']) ? floatval($datapost['subtotal']) : 0;
            $total = isset($datapost['total']) ? floatval($datapost['total']) : 0;
            $estado = ESTADO_BORRADOR;

            // Validaciones
            if ($proveedor_id <= 0) {
                sendResponse(false, "Debe seleccionar un proveedor");
                break;
            }

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

            $conn->begin_transaction();

            // Generar folio
            $folio = generarFolioOrden($conn);

            // Insertar orden (usuario_id puede ser NULL)
            if ($usuario_id !== null) {
                $query = "INSERT INTO ordenes_compra (folio, proveedor_id, usuario_id, subtotal, total, estado, notas)
                          VALUES (?, ?, ?, ?, ?, ?, ?)";
                $stmt = $conn->prepare($query);
                $stmt->bind_param("siiddss", $folio, $proveedor_id, $usuario_id, $subtotal, $total, $estado, $notas);
            } else {
                $query = "INSERT INTO ordenes_compra (folio, proveedor_id, subtotal, total, estado, notas)
                          VALUES (?, ?, ?, ?, ?, ?)";
                $stmt = $conn->prepare($query);
                $stmt->bind_param("siddss", $folio, $proveedor_id, $subtotal, $total, $estado, $notas);
            }

            if (!$stmt->execute()) {
                throw new Exception("Error al insertar orden: " . $stmt->error);
            }

            $ordenId = $conn->insert_id;

            // Insertar detalles
            $queryDetalle = "INSERT INTO orden_compra_detalle (orden_compra_id, producto_id, cantidad, precio_unitario, subtotal)
                             VALUES (?, ?, ?, ?, ?)";
            $stmtDetalle = $conn->prepare($queryDetalle);

            foreach ($detalles as $detalle) {
                $producto_id = intval($detalle['producto_id'] ?? 0);
                $cantidad = floatval($detalle['cantidad'] ?? 0);
                $precio = floatval($detalle['precio_unitario'] ?? 0);
                $subtotalItem = floatval($detalle['subtotal'] ?? ($cantidad * $precio));

                $stmtDetalle->bind_param("iiddd", $ordenId, $producto_id, $cantidad, $precio, $subtotalItem);

                if (!$stmtDetalle->execute()) {
                    throw new Exception("Error al insertar detalle: " . $stmtDetalle->error);
                }
            }

            $conn->commit();

            sendResponse(true, "Orden de compra creada correctamente", [
                "id" => $ordenId,
                "folio" => $folio
            ]);
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al crear orden: " . $e->getMessage());
            sendResponse(false, "Error al crear orden: " . $e->getMessage());
        }
        break;

    // Actualizar orden de compra (solo si está en borrador)
    case 'actualizarOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;
            $proveedor_id = isset($datapost['proveedor_id']) ? intval($datapost['proveedor_id']) : 0;
            $detalles = isset($datapost['detalles']) ? $datapost['detalles'] : [];
            $notas = isset($datapost['notas']) ? trim($datapost['notas']) : '';
            $subtotal = isset($datapost['subtotal']) ? floatval($datapost['subtotal']) : 0;
            $total = isset($datapost['total']) ? floatval($datapost['total']) : 0;

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            // Verificar que la orden esté en borrador
            $checkQuery = "SELECT estado FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] !== ESTADO_BORRADOR) {
                sendResponse(false, "Solo se pueden editar órdenes en estado borrador");
                break;
            }

            $conn->begin_transaction();

            // Actualizar orden
            $query = "UPDATE ordenes_compra SET
                      proveedor_id = ?,
                      subtotal = ?,
                      total = ?,
                      notas = ?
                      WHERE id = ?";

            $stmt = $conn->prepare($query);
            $stmt->bind_param("iddsi", $proveedor_id, $subtotal, $total, $notas, $id);
            $stmt->execute();

            // Eliminar detalles anteriores
            $deleteQuery = "DELETE FROM orden_compra_detalle WHERE orden_compra_id = ?";
            $deleteStmt = $conn->prepare($deleteQuery);
            $deleteStmt->bind_param("i", $id);
            $deleteStmt->execute();

            // Insertar nuevos detalles
            $queryDetalle = "INSERT INTO orden_compra_detalle (orden_compra_id, producto_id, cantidad, precio_unitario, subtotal)
                             VALUES (?, ?, ?, ?, ?)";
            $stmtDetalle = $conn->prepare($queryDetalle);

            foreach ($detalles as $detalle) {
                $producto_id = intval($detalle['producto_id'] ?? 0);
                $cantidad = floatval($detalle['cantidad'] ?? 0);
                $precio = floatval($detalle['precio_unitario'] ?? 0);
                $subtotalItem = floatval($detalle['subtotal'] ?? ($cantidad * $precio));

                $stmtDetalle->bind_param("iiddd", $id, $producto_id, $cantidad, $precio, $subtotalItem);
                $stmtDetalle->execute();
            }

            $conn->commit();

            sendResponse(true, "Orden actualizada correctamente");
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al actualizar orden: " . $e->getMessage());
            sendResponse(false, "Error al actualizar orden");
        }
        break;

    // Enviar orden a aprobación
    case 'enviarAprobacionOrden':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            $checkQuery = "SELECT estado FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] !== ESTADO_BORRADOR) {
                sendResponse(false, "Solo se pueden enviar a aprobación órdenes en estado borrador");
                break;
            }

            $nuevoEstado = ESTADO_PENDIENTE;
            $query = "UPDATE ordenes_compra SET estado = ? WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("si", $nuevoEstado, $id);

            if ($stmt->execute()) {
                sendResponse(true, "Orden enviada a aprobación");
            } else {
                sendResponse(false, "Error al enviar orden a aprobación");
            }
        } catch (Exception $e) {
            error_log("Error: " . $e->getMessage());
            sendResponse(false, "Error al enviar orden a aprobación");
        }
        break;

    // Aprobar orden de compra
    case 'aprobarOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;
            $aprobado_por = isset($datapost['aprobado_por']) && intval($datapost['aprobado_por']) > 0 ? intval($datapost['aprobado_por']) : null;

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            $checkQuery = "SELECT estado FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] !== ESTADO_PENDIENTE) {
                sendResponse(false, "Solo se pueden aprobar órdenes pendientes de aprobación");
                break;
            }

            $nuevoEstado = ESTADO_APROBADA;

            if ($aprobado_por !== null) {
                $query = "UPDATE ordenes_compra SET
                          estado = ?,
                          aprobado_por = ?,
                          fecha_aprobacion = NOW()
                          WHERE id = ?";
                $stmt = $conn->prepare($query);
                $stmt->bind_param("sii", $nuevoEstado, $aprobado_por, $id);
            } else {
                $query = "UPDATE ordenes_compra SET
                          estado = ?,
                          fecha_aprobacion = NOW()
                          WHERE id = ?";
                $stmt = $conn->prepare($query);
                $stmt->bind_param("si", $nuevoEstado, $id);
            }

            if ($stmt->execute()) {
                sendResponse(true, "Orden aprobada correctamente");
            } else {
                sendResponse(false, "Error al aprobar orden: " . $stmt->error);
            }
        } catch (Exception $e) {
            error_log("Error al aprobar orden: " . $e->getMessage());
            sendResponse(false, "Error al aprobar orden: " . $e->getMessage());
        }
        break;

    // Rechazar orden de compra
    case 'rechazarOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;
            $motivo = isset($datapost['motivo']) ? trim($datapost['motivo']) : '';

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            $checkQuery = "SELECT estado, notas FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] !== ESTADO_PENDIENTE) {
                sendResponse(false, "Solo se pueden rechazar órdenes pendientes de aprobación");
                break;
            }

            $nuevoEstado = ESTADO_BORRADOR;
            $nuevasNotas = ($orden['notas'] ? $orden['notas'] . "\n" : '') . "[RECHAZADA] " . $motivo;

            $query = "UPDATE ordenes_compra SET estado = ?, notas = ? WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("ssi", $nuevoEstado, $nuevasNotas, $id);

            if ($stmt->execute()) {
                sendResponse(true, "Orden rechazada y devuelta a borrador");
            } else {
                sendResponse(false, "Error al rechazar orden");
            }
        } catch (Exception $e) {
            error_log("Error al rechazar orden: " . $e->getMessage());
            sendResponse(false, "Error al rechazar orden");
        }
        break;

    // Recibir orden de compra (actualiza inventario)
    case 'recibirOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;
            $productos_recibidos = isset($datapost['productos']) ? $datapost['productos'] : [];
            $recibido_por = isset($datapost['recibido_por']) ? intval($datapost['recibido_por']) : 0;
            $estado_pago = isset($datapost['estado_pago']) ? trim($datapost['estado_pago']) : 'pendiente';

            // Validar estado_pago
            if (!in_array($estado_pago, ['pendiente', 'pagada'])) {
                $estado_pago = 'pendiente';
            }

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            if (empty($productos_recibidos)) {
                sendResponse(false, "Debe especificar los productos recibidos");
                break;
            }

            $checkQuery = "SELECT estado FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] !== ESTADO_APROBADA && $orden['estado'] !== ESTADO_RECIBIDA_PARCIAL) {
                sendResponse(false, "Solo se pueden recibir órdenes aprobadas o con recepción parcial");
                break;
            }

            $conn->begin_transaction();

            $todoRecibido = true;
            $totalOrden = 0;

            foreach ($productos_recibidos as $item) {
                $detalle_id = intval($item['detalle_id'] ?? 0);
                $cantidad_recibida = floatval($item['cantidad_recibida'] ?? 0);
                $precio_unitario = floatval($item['precio_unitario'] ?? 0);

                if ($detalle_id <= 0 || $cantidad_recibida <= 0) continue;

                // Obtener detalle actual
                $queryDetalle = "SELECT * FROM orden_compra_detalle WHERE id = ?";
                $stmtDetalle = $conn->prepare($queryDetalle);
                $stmtDetalle->bind_param("i", $detalle_id);
                $stmtDetalle->execute();
                $resultDetalle = $stmtDetalle->get_result();
                $detalle = $resultDetalle->fetch_assoc();

                if (!$detalle) continue;

                $nueva_cantidad_recibida = floatval($detalle['cantidad_recibida'] ?? 0) + $cantidad_recibida;
                $subtotalDetalle = floatval($detalle['cantidad']) * $precio_unitario;

                // Actualizar cantidad recibida, precio y subtotal en detalle
                $updateDetalle = "UPDATE orden_compra_detalle SET cantidad_recibida = ?, precio_unitario = ?, subtotal = ? WHERE id = ?";
                $stmtUpdate = $conn->prepare($updateDetalle);
                $stmtUpdate->bind_param("dddi", $nueva_cantidad_recibida, $precio_unitario, $subtotalDetalle, $detalle_id);
                $stmtUpdate->execute();

                $totalOrden += $subtotalDetalle;

                // Actualizar stock del producto
                $updateStock = "UPDATE productos SET stock = stock + ? WHERE id = ?";
                $stmtStock = $conn->prepare($updateStock);
                $stmtStock->bind_param("di", $cantidad_recibida, $detalle['producto_id']);
                $stmtStock->execute();

                // Verificar si falta recibir
                if ($nueva_cantidad_recibida < floatval($detalle['cantidad'])) {
                    $todoRecibido = false;
                }
            }

            // Recalcular total de la orden sumando todos los subtotales
            $queryTotalOrden = "SELECT SUM(subtotal) as total FROM orden_compra_detalle WHERE orden_compra_id = ?";
            $stmtTotalOrden = $conn->prepare($queryTotalOrden);
            $stmtTotalOrden->bind_param("i", $id);
            $stmtTotalOrden->execute();
            $resultTotal = $stmtTotalOrden->get_result();
            $rowTotal = $resultTotal->fetch_assoc();
            $totalOrden = floatval($rowTotal['total'] ?? 0);

            // Actualizar total en la orden
            $updateTotal = "UPDATE ordenes_compra SET subtotal = ?, total = ? WHERE id = ?";
            $stmtUpdateTotal = $conn->prepare($updateTotal);
            $stmtUpdateTotal->bind_param("ddi", $totalOrden, $totalOrden, $id);
            $stmtUpdateTotal->execute();

            // Verificar todos los detalles para determinar estado final
            $queryCheck = "SELECT SUM(cantidad) as total_ordenado, SUM(IFNULL(cantidad_recibida, 0)) as total_recibido
                          FROM orden_compra_detalle WHERE orden_compra_id = ?";
            $stmtCheck = $conn->prepare($queryCheck);
            $stmtCheck->bind_param("i", $id);
            $stmtCheck->execute();
            $resultCheck = $stmtCheck->get_result();
            $totales = $resultCheck->fetch_assoc();

            $todoRecibido = floatval($totales['total_recibido']) >= floatval($totales['total_ordenado']);

            // Actualizar estado de la orden y estado de pago
            $nuevoEstado = $todoRecibido ? ESTADO_RECIBIDA : ESTADO_RECIBIDA_PARCIAL;

            if ($todoRecibido) {
                if ($estado_pago === 'pagada') {
                    if ($recibido_por > 0) {
                        $updateOrden = "UPDATE ordenes_compra SET estado = ?, estado_pago = ?, fecha_recepcion = NOW(), fecha_pago = NOW(), recibido_por = ? WHERE id = ?";
                        $stmtOrden = $conn->prepare($updateOrden);
                        $stmtOrden->bind_param("ssii", $nuevoEstado, $estado_pago, $recibido_por, $id);
                    } else {
                        $updateOrden = "UPDATE ordenes_compra SET estado = ?, estado_pago = ?, fecha_recepcion = NOW(), fecha_pago = NOW() WHERE id = ?";
                        $stmtOrden = $conn->prepare($updateOrden);
                        $stmtOrden->bind_param("ssi", $nuevoEstado, $estado_pago, $id);
                    }
                } else {
                    if ($recibido_por > 0) {
                        $updateOrden = "UPDATE ordenes_compra SET estado = ?, estado_pago = ?, fecha_recepcion = NOW(), recibido_por = ? WHERE id = ?";
                        $stmtOrden = $conn->prepare($updateOrden);
                        $stmtOrden->bind_param("ssii", $nuevoEstado, $estado_pago, $recibido_por, $id);
                    } else {
                        $updateOrden = "UPDATE ordenes_compra SET estado = ?, estado_pago = ?, fecha_recepcion = NOW() WHERE id = ?";
                        $stmtOrden = $conn->prepare($updateOrden);
                        $stmtOrden->bind_param("ssi", $nuevoEstado, $estado_pago, $id);
                    }
                }
            } else {
                if ($recibido_por > 0) {
                    $updateOrden = "UPDATE ordenes_compra SET estado = ?, estado_pago = ?, recibido_por = ? WHERE id = ?";
                    $stmtOrden = $conn->prepare($updateOrden);
                    $stmtOrden->bind_param("ssii", $nuevoEstado, $estado_pago, $recibido_por, $id);
                } else {
                    $updateOrden = "UPDATE ordenes_compra SET estado = ?, estado_pago = ? WHERE id = ?";
                    $stmtOrden = $conn->prepare($updateOrden);
                    $stmtOrden->bind_param("ssi", $nuevoEstado, $estado_pago, $id);
                }
            }

            $stmtOrden->execute();

            $conn->commit();

            $mensaje = $todoRecibido ? "Orden recibida completamente" : "Recepción parcial registrada";
            if ($estado_pago === 'pendiente') {
                $mensaje .= " - Pendiente de pago";
            }
            sendResponse(true, $mensaje, ["estado" => $nuevoEstado, "estado_pago" => $estado_pago]);
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al recibir orden: " . $e->getMessage());
            sendResponse(false, "Error al recibir orden: " . $e->getMessage());
        }
        break;

    // Cancelar orden de compra
    case 'cancelarOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;
            $motivo = isset($datapost['motivo']) ? trim($datapost['motivo']) : '';

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            $checkQuery = "SELECT estado, notas FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] === ESTADO_RECIBIDA || $orden['estado'] === ESTADO_RECIBIDA_PARCIAL) {
                sendResponse(false, "No se pueden cancelar órdenes que ya tienen productos recibidos");
                break;
            }

            $nuevoEstado = ESTADO_CANCELADA;
            $nuevasNotas = ($orden['notas'] ? $orden['notas'] . "\n" : '') . "[CANCELADA] " . $motivo;

            $query = "UPDATE ordenes_compra SET estado = ?, notas = ? WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("ssi", $nuevoEstado, $nuevasNotas, $id);

            if ($stmt->execute()) {
                sendResponse(true, "Orden cancelada correctamente");
            } else {
                sendResponse(false, "Error al cancelar orden");
            }
        } catch (Exception $e) {
            error_log("Error al cancelar orden: " . $e->getMessage());
            sendResponse(false, "Error al cancelar orden");
        }
        break;

    // Eliminar orden (solo borradores)
    case 'eliminarOrdenCompra':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            $checkQuery = "SELECT estado FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado'] !== ESTADO_BORRADOR) {
                sendResponse(false, "Solo se pueden eliminar órdenes en estado borrador");
                break;
            }

            $conn->begin_transaction();

            // Eliminar detalles
            $deleteDetalles = "DELETE FROM orden_compra_detalle WHERE orden_compra_id = ?";
            $stmtDetalles = $conn->prepare($deleteDetalles);
            $stmtDetalles->bind_param("i", $id);
            $stmtDetalles->execute();

            // Eliminar orden
            $deleteOrden = "DELETE FROM ordenes_compra WHERE id = ?";
            $stmtOrden = $conn->prepare($deleteOrden);
            $stmtOrden->bind_param("i", $id);
            $stmtOrden->execute();

            $conn->commit();

            sendResponse(true, "Orden eliminada correctamente");
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error al eliminar orden: " . $e->getMessage());
            sendResponse(false, "Error al eliminar orden");
        }
        break;

    // Obtener órdenes por proveedor
    case 'getOrdenesCompraPorProveedor':
        try {
            $proveedor_id = isset($datapost['proveedor_id']) ? intval($datapost['proveedor_id']) : 0;

            if ($proveedor_id <= 0) {
                sendResponse(false, "ID de proveedor no válido");
                break;
            }

            $query = "SELECT oc.*, p.nombre as proveedor_nombre
                      FROM ordenes_compra oc
                      LEFT JOIN proveedores p ON oc.proveedor_id = p.id
                      WHERE oc.proveedor_id = ?
                      ORDER BY oc.fecha_creacion DESC";

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

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

            sendResponse(true, "Órdenes del proveedor obtenidas", $ordenes);
        } catch (Exception $e) {
            error_log("Error: " . $e->getMessage());
            sendResponse(false, "Error al obtener órdenes");
        }
        break;

    // Obtener órdenes por estado
    case 'getOrdenesCompraPorEstado':
        try {
            $estado = isset($datapost['estado']) ? trim($datapost['estado']) : '';

            if (empty($estado)) {
                sendResponse(false, "Estado no especificado");
                break;
            }

            $query = "SELECT oc.*, p.nombre as proveedor_nombre
                      FROM ordenes_compra oc
                      LEFT JOIN proveedores p ON oc.proveedor_id = p.id
                      WHERE oc.estado = ?
                      ORDER BY oc.fecha_creacion DESC";

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

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

            sendResponse(true, "Órdenes obtenidas", $ordenes);
        } catch (Exception $e) {
            error_log("Error: " . $e->getMessage());
            sendResponse(false, "Error al obtener órdenes");
        }
        break;

    // Obtener órdenes por fecha
    case 'getOrdenesCompraPorFecha':
        try {
            $fecha_inicio = isset($datapost['fecha_inicio']) ? $datapost['fecha_inicio'] : '';
            $fecha_fin = isset($datapost['fecha_fin']) ? $datapost['fecha_fin'] : '';

            $query = "SELECT oc.*, p.nombre as proveedor_nombre
                      FROM ordenes_compra oc
                      LEFT JOIN proveedores p ON oc.proveedor_id = p.id
                      WHERE DATE(oc.fecha_creacion) BETWEEN ? AND ?
                      ORDER BY oc.fecha_creacion DESC";

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

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

            sendResponse(true, "Órdenes obtenidas", $ordenes);
        } catch (Exception $e) {
            error_log("Error: " . $e->getMessage());
            sendResponse(false, "Error al obtener órdenes");
        }
        break;

    // ============== CUENTAS POR PAGAR (CXP) ==============

    // Obtener órdenes pendientes de pago
    case 'getCuentasPorPagar':
        try {
            $fecha_inicio = isset($datapost['fecha_inicio']) ? $datapost['fecha_inicio'] : '';
            $fecha_fin = isset($datapost['fecha_fin']) ? $datapost['fecha_fin'] : '';
            $proveedor_id = isset($datapost['proveedor_id']) ? intval($datapost['proveedor_id']) : 0;

            $query = "SELECT oc.*, p.nombre as proveedor_nombre, p.telefono as proveedor_telefono,
                      (SELECT COUNT(*) FROM orden_compra_detalle WHERE orden_compra_id = oc.id) as total_productos
                      FROM ordenes_compra oc
                      LEFT JOIN proveedores p ON oc.proveedor_id = p.id
                      WHERE oc.estado_pago = 'pendiente'
                      AND oc.estado IN ('recibida', 'recibida_parcial')";

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

            if (!empty($fecha_inicio) && !empty($fecha_fin)) {
                $query .= " AND DATE(oc.fecha_recepcion) BETWEEN ? AND ?";
                $params[] = $fecha_inicio;
                $params[] = $fecha_fin;
                $types .= "ss";
            }

            if ($proveedor_id > 0) {
                $query .= " AND oc.proveedor_id = ?";
                $params[] = $proveedor_id;
                $types .= "i";
            }

            $query .= " ORDER BY oc.fecha_recepcion ASC";

            if (!empty($params)) {
                $stmt = $conn->prepare($query);
                $stmt->bind_param($types, ...$params);
                $stmt->execute();
                $result = $stmt->get_result();
            } else {
                $result = $conn->query($query);
            }

            if (!$result) {
                sendResponse(false, "Error en consulta: " . $conn->error);
                break;
            }

            $ordenes = [];
            $totalPendiente = 0;
            while ($row = $result->fetch_assoc()) {
                $row['id'] = (int)$row['id'];
                $row['proveedor_id'] = (int)$row['proveedor_id'];
                $row['total'] = (float)$row['total'];
                $row['total_productos'] = (int)$row['total_productos'];
                $totalPendiente += (float)$row['total'];
                $ordenes[] = $row;
            }

            sendResponse(true, "Cuentas por pagar obtenidas", [
                'ordenes' => $ordenes,
                'total_pendiente' => $totalPendiente,
                'cantidad' => count($ordenes)
            ]);
        } catch (Exception $e) {
            error_log("Error al obtener CXP: " . $e->getMessage());
            sendResponse(false, "Error al obtener cuentas por pagar");
        }
        break;

    // Marcar orden como pagada
    case 'marcarComoPagada':
        try {
            $id = isset($datapost['id']) ? intval($datapost['id']) : 0;
            $pagado_por = isset($datapost['pagado_por']) && intval($datapost['pagado_por']) > 0 ? intval($datapost['pagado_por']) : null;

            if ($id <= 0) {
                sendResponse(false, "ID de orden no válido");
                break;
            }

            $checkQuery = "SELECT estado_pago FROM ordenes_compra WHERE id = ?";
            $checkStmt = $conn->prepare($checkQuery);
            $checkStmt->bind_param("i", $id);
            $checkStmt->execute();
            $checkResult = $checkStmt->get_result();
            $orden = $checkResult->fetch_assoc();

            if (!$orden) {
                sendResponse(false, "Orden no encontrada");
                break;
            }

            if ($orden['estado_pago'] === 'pagada') {
                sendResponse(false, "Esta orden ya está marcada como pagada");
                break;
            }

            $query = "UPDATE ordenes_compra SET estado_pago = 'pagada', fecha_pago = NOW() WHERE id = ?";
            $stmt = $conn->prepare($query);
            $stmt->bind_param("i", $id);

            if ($stmt->execute()) {
                sendResponse(true, "Orden marcada como pagada");
            } else {
                sendResponse(false, "Error al actualizar orden: " . $stmt->error);
            }
        } catch (Exception $e) {
            error_log("Error al marcar como pagada: " . $e->getMessage());
            sendResponse(false, "Error al marcar como pagada");
        }
        break;

    // Marcar múltiples órdenes como pagadas
    case 'marcarVariasComoPagadas':
        try {
            $ids = isset($datapost['ids']) ? $datapost['ids'] : [];

            if (empty($ids) || !is_array($ids)) {
                sendResponse(false, "Debe seleccionar al menos una orden");
                break;
            }

            $conn->begin_transaction();

            $query = "UPDATE ordenes_compra SET estado_pago = 'pagada', fecha_pago = NOW() WHERE id = ? AND estado_pago = 'pendiente'";
            $stmt = $conn->prepare($query);

            $actualizadas = 0;
            foreach ($ids as $id) {
                $id = intval($id);
                if ($id <= 0) continue;

                $stmt->bind_param("i", $id);
                $stmt->execute();
                if ($stmt->affected_rows > 0) {
                    $actualizadas++;
                }
            }

            $conn->commit();

            sendResponse(true, "$actualizadas orden(es) marcada(s) como pagada(s)", ['actualizadas' => $actualizadas]);
        } catch (Exception $e) {
            $conn->rollback();
            error_log("Error: " . $e->getMessage());
            sendResponse(false, "Error al marcar órdenes como pagadas");
        }
        break;

    // Resumen de CXP por proveedor
    case 'getResumenCXPPorProveedor':
        try {
            $query = "SELECT p.id, p.nombre, p.telefono, p.email,
                      COUNT(oc.id) as cantidad_ordenes,
                      SUM(oc.total) as total_pendiente,
                      MIN(oc.fecha_recepcion) as orden_mas_antigua
                      FROM ordenes_compra oc
                      INNER JOIN proveedores p ON oc.proveedor_id = p.id
                      WHERE oc.estado_pago = 'pendiente'
                      AND oc.estado IN ('recibida', 'recibida_parcial')
                      GROUP BY p.id, p.nombre, p.telefono, p.email
                      ORDER BY total_pendiente DESC";

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

            if (!$result) {
                sendResponse(false, "Error en consulta: " . $conn->error);
                break;
            }

            $proveedores = [];
            $totalGeneral = 0;
            while ($row = $result->fetch_assoc()) {
                $row['id'] = (int)$row['id'];
                $row['cantidad_ordenes'] = (int)$row['cantidad_ordenes'];
                $row['total_pendiente'] = (float)$row['total_pendiente'];
                $totalGeneral += $row['total_pendiente'];
                $proveedores[] = $row;
            }

            sendResponse(true, "Resumen obtenido", [
                'proveedores' => $proveedores,
                'total_general' => $totalGeneral
            ]);
        } catch (Exception $e) {
            error_log("Error: " . $e->getMessage());
            sendResponse(false, "Error al obtener resumen");
        }
        break;

    default:
        sendResponse(false, "Operación de órdenes de compra no válida: " . $tipo);
        break;
}
