<?php

/**
 * Ventas.php - Manejo de ventas de productos
 */

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

// === REGISTRAR VENTA ===
if ($tipo === 'registrarVenta') {
    error_log("=== REGISTRANDO VENTA ===");

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

    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;
    $productos = isset($datapost['productos']) ? $datapost['productos'] : [];
    $total = isset($datapost['total']) ? (float)$datapost['total'] : 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");
    }

    if (empty($productos)) {
        sendResponse(false, "Debe incluir al menos un producto");
    }

    try {
        error_log("Registrando venta: Cliente ID=$clienteId, Total=$total, Productos=" . count($productos));

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

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

        $stmtVenta = $conn->prepare($queryVenta);
        $stmtVenta->bindParam(':cliente_id', $clienteId);
        $stmtVenta->bindParam(':repartidor_id', $repartidorId);
        $stmtVenta->bindParam(':visita_id', $visitaId);
        $stmtVenta->bindParam(':subtotal', $total);
        $stmtVenta->bindParam(':total', $total);
        $stmtVenta->bindParam(':forma_pago', $formaPago);
        $stmtVenta->bindParam(':notas', $notas);
        $stmtVenta->execute();

        $ventaId = $conn->lastInsertId();
        error_log("Venta creada con ID: $ventaId");

        // Insertar detalles de la venta y actualizar inventario del repartidor
        foreach ($productos as $producto) {
            $productoId = (int)$producto['producto_id'];
            $cantidad = (float)$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,
                                descuento,
                                subtotal,
                                created_at
                            ) VALUES (
                                :venta_id,
                                :producto_id,
                                :cantidad,
                                :precio_unitario,
                                0,
                                :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();

            // Actualizar inventario del repartidor (restar la cantidad vendida)
            // Permite ventas incluso sin stock (cantidad puede quedar en negativo)
            $queryInventarioRep = "UPDATE inventarios_repartidor
                                  SET cantidad = cantidad - :cantidad,
                                      updated_at = NOW()
                                  WHERE repartidor_id = :repartidor_id
                                    AND producto_id = :producto_id";

            $stmtInventarioRep = $conn->prepare($queryInventarioRep);
            $stmtInventarioRep->bindParam(':cantidad', $cantidad);
            $stmtInventarioRep->bindParam(':repartidor_id', $repartidorId);
            $stmtInventarioRep->bindParam(':producto_id', $productoId);
            $stmtInventarioRep->execute();

            // Si el producto no existe en el inventario del repartidor, crear registro con cantidad negativa
            if ($stmtInventarioRep->rowCount() === 0) {
                error_log("Producto ID=$productoId no existe en inventario del repartidor, creando registro con cantidad negativa");
                $queryInsertInventario = "INSERT INTO inventarios_repartidor (
                                            repartidor_id,
                                            producto_id,
                                            cantidad,
                                            created_at,
                                            updated_at
                                        ) VALUES (
                                            :repartidor_id,
                                            :producto_id,
                                            :cantidad_negativa,
                                            NOW(),
                                            NOW()
                                        )";
                $stmtInsertInventario = $conn->prepare($queryInsertInventario);
                $cantidadNegativa = -$cantidad;
                $stmtInsertInventario->bindParam(':repartidor_id', $repartidorId);
                $stmtInsertInventario->bindParam(':producto_id', $productoId);
                $stmtInsertInventario->bindParam(':cantidad_negativa', $cantidadNegativa);
                $stmtInsertInventario->execute();
            }

            // Registrar movimiento en el inventario del repartidor
            $queryMovimiento = "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()
                               )";

            $stmtMovimiento = $conn->prepare($queryMovimiento);
            $stmtMovimiento->bindParam(':repartidor_id', $repartidorId);
            $stmtMovimiento->bindParam(':producto_id', $productoId);
            $stmtMovimiento->bindParam(':cantidad', $cantidad);
            $stmtMovimiento->bindParam(':venta_id', $ventaId);
            $notasMovimiento = "Venta al cliente ID: $clienteId";
            $stmtMovimiento->bindParam(':notas', $notasMovimiento);
            $stmtMovimiento->execute();

            error_log("Producto ID=$productoId: Cantidad=$cantidad vendida, Inventario del repartidor actualizado");
        }

        // Si hay visita_id, actualizar la visita con información de venta
        if ($visitaId) {
            $productosJson = json_encode($productos);
            $cantidadTotal = array_sum(array_column($productos, 'cantidad'));

            $queryUpdateVisita = "UPDATE visitas_paradas
                                 SET tiene_venta = 1,
                                     monto_venta = :monto,
                                     forma_pago = :forma_pago,
                                     productos_entregados = :productos,
                                     cantidad_productos = :cantidad_productos,
                                     updated_at = NOW()
                                 WHERE id = :visita_id";

            $stmtUpdateVisita = $conn->prepare($queryUpdateVisita);
            $stmtUpdateVisita->bindParam(':monto', $total);
            $stmtUpdateVisita->bindParam(':forma_pago', $formaPago);
            $stmtUpdateVisita->bindParam(':productos', $productosJson);
            $stmtUpdateVisita->bindParam(':cantidad_productos', $cantidadTotal);
            $stmtUpdateVisita->bindParam(':visita_id', $visitaId);
            $stmtUpdateVisita->execute();

            error_log("Visita ID=$visitaId actualizada con información de venta");
        }

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

        // Preparar respuesta
        $respuesta = [
            'venta_id' => $ventaId,
            'cliente_id' => $clienteId,
            'total' => $total,
            'productos_count' => count($productos),
            'timestamp' => date('Y-m-d H:i:s')
        ];

        sendResponse(true, "Venta registrada exitosamente", $respuesta);

    } catch (Exception $e) {
        // Revertir transacción en caso de error
        if ($conn->inTransaction()) {
            $conn->rollBack();
        }

        error_log("Error registrando venta: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error registrando venta: " . $e->getMessage());
    }
}

