//! Concurrent HNSW Index for high-throughput vector operations
//!
//! This module provides a sharded, high-concurrency wrapper around HNSWIndex,
//! reusing the existing concurrent components from storage module.
//!
//! # Architecture
//!
//! ```text
//! ConcurrentHNSWIndex
//!     └── VectorShardRouter
//!             ├── VectorShard[0] (HNSWIndex + WriteQueue + BatchAggregator)
//!             ├── VectorShard[1]
//!             ├── ...
//!             └── VectorShard[N-1]
//!             │
//!             ├── BackpressureController
//!             ├── GlobalVectorIndex
//!             └── WriteMetrics
//! ```
//!
//! # Features
//!
//! - **Sharded Storage**: Distributes vectors across multiple HNSW indices
//! - **Write Queue**: Async buffering for high-throughput writes
//! - **Batch Aggregation**: Groups writes for efficient processing
//! - **Backpressure Control**: Prevents system overload
//! - **Cross-shard Search**: Parallel search across all shards
//!
//! # Example
//!
//! ```ignore
//! use aifastdb_core::vector::concurrent::{ConcurrentHNSWIndex, ConcurrentHNSWConfig};
//!
//! let config = ConcurrentHNSWConfig::default();
//! let index = ConcurrentHNSWIndex::new(config);
//!
//! // Async insert
//! index.insert("vec_1".to_string(), vec![1.0; 128]).await?;
//!
//! // Search across all shards
//! let results = index.search(&query_vector, 10);
//! ```

pub mod config;
pub mod types;
pub mod shard;
pub mod router;
pub mod global_index;

#[cfg(test)]
mod tests;

// Re-export main types
pub use config::ConcurrentHNSWConfig;
pub use types::{VectorWriteOp, VectorWriteRequest, VectorWriteResult, VectorShardError, VectorSearchResult};
pub use shard::VectorShard;
pub use router::VectorShardRouter;
pub use global_index::GlobalVectorIndex;

use std::sync::Arc;
use crate::types::HNSWConfig;
use crate::storage::concurrent::{MetricsSnapshot, BackpressureAction};

/// Concurrent HNSW Index with sharded storage and async write support
/// 
/// This is the main entry point for high-concurrency vector operations.
/// It wraps multiple HNSW indices (shards) and provides:
/// - Async insert with write queuing
/// - Parallel search across shards
/// - Backpressure control
/// - Performance metrics
pub struct ConcurrentHNSWIndex {
    /// Shard router
    router: Arc<VectorShardRouter>,
}

impl ConcurrentHNSWIndex {
    /// Create a new concurrent HNSW index
    pub fn new(config: ConcurrentHNSWConfig) -> Self {
        let router = VectorShardRouter::new(config);
        Self {
            router: Arc::new(router),
        }
    }
    
    /// Create with high-throughput configuration
    pub fn high_throughput(hnsw_config: HNSWConfig) -> Self {
        let config = ConcurrentHNSWConfig::high_throughput(hnsw_config);
        Self::new(config)
    }
    
    /// Create with low-latency configuration
    pub fn low_latency(hnsw_config: HNSWConfig) -> Self {
        let config = ConcurrentHNSWConfig::low_latency(hnsw_config);
        Self::new(config)
    }
    
    // ========================================================================
    // Async Write API
    // ========================================================================
    
    /// Insert a vector asynchronously
    /// 
    /// The write is queued and batched for efficiency.
    /// Returns immediately after queuing (doesn't wait for persistence).
    pub async fn insert(&self, id: String, vector: Vec<f32>) -> Result<VectorWriteResult, VectorShardError> {
        self.router.insert(id, vector).await
    }
    
    /// Insert a vector and wait for completion
    pub async fn insert_sync(&self, id: String, vector: Vec<f32>) -> Result<VectorWriteResult, VectorShardError> {
        self.router.insert_sync(id, vector).await
    }
    
    /// Batch insert multiple vectors
    pub async fn insert_batch(&self, items: Vec<(String, Vec<f32>)>) -> Result<Vec<VectorWriteResult>, VectorShardError> {
        self.router.insert_batch(items).await
    }
    
    /// Delete a vector
    pub async fn delete(&self, id: &str) -> Result<VectorWriteResult, VectorShardError> {
        self.router.delete(id).await
    }
    
    // ========================================================================
    // Read API (Sync)
    // ========================================================================
    
    /// Search for k nearest neighbors
    /// 
    /// Searches all shards in parallel and merges results.
    pub fn search(&self, query: &[f32], k: usize) -> Vec<VectorSearchResult> {
        self.router.search(query, k)
    }
    
    /// Search with ef parameter override
    pub fn search_with_ef(&self, query: &[f32], k: usize, ef: usize) -> Vec<VectorSearchResult> {
        self.router.search_with_ef(query, k, ef)
    }
    
    /// Get a vector by ID
    pub fn get(&self, id: &str) -> Option<Arc<Vec<f32>>> {
        self.router.get(id)
    }
    
    /// Check if a vector exists
    pub fn contains(&self, id: &str) -> bool {
        self.router.contains(id)
    }
    
    /// Get total number of vectors across all shards
    pub fn len(&self) -> usize {
        self.router.len()
    }
    
    /// Check if index is empty
    pub fn is_empty(&self) -> bool {
        self.len() == 0
    }
    
    // ========================================================================
    // Management API
    // ========================================================================
    
    /// Get performance metrics
    pub fn metrics(&self) -> MetricsSnapshot {
        self.router.metrics()
    }
    
    /// Get queue fill ratio (0.0 - 1.0)
    pub fn queue_fill_ratio(&self) -> f64 {
        self.router.queue_fill_ratio()
    }
    
    /// Flush all pending writes
    pub async fn flush(&self) -> Result<(), VectorShardError> {
        self.router.flush().await
    }
    
    /// Check backpressure status
    pub fn backpressure_status(&self) -> BackpressureAction {
        self.router.backpressure_status()
    }
    
    /// Get number of shards
    pub fn shard_count(&self) -> usize {
        self.router.shard_count()
    }
    
    /// Get shard statistics
    pub fn shard_stats(&self) -> Vec<(usize, usize)> {
        self.router.shard_stats()
    }
}

impl Clone for ConcurrentHNSWIndex {
    fn clone(&self) -> Self {
        Self {
            router: Arc::clone(&self.router),
        }
    }
}
