// Pre-compiled regex patterns for metadata extraction

use lazy_static::lazy_static;
use regex::Regex;

lazy_static! {
    /// Main metadata pattern regex
    /// Captures: Group 1 = pattern name, Group 2 = single-quoted value,
    ///           Group 3 = double-quoted value, Group 4 = unquoted value
    ///
    /// Format: __<name>__ <value>
    /// where:
    ///   - name matches [a-zA-Z_][a-zA-Z0-9_]*
    ///   - value is single-quoted (with escaped quotes: \'), double-quoted (with escaped quotes: \"),
    ///     or unquoted (non-whitespace, not starting with quote or __)
    ///
    /// Unquoted value pattern explanation:
    /// - First character: [^'"\s_] (not quote, space, or underscore) OR _[^_] (single underscore not followed by another underscore)
    /// - Remaining characters: \S* (any non-whitespace)
    /// This prevents matching placeholder names like __name__ as values
    pub static ref METADATA_PATTERN: Regex = Regex::new(
        r#"__([a-zA-Z_][a-zA-Z0-9_]*)__\s+(?:'((?:[^'\\]|\\.)*)'|"((?:[^"\\]|\\.)*)"|((?:[^'"\s_]|_[^_])\S*))"#
    ).expect("Failed to compile metadata pattern regex");
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_single_value_unquoted() {
        let input = "__idpattern__ value";
        let captures = METADATA_PATTERN.captures(input).unwrap();
        assert_eq!(captures.get(1).unwrap().as_str(), "idpattern");
        assert_eq!(captures.get(4).unwrap().as_str(), "value");
    }

    #[test]
    fn test_single_value_single_quoted() {
        let input = "__name__ 'quoted value'";
        let captures = METADATA_PATTERN.captures(input).unwrap();
        assert_eq!(captures.get(1).unwrap().as_str(), "name");
        assert_eq!(captures.get(2).unwrap().as_str(), "quoted value");
    }

    #[test]
    fn test_single_value_double_quoted() {
        let input = "__type__ \"double quoted\"";
        let captures = METADATA_PATTERN.captures(input).unwrap();
        assert_eq!(captures.get(1).unwrap().as_str(), "type");
        assert_eq!(captures.get(3).unwrap().as_str(), "double quoted");
    }

    #[test]
    fn test_pattern_with_underscores_and_numbers() {
        let input = "__pattern_123__ value123";
        let captures = METADATA_PATTERN.captures(input).unwrap();
        assert_eq!(captures.get(1).unwrap().as_str(), "pattern_123");
        assert_eq!(captures.get(4).unwrap().as_str(), "value123");
    }

    #[test]
    fn test_multiple_patterns_on_line() {
        let input = "__key1__ val1 __key2__ val2";
        let mut matches = METADATA_PATTERN.captures_iter(input);

        let first = matches.next().unwrap();
        assert_eq!(first.get(1).unwrap().as_str(), "key1");
        assert_eq!(first.get(4).unwrap().as_str(), "val1");

        let second = matches.next().unwrap();
        assert_eq!(second.get(1).unwrap().as_str(), "key2");
        assert_eq!(second.get(4).unwrap().as_str(), "val2");
    }

    #[test]
    fn test_pattern_in_middle_of_line() {
        let input = "prefix __pattern__ value suffix";
        let captures = METADATA_PATTERN.captures(input).unwrap();
        assert_eq!(captures.get(1).unwrap().as_str(), "pattern");
        assert_eq!(captures.get(4).unwrap().as_str(), "value");
    }

    #[test]
    fn test_no_match_invalid_name() {
        let input = "__123invalid__ value";
        assert!(METADATA_PATTERN.captures(input).is_none());
    }

    #[test]
    fn test_no_match_no_spaces() {
        let input = "__pattern__value";
        assert!(METADATA_PATTERN.captures(input).is_none());
    }
}