// === OBTENER HISTORIAL DE VENTAS ===
if ($tipo === 'getHistorialVentas') {
    error_log("=== OBTENIENDO HISTORIAL DE VENTAS ===");

    // Obtener repartidor_id del parámetro
    $repartidorId = isset($datapost['repartidor_id']) ? (int)$datapost['repartidor_id'] : 0;
    $fechaInicio = isset($datapost['fecha_inicio']) ? $datapost['fecha_inicio'] : null;
    $fechaFin = isset($datapost['fecha_fin']) ? $datapost['fecha_fin'] : null;

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

    try {
        // Construir query base
        $query = "SELECT
                    v.id,
                    v.fecha_venta,
                    v.hora_venta,
                    v.total,
                    v.forma_pago,
                    v.estado,
                    v.notas,
                    COALESCE(c.nombre_comercial, CONCAT(c.nombre, ' ', COALESCE(c.apellidos, ''))) as cliente_nombre,
                    c.nombre_comercial,
                    CONCAT(v.fecha_venta, ' ', v.hora_venta) as fecha_venta_completa,
                    (SELECT COUNT(*) FROM ventas_detalle WHERE venta_id = v.id) as productos_count,
                    CONCAT('V-', LPAD(v.id, 6, '0')) as folio
                  FROM ventas v
                  LEFT JOIN clientes c ON v.cliente_id = c.id
                  WHERE v.repartidor_id = :repartidor_id";

        // Agregar filtros de fecha si están presentes
        if ($fechaInicio && $fechaFin) {
            $query .= " AND v.fecha_venta BETWEEN :fecha_inicio AND :fecha_fin";
        } elseif ($fechaInicio) {
            $query .= " AND v.fecha_venta >= :fecha_inicio";
        } elseif ($fechaFin) {
            $query .= " AND v.fecha_venta <= :fecha_fin";
        }

        $query .= " ORDER BY v.fecha_venta DESC, v.hora_venta DESC";

        error_log("Query historial: " . $query);
        error_log("Params: repartidor_id=$repartidorId, fecha_inicio=$fechaInicio, fecha_fin=$fechaFin");

        $stmt = $conn->prepare($query);
        $stmt->bindParam(':repartidor_id', $repartidorId, PDO::PARAM_INT);

        if ($fechaInicio && $fechaFin) {
            $stmt->bindParam(':fecha_inicio', $fechaInicio);
            $stmt->bindParam(':fecha_fin', $fechaFin);
        } elseif ($fechaInicio) {
            $stmt->bindParam(':fecha_inicio', $fechaInicio);
        } elseif ($fechaFin) {
            $stmt->bindParam(':fecha_fin', $fechaFin);
        }

        $stmt->execute();
        $ventas = $stmt->fetchAll(PDO::FETCH_ASSOC);

        error_log("Ventas encontradas: " . count($ventas));

        sendResponse(true, "Historial de ventas obtenido correctamente", $ventas);

    } catch (Exception $e) {
        error_log("Error obteniendo historial de ventas: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error obteniendo historial de ventas: " . $e->getMessage());
    }
}

