use herolib_mos::cloud_hypervisor::config::VMConfig;
use herolib_mos::cloud_hypervisor::errors::CloudHypervisorError;
use httpmock::prelude::*;
use std::path::PathBuf;
use tempfile::TempDir;

#[tokio::test]
async fn test_api_client_vm_create_mock() {
    let temp_dir = TempDir::new().unwrap();
    let socket_path = temp_dir.path().join("test.sock");
    
    std::fs::write(&socket_path, b"").unwrap();
    
    let config = VMConfig::new()
        .with_kernel("/boot/vmlinux")
        .with_cpus(2)
        .with_memory(1024);
    
    assert!(config.kernel.is_some());
}

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

#[tokio::test]
async fn test_device_hotplug_mock() {
    let mut config = VMConfig::new()
        .with_kernel("/boot/vmlinux")
        .with_cpus(2)
        .with_memory(1024);
    
    config.add_virtio_blk("/disk.img", false);
    
    assert_eq!(config.disks.len(), 1);
}

#[tokio::test]
async fn test_snapshot_restore_mock() {
    let temp_dir = TempDir::new().unwrap();
    let snapshot_path = temp_dir.path().join("snapshot.snap");
    
    std::fs::write(&snapshot_path, b"snapshot data").unwrap();
    
    assert!(snapshot_path.exists());
}

#[test]
fn test_config_serialization() {
    let config = VMConfig::new()
        .with_kernel("/boot/vmlinux")
        .with_cpus(4)
        .with_memory(2048);
    
    let json = serde_json::to_string(&config).unwrap();
    let deserialized: VMConfig = serde_json::from_str(&json).unwrap();
    
    assert_eq!(deserialized.cpus.boot_vcpus, 4);
    assert_eq!(deserialized.memory.size, 2048 * 1024 * 1024);
}

#[test]
fn test_vm_spec_generation() {
    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);
}

#[tokio::test]
async fn test_multiple_devices() {
    let mut config = VMConfig::new()
        .with_kernel("/boot/vmlinux")
        .with_cpus(2)
        .with_memory(1024);
    
    config
        .add_virtio_blk("/disk1.img", false)
        .add_virtio_blk("/disk2.img", true)
        .add_virtio_net("tap0")
        .add_virtio_net("tap1");
    
    assert_eq!(config.disks.len(), 2);
    assert_eq!(config.net.len(), 2);
}

#[test]
fn test_error_propagation() {
    let config = VMConfig::new().with_cpus(2).with_memory(1024);
    
    let result = config.build();
    assert!(result.is_err());
    
    match result {
        Err(CloudHypervisorError::Config(_)) => {}
        _ => panic!("Expected Config error"),
    }
}

#[tokio::test]
async fn test_concurrent_vm_operations() {
    let config1 = VMConfig::new()
        .with_kernel("/boot/vmlinux1")
        .with_cpus(2)
        .with_memory(1024);
    
    let config2 = VMConfig::new()
        .with_kernel("/boot/vmlinux2")
        .with_cpus(4)
        .with_memory(2048);
    
    let spec1 = config1.build().unwrap();
    let spec2 = config2.build().unwrap();
    
    assert_ne!(spec1.id, spec2.id);
    assert_eq!(spec1.config.cpus.boot_vcpus, 2);
    assert_eq!(spec2.config.cpus.boot_vcpus, 4);
}

#[test]
fn test_device_config_validation() {
    use herolib_mos::cloud_hypervisor::devices::DiskBuilder;
    
    let disk = DiskBuilder::new()
        .path("/disk.img")
        .readonly(true)
        .build()
        .unwrap();
    
    assert!(disk.readonly);
    assert_eq!(disk.path, PathBuf::from("/disk.img"));
}

#[test]
fn test_net_config_validation() {
    use herolib_mos::cloud_hypervisor::devices::NetBuilder;
    
    let net = NetBuilder::new()
        .tap("tap0")
        .mac("00:11:22:33:44:55")
        .build()
        .unwrap();
    
    assert_eq!(net.tap, Some("tap0".to_string()));
    assert_eq!(net.mac, Some("00:11:22:33:44:55".to_string()));
}
