// Tests for mecha10_cli::services::docker::types

use mecha10_cli::services::docker::types::*;

// === DockerInfo Tests ===

#[test]
fn test_docker_info_creation() {
    let info = DockerInfo {
        version: "Docker version 24.0.0".to_string(),
        compose_version: "Docker Compose version v2.20.0".to_string(),
    };

    assert_eq!(info.version, "Docker version 24.0.0");
    assert_eq!(info.compose_version, "Docker Compose version v2.20.0");
}

#[test]
fn test_docker_info_clone() {
    let info1 = DockerInfo {
        version: "Docker version 24.0.0".to_string(),
        compose_version: "Docker Compose version v2.20.0".to_string(),
    };

    let info2 = info1.clone();

    assert_eq!(info1.version, info2.version);
    assert_eq!(info1.compose_version, info2.compose_version);
}

#[test]
fn test_docker_info_debug() {
    let info = DockerInfo {
        version: "Docker version 24.0.0".to_string(),
        compose_version: "Docker Compose version v2.20.0".to_string(),
    };

    let debug_str = format!("{:?}", info);
    assert!(debug_str.contains("DockerInfo"));
    assert!(debug_str.contains("24.0.0"));
    assert!(debug_str.contains("v2.20.0"));
}

#[test]
fn test_docker_info_with_empty_strings() {
    let info = DockerInfo {
        version: String::new(),
        compose_version: String::new(),
    };

    assert_eq!(info.version, "");
    assert_eq!(info.compose_version, "");
}

#[test]
fn test_docker_info_with_various_formats() {
    // Test different version string formats
    let formats = vec![
        ("Docker version 24.0.0, build abc123", "v2.20.0"),
        ("24.0.0", "2.20.0"),
        (
            "Docker Engine - Community, Version 24.0.0",
            "Docker Compose version v2.20.0",
        ),
    ];

    for (version, compose) in formats {
        let info = DockerInfo {
            version: version.to_string(),
            compose_version: compose.to_string(),
        };

        assert_eq!(info.version, version);
        assert_eq!(info.compose_version, compose);
    }
}

// === ContainerInfo Tests ===

#[test]
fn test_container_info_creation() {
    let info = ContainerInfo {
        name: "mecha10-redis".to_string(),
        status: "Up 2 hours".to_string(),
        ports: Some("0.0.0.0:6379->6379/tcp".to_string()),
    };

    assert_eq!(info.name, "mecha10-redis");
    assert_eq!(info.status, "Up 2 hours");
    assert_eq!(info.ports, Some("0.0.0.0:6379->6379/tcp".to_string()));
}

#[test]
fn test_container_info_without_ports() {
    let info = ContainerInfo {
        name: "test-container".to_string(),
        status: "Exited (0) 5 minutes ago".to_string(),
        ports: None,
    };

    assert_eq!(info.name, "test-container");
    assert_eq!(info.status, "Exited (0) 5 minutes ago");
    assert!(info.ports.is_none());
}

#[test]
fn test_container_info_clone() {
    let info1 = ContainerInfo {
        name: "test".to_string(),
        status: "Running".to_string(),
        ports: Some("8080:80".to_string()),
    };

    let info2 = info1.clone();

    assert_eq!(info1.name, info2.name);
    assert_eq!(info1.status, info2.status);
    assert_eq!(info1.ports, info2.ports);
}

#[test]
fn test_container_info_debug() {
    let info = ContainerInfo {
        name: "mecha10-redis".to_string(),
        status: "Up 2 hours".to_string(),
        ports: Some("6379:6379".to_string()),
    };

    let debug_str = format!("{:?}", info);
    assert!(debug_str.contains("ContainerInfo"));
    assert!(debug_str.contains("mecha10-redis"));
    assert!(debug_str.contains("Up 2 hours"));
}

#[test]
fn test_container_info_with_multiple_ports() {
    let info = ContainerInfo {
        name: "web-server".to_string(),
        status: "Up 1 hour".to_string(),
        ports: Some("0.0.0.0:80->80/tcp, 0.0.0.0:443->443/tcp".to_string()),
    };

    assert!(info.ports.is_some());
    let ports = info.ports.unwrap();
    assert!(ports.contains("80"));
    assert!(ports.contains("443"));
}

#[test]
fn test_container_info_with_various_statuses() {
    let statuses = vec![
        "Up 5 minutes",
        "Up 2 hours",
        "Up 3 days",
        "Exited (0) 1 minute ago",
        "Exited (1) 10 minutes ago",
        "Restarting (1) 5 seconds ago",
        "Created",
        "Dead",
    ];

    for status in statuses {
        let info = ContainerInfo {
            name: "test".to_string(),
            status: status.to_string(),
            ports: None,
        };

        assert_eq!(info.status, status);
    }
}

#[test]
fn test_container_info_empty_strings() {
    let info = ContainerInfo {
        name: String::new(),
        status: String::new(),
        ports: Some(String::new()),
    };

    assert_eq!(info.name, "");
    assert_eq!(info.status, "");
    assert_eq!(info.ports, Some(String::new()));
}

#[test]
fn test_container_info_with_unicode() {
    let info = ContainerInfo {
        name: "容器-test".to_string(),
        status: "Running ✓".to_string(),
        ports: None,
    };

    assert_eq!(info.name, "容器-test");
    assert_eq!(info.status, "Running ✓");
}

#[test]
fn test_container_info_ports_option() {
    let info_with_ports = ContainerInfo {
        name: "test1".to_string(),
        status: "Up".to_string(),
        ports: Some("8080:80".to_string()),
    };

    let info_without_ports = ContainerInfo {
        name: "test2".to_string(),
        status: "Up".to_string(),
        ports: None,
    };

    assert!(info_with_ports.ports.is_some());
    assert!(info_without_ports.ports.is_none());
}

// === Collection Tests ===

#[test]
fn test_container_info_vec() {
    let containers = [
        ContainerInfo {
            name: "redis".to_string(),
            status: "Up".to_string(),
            ports: Some("6379:6379".to_string()),
        },
        ContainerInfo {
            name: "postgres".to_string(),
            status: "Up".to_string(),
            ports: Some("5432:5432".to_string()),
        },
    ];

    assert_eq!(containers.len(), 2);
    assert_eq!(containers[0].name, "redis");
    assert_eq!(containers[1].name, "postgres");
}

#[test]
fn test_docker_info_and_container_info_independence() {
    let docker_info = DockerInfo {
        version: "24.0.0".to_string(),
        compose_version: "v2.20.0".to_string(),
    };

    let container_info = ContainerInfo {
        name: "test".to_string(),
        status: "Up".to_string(),
        ports: None,
    };

    // These should be independent types
    assert_eq!(docker_info.version, "24.0.0");
    assert_eq!(container_info.name, "test");
}