// === OBTENER DETALLE DE VENTA ===
if ($tipo === 'getDetalleVenta') {
    error_log("=== OBTENIENDO DETALLE DE VENTA ===");

    // Obtener parámetros
    $ventaId = isset($datapost['venta_id']) ? (int)$datapost['venta_id'] : 0;
    $repartidorId = isset($datapost['repartidor_id']) ? (int)$datapost['repartidor_id'] : 0;

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

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

    try {
        // Obtener información de la venta
        $queryVenta = "SELECT
                        v.id,
                        v.fecha_venta,
                        v.hora_venta,
                        v.subtotal,
                        v.impuestos,
                        v.descuento,
                        v.total,
                        v.forma_pago,
                        v.estado,
                        v.notas,
                        COALESCE(c.nombre_comercial, CONCAT(c.nombre, ' ', COALESCE(c.apellidos, ''))) as cliente_nombre,
                        c.nombre_comercial,
                        CONCAT('V-', LPAD(v.id, 6, '0')) as folio
                      FROM ventas v
                      LEFT JOIN clientes c ON v.cliente_id = c.id
                      WHERE v.id = :venta_id AND v.repartidor_id = :repartidor_id";

        error_log("Query detalle venta: " . $queryVenta);
        error_log("Params: venta_id=$ventaId, repartidor_id=$repartidorId");

        $stmtVenta = $conn->prepare($queryVenta);
        $stmtVenta->bindParam(':venta_id', $ventaId, PDO::PARAM_INT);
        $stmtVenta->bindParam(':repartidor_id', $repartidorId, PDO::PARAM_INT);
        $stmtVenta->execute();

        $venta = $stmtVenta->fetch(PDO::FETCH_ASSOC);

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

        // Obtener productos de la venta
        $queryProductos = "SELECT
                            vd.id,
                            vd.producto_id,
                            vd.cantidad,
                            vd.precio_unitario,
                            vd.subtotal,
                            p.nombre as producto_nombre,
                            p.codigo as producto_codigo,
                            p.descripcion,
                            p.unidad_medida as unidad
                          FROM ventas_detalle vd
                          LEFT JOIN productos p ON vd.producto_id = p.id
                          WHERE vd.venta_id = :venta_id
                          ORDER BY vd.id";

        error_log("Query productos: " . $queryProductos);

        $stmtProductos = $conn->prepare($queryProductos);
        $stmtProductos->bindParam(':venta_id', $ventaId, PDO::PARAM_INT);
        $stmtProductos->execute();

        $productos = $stmtProductos->fetchAll(PDO::FETCH_ASSOC);

        error_log("Productos encontrados: " . count($productos));

        // Agregar productos a la venta
        $venta['productos'] = $productos;

        sendResponse(true, "Detalle de venta obtenido correctamente", $venta);

    } catch (Exception $e) {
        error_log("Error obteniendo detalle de venta: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error obteniendo detalle de venta: " . $e->getMessage());
    }
}

