use crate::utils::aliases::{ARlockmap, JsonMap, TResult};
use tera::{Function, Value};

pub struct LinkFunction {
    pub url_registry: ARlockmap,
}

impl Function for LinkFunction {
    fn call(&self, args: &JsonMap) -> TResult {
        link_function(args, &self.url_registry)
    }
}

fn link_function(args: &JsonMap, url_registry: &ARlockmap) -> TResult {
    let link_name = args
        .get("link")
        .and_then(|v| v.as_str())
        .ok_or_else(|| tera::Error::msg("link() nécessite un argument 'link'"))?;

    let map = url_registry.read().unwrap();
    let pattern = map.get(link_name).cloned().ok_or_else(|| {
        tera::Error::msg(format!(
            "Route '{}' introuvable.\n\nVérifiez que la route existe dans vos routes !",
            link_name
        ))
    })?;
    drop(map);

    // Substituer les paramètres {id}, {slug}, etc.
    let result = args
        .iter()
        .filter(|(k, _)| *k != "link")
        .fold(pattern, |acc, (k, v)| {
            let value = match v {
                Value::String(s) => s.clone(),
                Value::Number(n) => n.to_string(),
                _ => v.to_string(),
            };
            acc.replace(&format!("{{{}}}", k), &value)
        });

    Ok(Value::String(result))
}
