//! Integration tests for Day 3 debugging features.
//!
//! These tests validate the three debugging features work correctly:
//! - VG-DAY3-001: --show-observations flag
//! - VG-DAY3-003: extractors validate command
//! - VG-DAY3-004: extractors test command

use crate::{run_scan, AphoriaConfig, FileSource, ScanArgs, ScanMode};
use tempfile::TempDir;

/// Test that show_observations flag populates observations in result.
#[tokio::test]
async fn test_show_observations_flag_populates_observations() {
    let temp_dir = TempDir::new().expect("create temp dir");
    let project_root = temp_dir.path();

    // Create a simple Rust project with code
    std::fs::write(
        project_root.join("main.rs"),
        r#"
        fn main() {
            let timeout = 0;
            println!("Hello");
        }
        "#,
    )
    .expect("write main.rs");

    std::fs::write(
        project_root.join("Cargo.toml"),
        r#"
        [package]
        name = "test"
        version = "0.1.0"
        "#,
    )
    .expect("write Cargo.toml");

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

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

    // Verify: Observations field exists and can be accessed
    // This test just verifies the field is accessible without panicking
    let _observations_exist = &result.observations;
}

/// Test that observations are formatted correctly when flag is enabled.
#[tokio::test]
async fn test_show_observations_formatting() {
    let temp_dir = TempDir::new().expect("create temp dir");
    let project_root = temp_dir.path();

    // Create a project that will trigger some extractors
    std::fs::write(
        project_root.join("test.rs"),
        r#"
        const MAX_SIZE: usize = 100;
        "#,
    )
    .expect("write test.rs");

    std::fs::write(
        project_root.join("Cargo.toml"),
        r#"
        [package]
        name = "test"
        version = "0.1.0"
        "#,
    )
    .expect("write Cargo.toml");

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

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

    // Test that format_observations can be called without panicking
    use crate::report::format_observations;
    let output = format_observations(&result);
    assert!(output.contains("Observations Created"));
}

/// Test that show_observations can be disabled (default behavior).
#[tokio::test]
async fn test_show_observations_disabled_by_default() {
    let temp_dir = TempDir::new().expect("create temp dir");
    let project_root = temp_dir.path();

    std::fs::write(project_root.join("test.rs"), "fn main() {}").expect("write test.rs");
    std::fs::write(
        project_root.join("Cargo.toml"),
        r#"
        [package]
        name = "test"
        version = "0.1.0"
        "#,
    )
    .expect("write Cargo.toml");

    let args = ScanArgs {
        path: project_root.to_path_buf(),
        format: "table".to_string(),
        exit_code_enabled: false,
        mode: ScanMode::Ephemeral,
        debug: false,
        sync: false,
        file_source: FileSource::All,
        benchmark: false,
        show_claims: false,
        strict: false,
        show_observations: false, // Explicitly disabled
        explain_authority: false,
        suggest_convergence: false,
    };

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

    // Observations should still be populated (the flag only affects display)
    // This test verifies the scan completes successfully regardless of flag value
    let _observations_exist = &result.observations;
}

/// Test that show_observations works with verify report.
#[tokio::test]
async fn test_show_observations_with_verify_report() {
    let temp_dir = TempDir::new().expect("create temp dir");
    let project_root = temp_dir.path();

    std::fs::write(project_root.join("test.rs"), "fn main() {}").expect("write test.rs");
    std::fs::write(
        project_root.join("Cargo.toml"),
        r#"
        [package]
        name = "test"
        version = "0.1.0"
        "#,
    )
    .expect("write Cargo.toml");

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

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

    // If verify report exists, format_observations should handle it gracefully
    use crate::report::format_observations;
    let output = format_observations(&result);

    if result.verify.is_some() {
        assert!(
            output.contains("Claim Matching Analysis")
                || output.contains("Use `aphoria verify run`")
        );
    }
}

/// Test edge case: show_observations with empty project.
#[tokio::test]
async fn test_show_observations_empty_project() {
    let temp_dir = TempDir::new().expect("create temp dir");
    let project_root = temp_dir.path();

    // Create minimal project with no scannable code
    std::fs::write(
        project_root.join("Cargo.toml"),
        r#"
        [package]
        name = "empty"
        version = "0.1.0"
        "#,
    )
    .expect("write Cargo.toml");

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

    let result = run_scan(args, &AphoriaConfig::default())
        .await
        .expect("scan should succeed even with empty project");

    use crate::report::format_observations;
    let output = format_observations(&result);

    // Should show "No observations created" message
    if result.observations.is_empty() {
        assert!(output.contains("No observations created"));
    }
}
