//! Tests for batch execution.

use entropyk_cli::batch::{discover_config_files, BatchSummary};
use entropyk_cli::run::{SimulationResult, SimulationStatus};
use std::path::PathBuf;
use tempfile::tempdir;

#[test]
fn test_discover_config_files() {
    let dir = tempdir().unwrap();

    std::fs::write(dir.path().join("config1.json"), "{}").unwrap();
    std::fs::write(dir.path().join("config2.json"), "{}").unwrap();
    std::fs::write(dir.path().join("config3.json"), "{}").unwrap();
    std::fs::write(dir.path().join("readme.txt"), "").unwrap();
    std::fs::write(dir.path().join("data.csv"), "a,b,c").unwrap();

    let files = discover_config_files(dir.path()).unwrap();
    assert_eq!(files.len(), 3);

    let names: Vec<String> = files
        .iter()
        .map(|p: &PathBuf| p.file_name().unwrap().to_string_lossy().to_string())
        .collect();
    assert!(names.contains(&"config1.json".to_string()));
    assert!(names.contains(&"config2.json".to_string()));
    assert!(names.contains(&"config3.json".to_string()));
}

#[test]
fn test_discover_config_files_sorted() {
    let dir = tempdir().unwrap();

    std::fs::write(dir.path().join("zebra.json"), "{}").unwrap();
    std::fs::write(dir.path().join("alpha.json"), "{}").unwrap();
    std::fs::write(dir.path().join("middle.json"), "{}").unwrap();

    let files = discover_config_files(dir.path()).unwrap();
    assert_eq!(files.len(), 3);
    assert!(files[0].ends_with("alpha.json"));
    assert!(files[1].ends_with("middle.json"));
    assert!(files[2].ends_with("zebra.json"));
}

#[test]
fn test_discover_empty_directory() {
    let dir = tempdir().unwrap();
    let files = discover_config_files(dir.path()).unwrap();
    assert!(files.is_empty());
}

#[test]
fn test_batch_summary_serialization() {
    let summary = BatchSummary {
        total: 100,
        succeeded: 95,
        failed: 3,
        non_converged: 2,
        total_elapsed_ms: 5000,
        avg_elapsed_ms: 50.0,
        results: vec![],
    };

    let json = serde_json::to_string_pretty(&summary).unwrap();
    assert!(json.contains("\"total\": 100"));
    assert!(json.contains("\"succeeded\": 95"));
    assert!(json.contains("\"avg_elapsed_ms\": 50.0"));
}

#[test]
fn test_batch_summary_default() {
    let summary = BatchSummary::default();
    assert_eq!(summary.total, 0);
    assert_eq!(summary.succeeded, 0);
    assert_eq!(summary.failed, 0);
    assert!(summary.results.is_empty());
}

#[test]
fn test_simulation_result_statuses() {
    let results = vec![
        SimulationResult {
            input: "ok.json".to_string(),
            status: SimulationStatus::Converged,
            convergence: None,
            iterations: Some(10),
            state: None,
            error: None,
            elapsed_ms: 50,
        },
        SimulationResult {
            input: "fail.json".to_string(),
            status: SimulationStatus::Error,
            convergence: None,
            iterations: None,
            state: None,
            error: Some("Error".to_string()),
            elapsed_ms: 0,
        },
        SimulationResult {
            input: "timeout.json".to_string(),
            status: SimulationStatus::Timeout,
            convergence: None,
            iterations: Some(100),
            state: None,
            error: None,
            elapsed_ms: 1000,
        },
    ];

    let converged_count = results
        .iter()
        .filter(|r| r.status == SimulationStatus::Converged)
        .count();
    let error_count = results
        .iter()
        .filter(|r| r.status == SimulationStatus::Error)
        .count();
    let timeout_count = results
        .iter()
        .filter(|r| r.status == SimulationStatus::Timeout)
        .count();

    assert_eq!(converged_count, 1);
    assert_eq!(error_count, 1);
    assert_eq!(timeout_count, 1);
}
