use crate::lenses::{apply_stack, Lens, LensContext, LensOutput};

pub type MatcherFn = Box<dyn Fn(&str, &[String]) -> bool + Send + Sync>;
pub type PreprocessorFn = Box<dyn Fn(&str, &LensContext) -> String + Send + Sync>;

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum FallbackPolicy {
    Passthrough,
    WarnAndPassthrough,
}

pub struct MeshNode {
    pub name: String,
    pub matcher: MatcherFn,
    pub lens_stack: Vec<Box<dyn Lens>>,
    pub fallback: FallbackPolicy,
    /// Optional domain-specific pre-processor: runs before lens stack.
    pub preprocessor: Option<PreprocessorFn>,
}

impl MeshNode {
    pub fn apply(&self, input: &str, ctx: &LensContext) -> LensOutput {
        let pre = match &self.preprocessor {
            Some(f) => f(input, ctx),
            None => input.to_string(),
        };
        apply_stack(&self.lens_stack, &pre, ctx)
    }
}