// === REPORTE DE VENTAS POR PRODUCTO Y MES ===
if ($tipo === 'getReporteVentasMensual') {
    error_log("=== GENERANDO REPORTE DE VENTAS MENSUAL ===");

    // Obtener parámetros
    $anio = isset($datapost['anio']) ? (int)$datapost['anio'] : date('Y');
    $rutaId = isset($datapost['ruta_id']) && $datapost['ruta_id'] !== '' ? (int)$datapost['ruta_id'] : null;
    $repartidorId = isset($datapost['repartidor_id']) && $datapost['repartidor_id'] !== '' ? (int)$datapost['repartidor_id'] : null;

    try {
        error_log("Parámetros: anio=$anio, ruta_id=$rutaId, repartidor_id=$repartidorId");

        // Query para obtener ventas agrupadas por producto y mes
        $query = "SELECT
                    p.id as producto_id,
                    p.codigo as producto_codigo,
                    p.nombre as producto_nombre,
                    MONTH(v.fecha_venta) as mes,
                    SUM(vd.subtotal) as total_ventas
                  FROM ventas v
                  INNER JOIN ventas_detalle vd ON v.id = vd.venta_id
                  INNER JOIN productos p ON vd.producto_id = p.id
                  WHERE YEAR(v.fecha_venta) = :anio
                    AND v.estado = 'completada'";

        // Filtro por repartidor (vendedor)
        if ($repartidorId) {
            $query .= " AND v.repartidor_id = :repartidor_id";
        }

        // Filtro por ruta (a través de la relación visita -> parada -> ruta)
        if ($rutaId) {
            $query .= " AND EXISTS (
                SELECT 1 FROM visitas_paradas vp
                INNER JOIN rutas_paradas rp ON vp.parada_id = rp.id
                WHERE vp.id = v.visita_id AND rp.ruta_id = :ruta_id
            )";
        }

        $query .= " GROUP BY p.id, p.codigo, p.nombre, MONTH(v.fecha_venta)
                    ORDER BY p.nombre, mes";

        error_log("Query reporte: " . $query);

        $stmt = $conn->prepare($query);
        $stmt->bindParam(':anio', $anio, PDO::PARAM_INT);

        if ($repartidorId) {
            $stmt->bindParam(':repartidor_id', $repartidorId, PDO::PARAM_INT);
        }
        if ($rutaId) {
            $stmt->bindParam(':ruta_id', $rutaId, PDO::PARAM_INT);
        }

        $stmt->execute();
        $resultados = $stmt->fetchAll(PDO::FETCH_ASSOC);

        error_log("Resultados obtenidos: " . count($resultados));

        // Procesar resultados para agrupar por producto
        $productosMap = [];
        foreach ($resultados as $row) {
            $productoId = $row['producto_id'];

            if (!isset($productosMap[$productoId])) {
                $productosMap[$productoId] = [
                    'id' => $productoId,
                    'codigo' => $row['producto_codigo'],
                    'nombre' => $row['producto_nombre'],
                    'ventas' => array_fill(0, 12, 0) // Inicializar 12 meses con 0
                ];
            }

            // El mes viene de 1-12, convertir a índice 0-11
            $mesIndex = (int)$row['mes'] - 1;
            $productosMap[$productoId]['ventas'][$mesIndex] = (float)$row['total_ventas'];
        }

        // Convertir a array y calcular totales
        $productos = array_values($productosMap);

        // Calcular totales por mes
        $totalesMensuales = array_fill(0, 12, 0);
        foreach ($productos as $producto) {
            for ($i = 0; $i < 12; $i++) {
                $totalesMensuales[$i] += $producto['ventas'][$i];
            }
        }

        $respuesta = [
            'anio' => $anio,
            'productos' => $productos,
            'totales' => $totalesMensuales,
            'total_general' => array_sum($totalesMensuales)
        ];

        sendResponse(true, "Reporte generado correctamente", $respuesta);

    } catch (Exception $e) {
        error_log("Error generando reporte de ventas: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error generando reporte: " . $e->getMessage());
    }
}

