#[derive(Debug, Clone)]
pub struct AnnConfig {
    pub dimensions: usize,
    pub max_neighbors: usize,
    pub max_base_neighbors: usize,
    pub ef_construction: usize,
    pub ef_search: usize,
    pub max_level: usize,
}

impl AnnConfig {
    pub fn for_dimensions(dimensions: usize) -> Self {
        Self {
            dimensions,
            max_neighbors: 24,
            max_base_neighbors: 24,
            ef_construction: 160,
            ef_search: 64,
            max_level: 16,
        }
    }
}

#[derive(Clone, Copy)]
pub struct AnnQuery<'a> {
    pub vector: &'a [f32],
    pub top_k: usize,
    pub ef_search: Option<usize>,
    pub filter: Option<&'a dyn AnnFilter>,
}

#[derive(Debug, Clone, PartialEq)]
pub struct AnnCandidate {
    pub id: String,
    pub score: f32,
}

pub trait AnnFilter {
    fn accept(&self, id: &str) -> bool;
}

impl<F> AnnFilter for F
where
    F: Fn(&str) -> bool,
{
    fn accept(&self, id: &str) -> bool {
        self(id)
    }
}

#[derive(Debug, thiserror::Error)]
pub enum AnnError {
    #[error("invalid ANN config: {0}")]
    InvalidConfig(String),
    #[error("invalid ANN vector: {0}")]
    InvalidVector(String),
    #[error("io error: {0}")]
    Io(#[from] std::io::Error),
    #[error("corrupted index snapshot: {0}")]
    Corrupted(String),
}
