//! Tests for TLS version extractor.

use super::*;
use crate::types::Language;
use stemedb_core::types::ObjectValue;

#[test]
fn test_rust_tls10_detection() {
    let extractor = TlsVersionExtractor::new();
    // Content with TLS10 on two lines - should find 2 matches
    let content = r#"
        use rustls::version::TLS10;
        config.min_protocol_version = Some(TLS10);
    "#;

    let claims = extractor.extract(&["rust".to_string()], content, Language::Rust, "src/tls.rs");

    // Both lines match TLS10 pattern
    assert_eq!(claims.len(), 2);
    assert!(claims.iter().all(|c| c.value == ObjectValue::Text("1.0".to_string())));
}

#[test]
fn test_rust_tls11_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        let version = TLS1_1;
    "#;

    let claims = extractor.extract(&["rust".to_string()], content, Language::Rust, "src/tls.rs");

    assert_eq!(claims.len(), 1);
    assert_eq!(claims[0].value, ObjectValue::Text("1.1".to_string()));
}

#[test]
fn test_go_version_tls10_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        cfg := &tls.Config{
            MinVersion: tls.VersionTLS10,
        }
    "#;

    let claims = extractor.extract(&["go".to_string()], content, Language::Go, "server.go");

    assert_eq!(claims.len(), 1);
    assert_eq!(claims[0].value, ObjectValue::Text("1.0".to_string()));
}

#[test]
fn test_go_version_tls11_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        cfg := &tls.Config{
            MinVersion: tls.VersionTLS11,
        }
    "#;

    let claims = extractor.extract(&["go".to_string()], content, Language::Go, "server.go");

    assert_eq!(claims.len(), 1);
    assert_eq!(claims[0].value, ObjectValue::Text("1.1".to_string()));
}

#[test]
fn test_python_tls_version_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        import ssl
        ctx = ssl.SSLContext(ssl.PROTOCOL_TLSv1)
        ctx.minimum_version = ssl.TLSVersion.TLSv1_1
    "#;

    let claims = extractor.extract(&["python".to_string()], content, Language::Python, "server.py");

    // Should detect both TLSv1 and TLSv1_1
    assert_eq!(claims.len(), 2);
}

#[test]
fn test_js_min_version_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        const server = https.createServer({
            minVersion: 'TLSv1',
            key: fs.readFileSync('key.pem')
        });
    "#;

    let claims = extractor.extract(&["js".to_string()], content, Language::JavaScript, "server.js");

    assert_eq!(claims.len(), 1);
    assert_eq!(claims[0].value, ObjectValue::Text("1.0".to_string()));
}

#[test]
fn test_js_secure_protocol_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        const options = {
            secureProtocol: 'TLSv1_method'
        };
    "#;

    let claims = extractor.extract(&["js".to_string()], content, Language::JavaScript, "client.js");

    assert_eq!(claims.len(), 1);
}

#[test]
fn test_yaml_min_version_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
tls:
  min_version: "1.0"
  cert_file: /etc/certs/server.crt
"#;

    let claims = extractor.extract(
        &["config".to_string()],
        content,
        Language::Yaml,
        "config/production.yaml",
    );

    assert_eq!(claims.len(), 1);
    assert_eq!(claims[0].value, ObjectValue::Text("deprecated".to_string()));
}

#[test]
fn test_yaml_tls_min_version_detection() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
server:
  tls_min_version: TLSv1.1
"#;

    let claims = extractor.extract(&["config".to_string()], content, Language::Yaml, "config.yaml");

    // May match both config pattern and semantic pattern
    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.value == ObjectValue::Text("deprecated".to_string())));
}

#[test]
fn test_no_false_positives_tls12() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        cfg := &tls.Config{
            MinVersion: tls.VersionTLS12,
        }
    "#;

    let claims = extractor.extract(&["go".to_string()], content, Language::Go, "server.go");

    assert!(claims.is_empty());
}

#[test]
fn test_no_false_positives_tls13() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        use rustls::version::TLS13;
        config.min_protocol_version = Some(TLS13);
    "#;

    let claims = extractor.extract(&["rust".to_string()], content, Language::Rust, "src/tls.rs");

    assert!(claims.is_empty());
}

#[test]
fn test_no_false_positives_modern_config() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
tls:
  min_version: "1.2"
  max_version: "1.3"
"#;

    let claims = extractor.extract(&["config".to_string()], content, Language::Yaml, "config.yaml");

    assert!(claims.is_empty());
}

