use crate::error::TaxError;
use crate::segment::TaxSegment;

/// A single segment in a query pattern: a required name and an optional rank filter.
///
/// If `rank` is `None`, the pattern matches any segment with the given name,
/// regardless of its stored rank. If `rank` is `Some(r)`, both name and rank
/// must match exactly.
#[derive(Debug, Clone, PartialEq, Eq)]
pub struct SegmentPattern {
    name: String,
    rank: Option<String>,
}

impl SegmentPattern {
    pub fn parse(raw: &str) -> Result<Self, TaxError> {
        let parts: Vec<&str> = raw.splitn(3, '@').collect();
        let (name_raw, rank_raw) = match parts.as_slice() {
            [name]       => (*name, None),
            [name, rank] => (*name, Some(*rank)),
            _            => return Err(TaxError::AmbiguousRank { segment: raw.to_string() }),
        };
        if name_raw.is_empty() {
            return Err(TaxError::EmptySegmentName);
        }
        let rank = match rank_raw {
            None     => None,
            Some("") => return Err(TaxError::EmptyRankName { segment: raw.to_string() }),
            Some(r)  => Some(r.to_string()),
        };
        Ok(Self { name: name_raw.to_string(), rank })
    }

    /// True if this pattern matches `seg`.
    /// Name must match exactly. If a rank is specified in the pattern, the
    /// segment's rank must match; otherwise any rank (or no rank) is accepted.
    pub fn matches(&self, seg: &TaxSegment) -> bool {
        self.name == seg.name()
            && self.rank.as_deref().map_or(true, |r| seg.rank() == Some(r))
    }
}