// === OBTENER ÚLTIMAS COMPRAS DEL CLIENTE ===
if ($tipo === 'getUltimasComprasCliente') {
    error_log("=== OBTENIENDO ÚLTIMAS COMPRAS DEL CLIENTE ===");

    // Obtener parámetros
    $clienteId = isset($datapost['cliente_id']) ? (int)$datapost['cliente_id'] : 0;
    $limite = isset($datapost['limite']) ? (int)$datapost['limite'] : 5;

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

    try {
        // Obtener últimas ventas del cliente
        $queryVentas = "SELECT
                        v.id,
                        v.fecha_venta,
                        v.hora_venta,
                        v.total,
                        v.forma_pago,
                        v.estado,
                        CONCAT(v.fecha_venta, ' ', v.hora_venta) as fecha_venta_completa,
                        CONCAT('V-', LPAD(v.id, 6, '0')) as folio,
                        (SELECT COUNT(*) FROM ventas_detalle WHERE venta_id = v.id) as productos_count
                      FROM ventas v
                      WHERE v.cliente_id = :cliente_id
                        AND v.estado = 'completada'
                      ORDER BY v.fecha_venta DESC, v.hora_venta DESC
                      LIMIT :limite";

        error_log("Query últimas compras: " . $queryVentas);
        error_log("Params: cliente_id=$clienteId, limite=$limite");

        $stmt = $conn->prepare($queryVentas);
        $stmt->bindParam(':cliente_id', $clienteId, PDO::PARAM_INT);
        $stmt->bindParam(':limite', $limite, PDO::PARAM_INT);
        $stmt->execute();

        $ventas = $stmt->fetchAll(PDO::FETCH_ASSOC);

        error_log("Últimas compras encontradas: " . count($ventas));

        // Para cada venta, obtener los primeros 3 productos con detalles
        foreach ($ventas as &$venta) {
            $queryProductos = "SELECT
                                vd.cantidad,
                                vd.precio_unitario,
                                vd.subtotal,
                                COALESCE(p.nombre, 'Producto') as producto_nombre
                              FROM ventas_detalle vd
                              LEFT JOIN productos p ON vd.producto_id = p.id
                              WHERE vd.venta_id = :venta_id
                              LIMIT 3";

            $stmtProductos = $conn->prepare($queryProductos);
            $stmtProductos->bindParam(':venta_id', $venta['id'], PDO::PARAM_INT);
            $stmtProductos->execute();

            $venta['productos'] = $stmtProductos->fetchAll(PDO::FETCH_ASSOC);
        }

        sendResponse(true, "Últimas compras obtenidas correctamente", $ventas);

    } catch (Exception $e) {
        error_log("Error obteniendo últimas compras: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error obteniendo últimas compras: " . $e->getMessage());
    }
}

