//! GPU 索引构建加速模块
//!
//! Phase-59: 提供 CUDA 加速的向量索引构建能力。
//!
//! ## 架构设计
//!
//! 本模块采用 **双层安全降级** 策略：
//!
//! ### 编译时隔离 (Feature Gate)
//! 所有 GPU 代码通过 `#[cfg(feature = "gpu-index")]` 条件编译隔离。
//! 默认编译不包含 GPU 代码，零运行时开销。
//!
//! ### 运行时检测 (GPU Availability Probe)
//! 即使编译时开启了 `gpu-index` feature，运行时仍然检测：
//! 1. CUDA 驱动是否安装
//! 2. 是否有兼容的 GPU（Compute Capability ≥ 6.0）
//! 3. GPU 显存是否足够
//! 4. 检测失败 → 自动回退到 CPU 路径
//!
//! ## 模块结构
//!
//! - [`device`]: GPU 设备检测、选择与管理
//! - [`memory`]: GPU 内存池与 OOM 降级
//! - [`error`]: GPU 相关错误类型
//! - [`config`]: GPU 索引构建配置
//! - [`kmeans`]: GPU 加速 KMeans 聚类 (IVF 训练)
//! - [`quantization`]: GPU 加速向量量化 (PQ/SQ 训练)
//! - [`batch_builder`]: 流式分批构建器 (double buffering + OOM 自适应)
//! - [`cagra`]: CAGRA GPU-native 图索引
//! - [`pipeline`]: 端到端混合 CPU/GPU 索引构建管线
//! - [`bench`]: GPU 性能基准测试框架

pub mod device;
pub mod memory;
pub mod error;
pub mod config;
pub mod kmeans;
pub mod quantization;
pub mod batch_builder;
pub mod cagra;
pub mod pipeline;
pub mod bench;

// Re-export key types
pub use device::{GpuDevice, GpuDeviceInfo, GpuAvailability};
pub use memory::GpuMemoryPool;
pub use error::GpuError;
pub use config::{GpuIndexConfig, GpuBuildMode};
pub use kmeans::{GpuKMeansTrainer, GpuKMeansConfig, KMeansResult};
pub use quantization::{
    GpuSqTrainer, SqTrainConfig, SqParams,
    GpuPqTrainer, PqTrainConfig, PqCodebook,
};
pub use batch_builder::{
    StreamingBatchBuilder, BatchBuilderConfig, BatchProgress,
    VectorBatch, DoubleBuffer,
};
pub use cagra::{CagraIndex, CagraConfig, CagraSearchResult, CagraBuildStats};
pub use pipeline::{
    IndexBuildPipeline, PipelineResult, PipelineStage,
    DeviceUsed, IvfBuildResult, CagraBuildResult,
};
pub use bench::{BenchSuite, BenchConfig, BenchReport, BenchMeasurement};

/// Check if GPU acceleration is available at runtime.
///
/// This is a convenience wrapper that performs a quick probe:
/// 1. Checks if CUDA driver is accessible
/// 2. Enumerates compatible GPU devices
/// 3. Returns availability status with device info
///
/// This function is safe to call on any platform — it will return
/// `GpuAvailability::Unavailable` with a reason if no GPU is found.
///
/// # Example
/// ```ignore
/// use aifastdb_core::gpu::gpu_available;
///
/// match gpu_available() {
///     GpuAvailability::Available(devices) => {
///         println!("Found {} GPU(s)", devices.len());
///     }
///     GpuAvailability::Unavailable(reason) => {
///         println!("GPU not available: {}", reason);
///         // Will use CPU fallback automatically
///     }
/// }
/// ```
pub fn gpu_available() -> GpuAvailability {
    device::probe_gpu_availability()
}

/// Check if GPU index building should be used for the given data size.
///
/// Returns `true` only when:
/// 1. GPU hardware is available
/// 2. The data size justifies GPU overhead (>= 10K vectors)
/// 3. GPU memory is sufficient for the workload
///
/// When this returns `false`, the caller should use the CPU path.
pub fn should_use_gpu(num_vectors: usize, dimension: usize) -> bool {
    // GPU overhead makes it not worthwhile for small datasets
    const MIN_VECTORS_FOR_GPU: usize = 10_000;
    const MIN_DATA_BYTES_FOR_GPU: usize = 10 * 1024 * 1024; // 10MB

    if num_vectors < MIN_VECTORS_FOR_GPU {
        return false;
    }

    let data_size_bytes = num_vectors * dimension * std::mem::size_of::<f32>();
    if data_size_bytes < MIN_DATA_BYTES_FOR_GPU {
        return false;
    }

    match gpu_available() {
        GpuAvailability::Available(devices) => {
            // Check if any device has enough memory (need ~3x data size for working space)
            let required_memory = data_size_bytes * 3;
            devices.iter().any(|d| d.free_memory_bytes >= required_memory)
        }
        GpuAvailability::Unavailable(_) => false,
    }
}
