//! Integration tests for conflict detection (Phase 2A).

use crate::*;

#[tokio::test]
async fn test_conflict_detection_tls_disabled() {
    // Create temp project with danger_accept_invalid_certs(true)
    let temp_dir =
        tempfile::Builder::new().prefix("aphoria_tls_conflict").tempdir().expect("create temp dir");

    let src_dir = temp_dir.path().join("src");
    std::fs::create_dir_all(&src_dir).expect("create src dir");

    // Write a Rust file with TLS verification disabled
    std::fs::write(
        src_dir.join("client.rs"),
        r#"
            fn create_client() -> Result<Client, Error> {
                let client = reqwest::Client::builder()
                    .danger_accept_invalid_certs(true)
                    .build()?;
                Ok(client)
            }
            "#,
    )
    .expect("write file");

    // Create Cargo.toml so it's detected as a Rust project
    std::fs::write(
        temp_dir.path().join("Cargo.toml"),
        r#"
            [package]
            name = "testproject"
            version = "0.1.0"
            "#,
    )
    .expect("write cargo.toml");

    let args = ScanArgs {
        path: temp_dir.path().to_path_buf(),
        format: "table".to_string(),
        exit_code_enabled: true,
        mode: ScanMode::Ephemeral,
        debug: false,
        sync: false,
        file_source: FileSource::All,
        benchmark: false,
        show_claims: false,
    };

    let mut config = AphoriaConfig::default();
    config.episteme.data_dir = temp_dir.path().join(".aphoria").join("db");

    let result = run_scan(args, &config).await.expect("scan should succeed");

    // Assert: conflicts not empty, has_blocks() == true
    assert!(
        !result.conflicts.is_empty(),
        "Should detect conflicts for TLS verification disabled. \
             Claims extracted: {}, Files scanned: {}",
        result.claims_extracted,
        result.files_scanned
    );

    assert!(
        result.has_blocks(),
        "TLS verification disabled should be a BLOCK verdict. \
             Conflicts: {:?}",
        result.conflicts.iter().map(|c| (&c.claim.concept_path, &c.verdict)).collect::<Vec<_>>()
    );
}

#[tokio::test]
async fn test_conflict_detection_jwt_audience_disabled() {
    // Create temp project with JWT audience validation disabled
    let temp_dir =
        tempfile::Builder::new().prefix("aphoria_jwt_conflict").tempdir().expect("create temp dir");

    let src_dir = temp_dir.path().join("src");
    std::fs::create_dir_all(&src_dir).expect("create src dir");

    // Write a Rust file with JWT audience validation disabled
    std::fs::write(
        src_dir.join("auth.rs"),
        r#"
            fn validate_token(token: &str) -> Result<Claims, Error> {
                let mut validation = Validation::default();
                validation.validate_aud = false;  // Disabled!
                let token_data = decode::<Claims>(token, &key, &validation)?;
                Ok(token_data.claims)
            }
            "#,
    )
    .expect("write file");

    // Create Cargo.toml
    std::fs::write(
        temp_dir.path().join("Cargo.toml"),
        r#"
            [package]
            name = "testproject"
            version = "0.1.0"
            "#,
    )
    .expect("write cargo.toml");

    let args = ScanArgs {
        path: temp_dir.path().to_path_buf(),
        format: "table".to_string(),
        exit_code_enabled: true,
        mode: ScanMode::Ephemeral,
        debug: false,
        sync: false,
        file_source: FileSource::All,
        benchmark: false,
        show_claims: false,
    };

    let mut config = AphoriaConfig::default();
    config.episteme.data_dir = temp_dir.path().join(".aphoria").join("db");

    let result = run_scan(args, &config).await.expect("scan should succeed");

    // Assert: conflicts not empty for JWT audience validation
    assert!(
        !result.conflicts.is_empty(),
        "Should detect conflicts for JWT audience validation disabled. \
             Claims extracted: {}, Files scanned: {}",
        result.claims_extracted,
        result.files_scanned
    );

    // Check that at least one conflict is about JWT audience
    let has_jwt_conflict = result
        .conflicts
        .iter()
        .any(|c| c.claim.concept_path.contains("jwt") && c.claim.concept_path.contains("audience"));
    assert!(
        has_jwt_conflict,
        "Should have a conflict about JWT audience validation. \
             Conflicts: {:?}",
        result.conflicts.iter().map(|c| &c.claim.concept_path).collect::<Vec<_>>()
    );
}

#[tokio::test]
async fn test_no_conflicts_when_compliant() {
    // Create temp project with compliant code (no dangerous patterns)
    let temp_dir =
        tempfile::Builder::new().prefix("aphoria_compliant").tempdir().expect("create temp dir");

    let src_dir = temp_dir.path().join("src");
    std::fs::create_dir_all(&src_dir).expect("create src dir");

    // Write a Rust file with compliant code
    std::fs::write(
        src_dir.join("main.rs"),
        r#"
            fn main() {
                println!("Hello, world!");
            }
            "#,
    )
    .expect("write file");

    // Create Cargo.toml
    std::fs::write(
        temp_dir.path().join("Cargo.toml"),
        r#"
            [package]
            name = "testproject"
            version = "0.1.0"
            "#,
    )
    .expect("write cargo.toml");

    let args = ScanArgs {
        path: temp_dir.path().to_path_buf(),
        format: "table".to_string(),
        exit_code_enabled: true,
        mode: ScanMode::Ephemeral,
        debug: false,
        sync: false,
        file_source: FileSource::All,
        benchmark: false,
        show_claims: false,
    };

    let mut config = AphoriaConfig::default();
    config.episteme.data_dir = temp_dir.path().join(".aphoria").join("db");

    let result = run_scan(args, &config).await.expect("scan should succeed");

    // No dangerous patterns = no claims = no conflicts
    assert!(
        result.conflicts.is_empty(),
        "Compliant code should have no conflicts. Found: {:?}",
        result.conflicts.iter().map(|c| &c.claim.concept_path).collect::<Vec<_>>()
    );
}