// === REPORTE BASE (DETALLE POR CLIENTE Y PRODUCTO) ===
if ($tipo === 'getReporteBaseMensual') {
    error_log("=== GENERANDO REPORTE BASE ===");

    // Obtener parámetros
    $anio = isset($datapost['anio']) ? (int)$datapost['anio'] : date('Y');
    $repartidorId = isset($datapost['repartidor_id']) && $datapost['repartidor_id'] !== '' ? (int)$datapost['repartidor_id'] : null;

    try {
        error_log("Parámetros: anio=$anio, repartidor_id=$repartidorId");

        // Query para obtener detalle por cliente y producto
        $query = "SELECT
                    c.codigo as cliente_codigo,
                    COALESCE(c.nombre_comercial, CONCAT(c.nombre, ' ', COALESCE(c.apellidos, ''))) as nombre_comercial,
                    r.nombre as vendedor,
                    c.direccion,
                    YEAR(v.fecha_venta) as anio_venta,
                    COALESCE(cat.nombre, 'Sin categoría') as categoria,
                    p.nombre as producto,
                    SUM(vd.cantidad) as cantidad
                  FROM ventas v
                  INNER JOIN ventas_detalle vd ON v.id = vd.venta_id
                  INNER JOIN productos p ON vd.producto_id = p.id
                  LEFT JOIN categorias_productos cat ON p.categoria_id = cat.id
                  INNER JOIN clientes c ON v.cliente_id = c.id
                  INNER JOIN repartidores r ON v.repartidor_id = r.id
                  WHERE YEAR(v.fecha_venta) = :anio
                    AND v.estado = 'completada'";

        // Filtro por repartidor (vendedor)
        if ($repartidorId) {
            $query .= " AND v.repartidor_id = :repartidor_id";
        }

        $query .= " GROUP BY c.id, c.codigo, c.nombre_comercial, c.nombre, c.apellidos,
                           r.nombre, c.direccion,
                           YEAR(v.fecha_venta), cat.nombre, p.id, p.nombre
                    ORDER BY c.codigo, p.nombre";

        error_log("Query reporte base: " . $query);

        $stmt = $conn->prepare($query);
        $stmt->bindParam(':anio', $anio, PDO::PARAM_INT);

        if ($repartidorId) {
            $stmt->bindParam(':repartidor_id', $repartidorId, PDO::PARAM_INT);
        }

        $stmt->execute();
        $resultados = $stmt->fetchAll(PDO::FETCH_ASSOC);

        error_log("Resultados obtenidos: " . count($resultados));

        // Procesar resultados para extraer municipio y estado de la dirección
        // Formato: "Calle 123, Colonia, 20416 Municipio, Estado., País"
        $registros = [];
        foreach ($resultados as $row) {
            $municipio = '';
            $estado = '';

            // Extraer municipio y estado de la dirección
            if (!empty($row['direccion'])) {
                $direccion = $row['direccion'];
                $partes = array_map('trim', explode(',', $direccion));
                $numPartes = count($partes);

                // Formato esperado: "Calle, Colonia, CP Municipio, Estado, País"
                if ($numPartes >= 4) {
                    // Estado está en la penúltima posición (antes de País)
                    $estado = trim($partes[$numPartes - 2]);
                    // Limpiar el punto si existe (ej: "Ags." -> "Ags")
                    $estado = rtrim($estado, '.');

                    // Municipio está en la antepenúltima posición, puede tener CP
                    $cpMunicipio = trim($partes[$numPartes - 3]);
                    // Remover el código postal (5 dígitos al inicio)
                    $municipio = preg_replace('/^\d{5}\s*/', '', $cpMunicipio);
                }
            }

            $registros[] = [
                'cliente_codigo' => $row['cliente_codigo'],
                'nombre_comercial' => $row['nombre_comercial'],
                'vendedor' => $row['vendedor'],
                'municipio' => $municipio ?: 'N/A',
                'estado' => $estado ?: 'N/A',
                'anio_venta' => $row['anio_venta'],
                'categoria' => $row['categoria'],
                'producto' => $row['producto'],
                'cantidad' => (float)$row['cantidad']
            ];
        }

        // Calcular total general
        $totalCantidad = array_sum(array_column($registros, 'cantidad'));

        $respuesta = [
            'anio' => $anio,
            'registros' => $registros,
            'total_registros' => count($registros),
            'total_cantidad' => $totalCantidad
        ];

        sendResponse(true, "Reporte base generado correctamente", $respuesta);

    } catch (Exception $e) {
        error_log("Error generando reporte base: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error generando reporte base: " . $e->getMessage());
    }
}

