//! Planner configuration for strategy selection thresholds.

/// Configuration for the adaptive query planner's strategy selection thresholds.
///
/// All selectivity values are in `[0.0, 1.0]` where `1.0` means "all vectors
/// pass the filter" and `0.0` means "no vectors pass."
#[derive(Debug, Clone)]
pub struct PlannerConfig {
    /// Minimum selectivity for in-graph filtering with default `ef_search`.
    /// Below this threshold, the planner widens the beam.
    /// Default: `0.20` (20%).
    pub in_graph_min_selectivity: f64,

    /// Maximum selectivity for pre-filter brute-force.
    /// Below this threshold, the planner switches to brute-force exact search.
    /// Default: `0.01` (1%).
    pub brute_force_max_selectivity: f64,

    /// `ef_search` multiplier for the 5-20% selectivity range.
    /// Default: `2.0` (e.g., 200 * 2.0 = 400).
    pub ef_search_multiplier_moderate: f64,

    /// `ef_search` multiplier for the 1-5% selectivity range.
    /// Default: `3.0` (e.g., 200 * 3.0 = 600).
    pub ef_search_multiplier_low: f64,

    /// Default beam width for unfiltered and in-graph-filtered searches.
    /// This is the baseline `ef_search` value that multipliers scale from.
    /// Default: `200`.
    pub default_ef_search: usize,
}

impl Default for PlannerConfig {
    fn default() -> Self {
        Self {
            in_graph_min_selectivity: 0.20,
            brute_force_max_selectivity: 0.01,
            ef_search_multiplier_moderate: 2.0,
            ef_search_multiplier_low: 3.0,
            default_ef_search: 200,
        }
    }
}

// ---------------------------------------------------------------------------
// Tests
// ---------------------------------------------------------------------------

#[cfg(test)]
#[allow(clippy::unwrap_used)]
mod tests {
    use super::*;

    #[test]
    fn planner_config_defaults() {
        let config = PlannerConfig::default();
        assert!((config.in_graph_min_selectivity - 0.20).abs() < f64::EPSILON);
        assert!((config.brute_force_max_selectivity - 0.01).abs() < f64::EPSILON);
        assert!((config.ef_search_multiplier_moderate - 2.0).abs() < f64::EPSILON);
        assert!((config.ef_search_multiplier_low - 3.0).abs() < f64::EPSILON);
        assert_eq!(config.default_ef_search, 200);
    }
}
