use herolib_mos::cloud_hypervisor::config::{CloudHypervisorConfig, VMConfig};
use herolib_mos::cloud_hypervisor::runtime::{VMHandle, VMStatus};
use tempfile::TempDir;

#[test]
fn test_vm_handle_creation() {
    let handle = VMHandle::new("vm123");
    assert_eq!(handle.id, "vm123");
}

#[test]
fn test_vm_status_equality() {
    assert_eq!(VMStatus::Created, VMStatus::Created);
    assert_eq!(VMStatus::Running, VMStatus::Running);
    assert_eq!(VMStatus::Paused, VMStatus::Paused);
    assert_eq!(VMStatus::Shutdown, VMStatus::Shutdown);
    assert_ne!(VMStatus::Created, VMStatus::Running);
}

#[test]
fn test_vm_status_serialization() {
    let status = VMStatus::Running;
    let json = serde_json::to_string(&status).unwrap();
    let deserialized: VMStatus = serde_json::from_str(&json).unwrap();
    assert_eq!(status, deserialized);
}

#[tokio::test]
async fn test_vm_config_build_and_spec() {
    let config = VMConfig::new()
        .with_kernel("/boot/vmlinux")
        .with_cpus(2)
        .with_memory(1024);
    
    let spec = config.build().unwrap();
    assert!(!spec.id.is_empty());
    assert_eq!(spec.config.cpus.boot_vcpus, 2);
}

#[test]
fn test_cloud_hypervisor_config_creation() {
    let temp_dir = TempDir::new().unwrap();
    let binary_path = temp_dir.path().join("cloud-hypervisor");
    std::fs::write(&binary_path, b"#!/bin/bash\necho test").unwrap();
    
    let config = CloudHypervisorConfig::new(&binary_path)
        .with_api_socket("/tmp/test.sock")
        .with_seccomp(false);
    
    assert_eq!(config.binary_path, binary_path);
    assert!(!config.seccomp);
}

#[tokio::test]
async fn test_multiple_vm_handles() {
    let handle1 = VMHandle::new("vm1");
    let handle2 = VMHandle::new("vm2");
    
    assert_ne!(handle1.id, handle2.id);
}

#[test]
fn test_vm_status_clone() {
    let status = VMStatus::Running;
    let cloned = status.clone();
    assert_eq!(status, cloned);
}

#[tokio::test]
async fn test_vm_lifecycle_states() {
    let states = vec![
        VMStatus::Created,
        VMStatus::Running,
        VMStatus::Paused,
        VMStatus::Running,
        VMStatus::Shutdown,
    ];
    
    for (i, state) in states.iter().enumerate() {
        assert!(matches!(
            state,
            VMStatus::Created
                | VMStatus::Running
                | VMStatus::Paused
                | VMStatus::Shutdown
                | VMStatus::Unknown
        ));
    }
}

#[test]
fn test_config_validation_missing_binary() {
    let config = CloudHypervisorConfig::new("/nonexistent/binary");
    let result = config.validate();
    assert!(result.is_err());
}

#[tokio::test]
async fn test_vm_spec_uniqueness() {
    let config = VMConfig::new()
        .with_kernel("/boot/vmlinux")
        .with_cpus(2)
        .with_memory(1024);
    
    let spec1 = config.clone().build().unwrap();
    let spec2 = config.build().unwrap();
    
    assert_ne!(spec1.id, spec2.id);
}

#[test]
fn test_vm_handle_clone() {
    let handle = VMHandle::new("vm123");
    let cloned = handle.clone();
    assert_eq!(handle.id, cloned.id);
}

#[test]
fn test_vm_handle_hash() {
    use std::collections::HashMap;
    
    let mut map = HashMap::new();
    let handle = VMHandle::new("vm123");
    map.insert(handle.clone(), "test");
    
    assert_eq!(map.get(&handle), Some(&"test"));
}