// === REPORTE DE CLIENTES ===
if ($tipo === 'getReporteClientes') {
    error_log("=== GENERANDO REPORTE DE CLIENTES ===");

    try {
        // Query para obtener todos los clientes
        $query = "SELECT
                    c.codigo,
                    COALESCE(c.nombre_comercial, CONCAT(c.nombre, ' ', COALESCE(c.apellidos, ''))) as nombre_comercial,
                    c.direccion
                  FROM clientes c
                  WHERE c.activo = 1
                  ORDER BY c.codigo";

        error_log("Query reporte clientes: " . $query);

        $stmt = $conn->prepare($query);
        $stmt->execute();
        $resultados = $stmt->fetchAll(PDO::FETCH_ASSOC);

        error_log("Clientes obtenidos: " . count($resultados));

        // Procesar resultados
        $registros = [];
        foreach ($resultados as $row) {
            $municipio = '';
            $estado = '';

            // Extraer municipio y estado de la dirección
            if (!empty($row['direccion'])) {
                $direccion = $row['direccion'];
                $partes = array_map('trim', explode(',', $direccion));
                $numPartes = count($partes);

                if ($numPartes >= 4) {
                    $estado = trim($partes[$numPartes - 2]);
                    $estado = rtrim($estado, '.');

                    $cpMunicipio = trim($partes[$numPartes - 3]);
                    $municipio = preg_replace('/^\d{5}\s*/', '', $cpMunicipio);
                }
            }

            // Extraer perfil (primera palabra del nombre comercial)
            $nombreComercial = $row['nombre_comercial'] ?: '';
            $palabras = explode(' ', trim($nombreComercial));
            $perfil = $palabras[0] ?? '';

            $registros[] = [
                'codigo' => $row['codigo'],
                'nombre_comercial' => $nombreComercial,
                'estado' => $estado ?: 'N/A',
                'municipio' => $municipio ?: 'N/A',
                'perfil' => $perfil ?: 'N/A'
            ];
        }

        $respuesta = [
            'registros' => $registros,
            'total_registros' => count($registros)
        ];

        sendResponse(true, "Reporte de clientes generado correctamente", $respuesta);

    } catch (Exception $e) {
        error_log("Error generando reporte de clientes: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error generando reporte de clientes: " . $e->getMessage());
    }
}

// === REPORTE DE PRODUCTOS ===
if ($tipo === 'getReporteProductos') {
    error_log("=== GENERANDO REPORTE DE PRODUCTOS ===");

    try {
        $query = "SELECT
                    p.codigo,
                    p.nombre,
                    COALESCE(cat.nombre, 'Sin categoría') as categoria,
                    p.precio
                  FROM productos p
                  LEFT JOIN categorias_productos cat ON p.categoria_id = cat.id
                  WHERE p.activo = 1
                  ORDER BY p.codigo";

        error_log("Query reporte productos: " . $query);

        $stmt = $conn->prepare($query);
        $stmt->execute();
        $resultados = $stmt->fetchAll(PDO::FETCH_ASSOC);

        error_log("Productos obtenidos: " . count($resultados));

        $registros = [];
        foreach ($resultados as $row) {
            $registros[] = [
                'codigo' => $row['codigo'],
                'nombre' => $row['nombre'],
                'categoria' => $row['categoria'],
                'precio' => (float)$row['precio']
            ];
        }

        $respuesta = [
            'registros' => $registros,
            'total_registros' => count($registros)
        ];

        sendResponse(true, "Reporte de productos generado correctamente", $respuesta);

    } catch (Exception $e) {
        error_log("Error generando reporte de productos: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error generando reporte de productos: " . $e->getMessage());
    }
}

