//! Declarative extractors defined via configuration.
//!
//! This module enables users to define pattern-based extractors in `aphoria.toml`
//! without writing Rust code. Declarative extractors use regex patterns to match
//! content and generate claims based on configuration.
//!
//! # Example Configuration
//!
//! ```toml
//! [[extractors.declarative]]
//! name = "deprecated_api_v1"
//! description = "Detects usage of deprecated v1 API endpoints"
//! languages = ["go", "rust", "python"]
//! pattern = '/api/v1/\w+'
//! claim.subject = "api/deprecated_endpoint"
//! claim.predicate = "version"
//! claim.value = "v1"
//! confidence = 1.0
//!
//! [[extractors.declarative]]
//! name = "legacy_encryption"
//! description = "Detects legacy encryption algorithms"
//! languages = ["rust", "go", "python", "javascript"]
//! pattern = '(?i)blowfish|twofish|cast5'
//! claim.subject = "crypto/encryption/algorithm"
//! claim.predicate = "algorithm"
//! claim.value_from_match = true
//! confidence = 0.9
//! ```

mod executor;
mod parser;
mod types;

// Re-export public types
pub use parser::DeclarativeExtractor;
pub use types::{DeclarativeClaimDef, DeclarativeExtractorDef, DeclarativeValue};

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

    #[test]
    fn test_deserialization_boolean_value() {
        let toml_str = r#"
            name = "test"
            description = "Test extractor"
            languages = ["rust"]
            pattern = "test"
            confidence = 0.9

            [claim]
            subject = "test/subject"
            predicate = "enabled"
            value = true
        "#;

        let def: DeclarativeExtractorDef = toml::from_str(toml_str).expect("valid toml");
        assert_eq!(def.name, "test");
        assert!(matches!(def.claim.value, DeclarativeValue::Boolean { value: true }));
    }

    #[test]
    fn test_deserialization_text_value() {
        let toml_str = r#"
            name = "test"
            description = "Test extractor"
            languages = ["rust"]
            pattern = "test"
            confidence = 0.9

            [claim]
            subject = "test/subject"
            predicate = "version"
            value = "v1"
        "#;

        let def: DeclarativeExtractorDef = toml::from_str(toml_str).expect("valid toml");
        assert!(matches!(def.claim.value, DeclarativeValue::Text { value } if value == "v1"));
    }

    #[test]
    fn test_deserialization_matched_text_value() {
        let toml_str = r#"
            name = "test"
            description = "Test extractor"
            languages = ["rust"]
            pattern = "test"
            confidence = 0.9

            [claim]
            subject = "test/subject"
            predicate = "matched"
            value_from_match = true
        "#;

        let def: DeclarativeExtractorDef = toml::from_str(toml_str).expect("valid toml");
        assert!(matches!(
            def.claim.value,
            DeclarativeValue::MatchedText { value_from_match: true }
        ));
    }

    #[test]
    fn test_default_confidence() {
        let toml_str = r#"
            name = "test"
            languages = ["rust"]
            pattern = "test"

            [claim]
            subject = "test/subject"
            predicate = "enabled"
            value = true
        "#;

        let def: DeclarativeExtractorDef = toml::from_str(toml_str).expect("valid toml");
        assert!((def.confidence - 1.0).abs() < f32::EPSILON);
    }
}