#[test]
fn test_concept_path_structure() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
        cfg := &tls.Config{MinVersion: tls.VersionTLS10}
    "#;

    let claims = extractor.extract(&["go".to_string()], content, Language::Go, "server.go");

    assert_eq!(claims.len(), 1);
    assert!(claims[0].concept_path.contains("tls/min_version"));
}

// ===== Phase 8.4: Semantic TLS Version Detection Tests =====

#[test]
fn test_semantic_const_rust() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"const TLS_MIN_VERSION: &str = "1.0";"#;

    let claims = extractor.extract(&["rust".to_string()], content, Language::Rust, "src/config.rs");

    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.description.contains("Semantic")));
}

#[test]
fn test_semantic_let_js() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"let sslVersion = "TLSv1";"#;

    let claims = extractor.extract(&["js".to_string()], content, Language::JavaScript, "config.js");

    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.description.contains("Semantic")));
}

#[test]
fn test_semantic_assignment_python() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"TLS_MINIMUM_VERSION = "1.1""#;

    let claims = extractor.extract(&["python".to_string()], content, Language::Python, "config.py");

    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.description.contains("Semantic")));
}

#[test]
fn test_semantic_ssl_version() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"const SSL_VERSION = "SSLv3";"#;

    let claims = extractor.extract(&["rust".to_string()], content, Language::Rust, "src/ssl.rs");

    assert!(!claims.is_empty());
}

#[test]
fn test_env_tls_version() {
    let extractor = TlsVersionExtractor::new();
    let content = "TLS_MIN_VERSION=1.0";

    let claims = extractor.extract(&["env".to_string()], content, Language::Dotenv, ".env");

    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.description.contains("Environment variable")));
}

#[test]
fn test_env_export_ssl() {
    let extractor = TlsVersionExtractor::new();
    let content = "export SSL_VERSION=TLSv1";

    let claims =
        extractor.extract(&["env".to_string()], content, Language::Dotenv, ".env.production");

    assert!(!claims.is_empty());
}

#[test]
fn test_terraform_min_tls_version() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"min_tls_version = "TLS1_0""#;

    let claims =
        extractor.extract(&["terraform".to_string()], content, Language::Terraform, "main.tf");

    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.description.contains("Terraform")));
}

#[test]
fn test_terraform_ssl_version() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"ssl_minimum_protocol_version = "TLSv1""#;

    let claims =
        extractor.extract(&["terraform".to_string()], content, Language::Terraform, "variables.tf");

    assert!(!claims.is_empty());
}

#[test]
fn test_k8s_min_tls_version() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"
apiVersion: v1
kind: Config
spec:
  minTLSVersion: VersionTLS10
"#;

    let claims =
        extractor.extract(&["k8s".to_string()], content, Language::Yaml, "deployment.yaml");

    assert!(!claims.is_empty());
    assert!(claims.iter().any(|c| c.description.contains("Kubernetes")));
}

#[test]
fn test_k8s_tls_min_version_camel() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"tlsMinVersion: "1.0""#;

    let claims = extractor.extract(&["k8s".to_string()], content, Language::Yaml, "ingress.yaml");

    assert!(!claims.is_empty());
}

#[test]
fn test_no_false_positive_semantic_tls12() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"const TLS_MIN_VERSION = "1.2";"#;

    let claims = extractor.extract(&["rust".to_string()], content, Language::Rust, "src/config.rs");

    // TLS 1.2 is safe, should not match semantic pattern
    assert!(claims.is_empty());
}

#[test]
fn test_no_false_positive_env_tls13() {
    let extractor = TlsVersionExtractor::new();
    let content = "TLS_VERSION=1.3";

    let claims = extractor.extract(&["env".to_string()], content, Language::Dotenv, ".env");

    // TLS 1.3 is safe, should not match
    assert!(claims.is_empty());
}

#[test]
fn test_no_false_positive_terraform_tls12() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"min_tls_version = "TLS1_2""#;

    let claims =
        extractor.extract(&["terraform".to_string()], content, Language::Terraform, "main.tf");

    // TLS 1.2 is safe
    assert!(claims.is_empty());
}

#[test]
fn test_no_false_positive_k8s_tls12() {
    let extractor = TlsVersionExtractor::new();
    let content = r#"minTLSVersion: VersionTLS12"#;

    let claims =
        extractor.extract(&["k8s".to_string()], content, Language::Yaml, "deployment.yaml");

    // TLS 1.2 is safe
    assert!(claims.is_empty());
}
