//! Subject URI builder for corpus patterns
//!
//! Converts WikiPattern + Authority into proper corpus subject URIs
//! (rfc://, owasp://, cwe://, community://wiki/).

use crate::corpus::authority_parser::Authority;
use crate::corpus::wiki_importer::WikiPattern;

/// Build corpus subject URI from WikiPattern and Authority
///
/// # Examples
///
/// ```
/// use aphoria::corpus::authority_parser::Authority;
/// use aphoria::corpus::subject_builder::build_corpus_subject;
/// use aphoria::corpus::wiki_importer::WikiPattern;
///
/// let pattern = WikiPattern {
///     subject: "tls/cert_verification".to_string(),
///     predicate: "enabled".to_string(),
///     value: "true".to_string(),
///     statement: "TLS cert verification MUST be enabled".to_string(),
///     authority: Some("RFC 5246 Section 7.4.2".to_string()),
/// };
///
/// let authority = Authority::RFC { num: 5246, section: Some("7.4.2".to_string()) };
/// let subject = build_corpus_subject(&pattern, &authority);
/// assert_eq!(subject, "rfc://5246/tls/cert_verification");
/// ```
pub fn build_corpus_subject(pattern: &WikiPattern, authority: &Authority) -> String {
    let normalized = normalize_subject(&pattern.subject);

    match authority {
        Authority::RFC { num, .. } => {
            format!("rfc://{}/{}", num, normalized)
        }
        Authority::OWASP { id, .. } => {
            format!("owasp://{}/{}", id.to_lowercase(), normalized)
        }
        Authority::CWE { id } => {
            format!("cwe://{}/{}", id, normalized)
        }
        Authority::Unknown(_) => {
            format!("community://wiki/{}", normalized)
        }
    }
}

/// Normalize subject path for URI
///
/// Converts to lowercase, replaces spaces with underscores, trims slashes.
fn normalize_subject(subject: &str) -> String {
    subject.trim().trim_matches('/').to_lowercase().replace(' ', "_")
}

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

    fn make_pattern(subject: &str) -> WikiPattern {
        WikiPattern {
            subject: subject.to_string(),
            predicate: "test".to_string(),
            value: CommunityObjectValue::Boolean(true),
            statement: "test statement".to_string(),
            authority: None,
        }
    }

    #[test]
    fn test_rfc_subject() {
        let pattern = make_pattern("tls/cert_verification");
        let authority = Authority::RFC { num: 5246, section: Some("7.4.2".to_string()) };
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "rfc://5246/tls/cert_verification");
    }

    #[test]
    fn test_rfc_subject_with_spaces() {
        let pattern = make_pattern("TLS Cert Verification");
        let authority = Authority::RFC { num: 5246, section: None };
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "rfc://5246/tls_cert_verification");
    }

    #[test]
    fn test_owasp_subject() {
        let pattern = make_pattern("password/storage");
        let authority = Authority::OWASP { id: "A03".to_string(), year: Some(2021) };
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "owasp://a03/password/storage");
    }

    #[test]
    fn test_cwe_subject() {
        let pattern = make_pattern("xss/prevention");
        let authority = Authority::CWE { id: 79 };
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "cwe://79/xss/prevention");
    }

    #[test]
    fn test_unknown_authority() {
        let pattern = make_pattern("custom/pattern");
        let authority = Authority::Unknown("Some Source".to_string());
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "community://wiki/custom/pattern");
    }

    #[test]
    fn test_normalize_leading_trailing_slashes() {
        let pattern = make_pattern("/api/security/");
        let authority = Authority::RFC { num: 7519, section: None };
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "rfc://7519/api/security");
    }

    #[test]
    fn test_normalize_uppercase() {
        let pattern = make_pattern("JWT/Validation");
        let authority = Authority::RFC { num: 7519, section: None };
        let subject = build_corpus_subject(&pattern, &authority);
        assert_eq!(subject, "rfc://7519/jwt/validation");
    }
}
