//! Condition parsing: `var == "value"` and `var != "value"`.

use super::node::{CmpOp, Cond};

/// Parse a condition string like `role == "admin"` or `type != "error"`.
pub fn parse_condition(s: &str, var_names: &[&str]) -> Result<Cond, String> {
    let s = s.trim();

    let (var_part, op, val_part) = if let Some(pos) = s.find("==") {
        (&s[..pos], CmpOp::Eq, &s[pos + 2..])
    } else if let Some(pos) = s.find("!=") {
        (&s[..pos], CmpOp::Neq, &s[pos + 2..])
    } else {
        return Err(format!(
            "invalid condition '{s}': expected 'var == \"value\"' or 'var != \"value\"'"
        ));
    };

    let var_part = var_part.trim();
    let var_idx = var_names
        .iter()
        .position(|n| *n == var_part)
        .ok_or_else(|| format!("unknown var '{var_part}' in condition"))?;
    let var_idx =
        u16::try_from(var_idx).map_err(|_| format!("too many vars (max {})", u16::MAX))?;

    let value = parse_quoted_value(val_part.trim())?;

    Ok(Cond { var: var_idx, op, value: value.into() })
}

/// Extract value from `"quoted"` or `'quoted'`. Reject unquoted or mismatched.
fn parse_quoted_value(s: &str) -> Result<&str, String> {
    if s.len() >= 2 {
        if s.starts_with('"') && s.ends_with('"') {
            return Ok(&s[1..s.len() - 1]);
        }
        if s.starts_with('\'') && s.ends_with('\'') {
            return Ok(&s[1..s.len() - 1]);
        }
    }
    Err(format!("condition value must be quoted: expected '\"value\"', got '{s}'"))
}
