use crate::trace::Trace;

/// Resolve a short signal name within a scope prefix to a full path.
/// For example, resolve("tb.dut", "counter", trace) -> Some("tb.dut.counter")
pub fn resolve(trace: &dyn Trace, scope: &str, short_name: &str) -> Option<String> {
    let candidate = if scope.is_empty() {
        short_name.to_string()
    } else {
        format!("{}.{}", scope, short_name)
    };
    if trace.signal_id(&candidate).is_some() {
        return Some(candidate);
    }
    // Try finding any signal ending with the short name
    for name in trace.signal_names() {
        if name.ends_with(short_name) {
            let prefix = &name[..name.len() - short_name.len()];
            if prefix.is_empty() || prefix.ends_with('.') {
                if scope.is_empty() || name.starts_with(scope) {
                    return Some(name.clone());
                }
            }
        }
    }
    None
}

/// List signals that are direct children of the given scope.
pub fn local_signals(trace: &dyn Trace, scope: &str) -> Vec<String> {
    let prefix = if scope.is_empty() {
        String::new()
    } else {
        format!("{}.", scope)
    };

    trace
        .signal_names()
        .iter()
        .filter(|name| {
            if prefix.is_empty() {
                !name.contains('.')
            } else if let Some(rest) = name.strip_prefix(&prefix) {
                !rest.contains('.')
            } else {
                false
            }
        })
        .cloned()
        .collect()
}

/// List child scopes of the given scope.
pub fn local_scopes(trace: &dyn Trace, scope: &str) -> Vec<String> {
    let prefix = if scope.is_empty() {
        String::new()
    } else {
        format!("{}.", scope)
    };

    let mut result: Vec<String> = Vec::new();
    for s in trace.scopes() {
        if prefix.is_empty() {
            if !s.contains('.') && !result.contains(s) {
                result.push(s.clone());
            }
        } else if let Some(rest) = s.strip_prefix(&prefix) {
            // Direct child scope: no more dots
            let child = rest.split('.').next().unwrap_or(rest);
            let full = format!("{}.{}", scope, child);
            if !result.contains(&full) {
                result.push(full);
            }
        }
    }
    result
}
