//! Integration tests for cache functionality
//!
//! Note: These tests use a shared cache file and must be run serially.
//! Run with: cargo test -- --test-threads=1

use lazydomain::cache::{CacheManager, CachedSearch};
use lazydomain::types::{CheckResult, CheckStatus};
use std::sync::Mutex;

// Global mutex to serialize cache tests
static TEST_MUTEX: Mutex<()> = Mutex::new(());

/// Helper to create a fresh cache manager and clear it
fn create_fresh_cache_manager() -> CacheManager {
    let manager = CacheManager::new().expect("Failed to create cache manager");
    manager.clear().ok(); // Clear any existing cache
    manager
}

/// Helper to create a test result
fn create_test_result(domain: &str, tld: &str, status: CheckStatus) -> CheckResult {
    match status {
        CheckStatus::Available => CheckResult::available(domain, tld),
        CheckStatus::Taken => CheckResult::taken(domain, tld, Some("Test Registrar".to_string()), None),
        CheckStatus::Error => CheckResult::error(domain, tld, "Test error"),
    }
}

#[test]
fn test_cached_search_creation() {
    let results = vec![
        create_test_result("example", "com", CheckStatus::Taken),
        create_test_result("example", "io", CheckStatus::Available),
    ];

    let cached = CachedSearch::new("example", results.clone());

    assert_eq!(cached.query, "example");
    assert_eq!(cached.result_count(), 2);
    assert_eq!(cached.available_count(), 1);
}

#[test]
fn test_cached_search_available_count() {
    let results = vec![
        create_test_result("test", "com", CheckStatus::Taken),
        create_test_result("test", "io", CheckStatus::Available),
        create_test_result("test", "net", CheckStatus::Available),
        create_test_result("test", "org", CheckStatus::Error),
    ];

    let cached = CachedSearch::new("test", results);

    assert_eq!(cached.result_count(), 4);
    assert_eq!(cached.available_count(), 2);
}

#[test]
fn test_cache_manager_empty_load() {
    let _lock = TEST_MUTEX.lock().unwrap();
    let manager = create_fresh_cache_manager();
    let searches = manager.load().expect("Failed to load cache");
    assert_eq!(searches.len(), 0);
}

#[test]
fn test_cache_manager_add_and_load() {
    let _lock = TEST_MUTEX.lock().unwrap();
    let manager = create_fresh_cache_manager();
    
    let results = vec![
        create_test_result("mysite", "com", CheckStatus::Taken),
        create_test_result("mysite", "io", CheckStatus::Available),
    ];

    manager.add_search("mysite", results.clone()).expect("Failed to add search");

    let searches = manager.load().expect("Failed to load cache");
    assert_eq!(searches.len(), 1);
    assert_eq!(searches[0].query, "mysite");
    assert_eq!(searches[0].result_count(), 2);
    assert_eq!(searches[0].available_count(), 1);
}

#[test]
fn test_cache_manager_multiple_searches() {
    let _lock = TEST_MUTEX.lock().unwrap();
    let manager = create_fresh_cache_manager();
    
    let results1 = vec![create_test_result("google", "com", CheckStatus::Available)];
    let results2 = vec![create_test_result("facebook", "io", CheckStatus::Taken)];
    let results3 = vec![create_test_result("alphainnovationlabs", "net", CheckStatus::Available)];

    manager.add_search("google", results1).expect("Failed to add google search");
    manager.add_search("facebook", results2).expect("Failed to add facebook search");
    manager.add_search("alphainnovationlabs", results3).expect("Failed to add alphainnovationlabs search");

    let searches = manager.load().expect("Failed to load cache");
    assert_eq!(searches.len(), 3);
    
    // Most recent first
    assert_eq!(searches[0].query, "alphainnovationlabs");
    assert_eq!(searches[1].query, "facebook");
    assert_eq!(searches[2].query, "google");
}

#[test]
fn test_cache_manager_clear() {
    let _lock = TEST_MUTEX.lock().unwrap();
    let manager = create_fresh_cache_manager();
    
    let results = vec![create_test_result("test", "com", CheckStatus::Available)];
    manager.add_search("test", results).expect("Failed to add search");

    let searches = manager.load().expect("Failed to load cache");
    assert_eq!(searches.len(), 1);

    manager.clear().expect("Failed to clear cache");

    let searches_after_clear = manager.load().expect("Failed to load cache");
    assert_eq!(searches_after_clear.len(), 0);
}

#[test]
fn test_cache_manager_count() {
    let _lock = TEST_MUTEX.lock().unwrap();
    let manager = create_fresh_cache_manager();
    
    assert_eq!(manager.count().expect("Failed to get count"), 0);

    let results1 = vec![create_test_result("google", "com", CheckStatus::Available)];
    manager.add_search("google", results1).expect("Failed to add search");
    assert_eq!(manager.count().expect("Failed to get count"), 1);

    let results2 = vec![create_test_result("facebook", "io", CheckStatus::Available)];
    manager.add_search("facebook", results2).expect("Failed to add search");
    assert_eq!(manager.count().expect("Failed to get count"), 2);
}
