/*!
Tests for sorting functionality.

Extracted from src/search/sorting.rs
*/

use kodegen_tools_filesystem::search::sorting::{sort_results, SortBy, SortDirection};
use kodegen_tools_filesystem::search::{SearchResult, SearchResultType};
use std::time::{Duration, SystemTime};

fn create_test_result(file: &str, modified: Option<SystemTime>) -> SearchResult {
    SearchResult {
        file: file.to_string(),
        line: None,
        r#match: None,
        r#type: SearchResultType::File,
        is_context: false,
        is_binary: None,
        binary_suppressed: None,
        modified,
        accessed: None,
        created: None,
    }
}

#[test]
fn test_sort_by_path_ascending() {
    let mut results = vec![
        create_test_result("c.rs", None),
        create_test_result("a.rs", None),
        create_test_result("b.rs", None),
    ];

    sort_results(&mut results, SortBy::Path, SortDirection::Ascending);

    assert_eq!(results[0].file, "a.rs");
    assert_eq!(results[1].file, "b.rs");
    assert_eq!(results[2].file, "c.rs");
}

#[test]
fn test_sort_by_path_descending() {
    let mut results = vec![
        create_test_result("a.rs", None),
        create_test_result("c.rs", None),
        create_test_result("b.rs", None),
    ];

    sort_results(&mut results, SortBy::Path, SortDirection::Descending);

    assert_eq!(results[0].file, "c.rs");
    assert_eq!(results[1].file, "b.rs");
    assert_eq!(results[2].file, "a.rs");
}

#[test]
fn test_sort_by_modified_ascending() {
    let now = SystemTime::now();
    let old = now.checked_sub(Duration::from_secs(86400)).unwrap_or(now);
    let mid = now.checked_sub(Duration::from_secs(3600)).unwrap_or(now);

    let mut results = vec![
        create_test_result("new.rs", Some(now)),
        create_test_result("old.rs", Some(old)),
        create_test_result("mid.rs", Some(mid)),
    ];

    sort_results(&mut results, SortBy::Modified, SortDirection::Ascending);

    assert_eq!(results[0].file, "old.rs");
    assert_eq!(results[1].file, "mid.rs");
    assert_eq!(results[2].file, "new.rs");
}

#[test]
fn test_sort_by_modified_descending() {
    let now = SystemTime::now();
    let old = now.checked_sub(Duration::from_secs(86400)).unwrap_or(now);
    let mid = now.checked_sub(Duration::from_secs(3600)).unwrap_or(now);

    let mut results = vec![
        create_test_result("old.rs", Some(old)),
        create_test_result("new.rs", Some(now)),
        create_test_result("mid.rs", Some(mid)),
    ];

    sort_results(&mut results, SortBy::Modified, SortDirection::Descending);

    assert_eq!(results[0].file, "new.rs");
    assert_eq!(results[1].file, "mid.rs");
    assert_eq!(results[2].file, "old.rs");
}

#[test]
fn test_sort_handles_missing_metadata() {
    let now = SystemTime::now();

    let mut results = vec![
        create_test_result("has_time.rs", Some(now)),
        create_test_result("no_time.rs", None),
        create_test_result("also_has_time.rs", Some(now)),
    ];

    // Ascending: files with timestamps should come before files without
    sort_results(&mut results, SortBy::Modified, SortDirection::Ascending);

    assert!(results[0].modified.is_some());
    assert!(results[1].modified.is_some());
    assert!(results[2].modified.is_none());
    assert_eq!(results[2].file, "no_time.rs");
}

#[test]
fn test_sort_respects_direction() {
    let now = SystemTime::now();
    let old = now.checked_sub(Duration::from_secs(3600)).unwrap_or(now);

    let mut results_asc = vec![
        create_test_result("new.rs", Some(now)),
        create_test_result("old.rs", Some(old)),
    ];

    let mut results_desc = results_asc.clone();

    sort_results(&mut results_asc, SortBy::Modified, SortDirection::Ascending);
    sort_results(
        &mut results_desc,
        SortBy::Modified,
        SortDirection::Descending,
    );

    // Verify reversed order
    assert_eq!(results_asc[0].file, "old.rs");
    assert_eq!(results_asc[1].file, "new.rs");
    assert_eq!(results_desc[0].file, "new.rs");
    assert_eq!(results_desc[1].file, "old.rs");
}