// === REPORTE RTM TOP 3 (Top 3 clientes por producto) ===
if ($tipo === 'getReporteRTMTop3') {
    error_log("=== GENERANDO REPORTE RTM TOP 3 ===");

    // Obtener filtros
    $anio = isset($datapost['anio']) ? (int)$datapost['anio'] : date('Y');
    $mes = isset($datapost['mes']) && !empty($datapost['mes']) ? (int)$datapost['mes'] : null;
    $productoIdFiltro = isset($datapost['producto_id']) && !empty($datapost['producto_id']) ? (int)$datapost['producto_id'] : null;

    error_log("Filtros RTM: anio=$anio, mes=$mes, producto_id=$productoIdFiltro");

    try {
        // Obtener productos (todos activos o solo el seleccionado)
        if ($productoIdFiltro) {
            $queryProductos = "SELECT id, codigo, nombre FROM productos WHERE activo = 1 AND id = :producto_id";
            $stmtProductos = $conn->prepare($queryProductos);
            $stmtProductos->bindParam(':producto_id', $productoIdFiltro, PDO::PARAM_INT);
        } else {
            $queryProductos = "SELECT id, codigo, nombre FROM productos WHERE activo = 1 ORDER BY nombre";
            $stmtProductos = $conn->prepare($queryProductos);
        }
        $stmtProductos->execute();
        $productos = $stmtProductos->fetchAll(PDO::FETCH_ASSOC);

        $registros = [];

        foreach ($productos as $producto) {
            // Para cada producto, obtener los top 3 clientes con filtros de fecha
            $queryTop = "SELECT
                            c.codigo as cliente_codigo,
                            COALESCE(c.nombre_comercial, CONCAT(c.nombre, ' ', COALESCE(c.apellidos, ''))) as cliente_nombre,
                            SUM(vd.cantidad) as total_cantidad
                         FROM ventas_detalle vd
                         INNER JOIN ventas v ON vd.venta_id = v.id
                         INNER JOIN clientes c ON v.cliente_id = c.id
                         WHERE vd.producto_id = :producto_id
                           AND v.estado = 'completada'
                           AND YEAR(v.fecha_venta) = :anio";

            // Agregar filtro de mes si se especificó
            if ($mes) {
                $queryTop .= " AND MONTH(v.fecha_venta) = :mes";
            }

            $queryTop .= " GROUP BY c.id, c.codigo, c.nombre_comercial, c.nombre, c.apellidos
                         ORDER BY total_cantidad DESC
                         LIMIT 3";

            $stmtTop = $conn->prepare($queryTop);
            $stmtTop->bindParam(':producto_id', $producto['id'], PDO::PARAM_INT);
            $stmtTop->bindParam(':anio', $anio, PDO::PARAM_INT);
            if ($mes) {
                $stmtTop->bindParam(':mes', $mes, PDO::PARAM_INT);
            }
            $stmtTop->execute();
            $topClientes = $stmtTop->fetchAll(PDO::FETCH_ASSOC);

            // Solo agregar productos que tienen ventas
            if (count($topClientes) > 0) {
                $registros[] = [
                    'producto_codigo' => $producto['codigo'],
                    'producto_nombre' => $producto['nombre'],
                    'top1_codigo' => $topClientes[0]['cliente_codigo'] ?? '',
                    'top1_nombre' => $topClientes[0]['cliente_nombre'] ?? '',
                    'top1_cantidad' => (float)($topClientes[0]['total_cantidad'] ?? 0),
                    'top2_codigo' => $topClientes[1]['cliente_codigo'] ?? '',
                    'top2_nombre' => $topClientes[1]['cliente_nombre'] ?? '',
                    'top2_cantidad' => (float)($topClientes[1]['total_cantidad'] ?? 0),
                    'top3_codigo' => $topClientes[2]['cliente_codigo'] ?? '',
                    'top3_nombre' => $topClientes[2]['cliente_nombre'] ?? '',
                    'top3_cantidad' => (float)($topClientes[2]['total_cantidad'] ?? 0)
                ];
            }
        }

        error_log("Productos con ventas: " . count($registros));

        $respuesta = [
            'registros' => $registros,
            'total_registros' => count($registros),
            'filtros' => [
                'anio' => $anio,
                'mes' => $mes,
                'producto_id' => $productoIdFiltro
            ]
        ];

        sendResponse(true, "Reporte RTM Top 3 generado correctamente", $respuesta);

    } catch (Exception $e) {
        error_log("Error generando reporte RTM Top 3: " . $e->getMessage());
        error_log("Stack trace: " . $e->getTraceAsString());
        sendResponse(false, "Error generando reporte RTM Top 3: " . $e->getMessage());
    }
}
