using EntKube.Clusters.Domain;
using FluentAssertions;

namespace EntKube.Clusters.Tests.Domain;

public class KubernetesClusterTests
{
    [Fact]
    public void Register_WithValidInputs_CreatesClusterInPendingState()
    {
        // Arrange & Act — A tenant admin registers a new cluster with its name and API URL.

        KubernetesCluster cluster = KubernetesCluster.Register(
            "production-eu",
            "https://k8s.example.com:6443",
            "secret-ref-123");

        // Assert — The cluster should be created with a unique ID and start in Pending state
        // because we haven't verified connectivity yet.

        cluster.Id.Should().NotBe(Guid.Empty);
        cluster.Name.Should().Be("production-eu");
        cluster.ApiServerUrl.Should().Be("https://k8s.example.com:6443");
        cluster.KubeConfigSecret.Should().Be("secret-ref-123");
        cluster.Status.Should().Be(ClusterStatus.Pending);
        cluster.RegisteredAt.Should().BeCloseTo(DateTimeOffset.UtcNow, TimeSpan.FromSeconds(5));
    }

    [Fact]
    public void Register_WithEmptyName_ThrowsArgumentException()
    {
        // Arrange & Act — Attempting to register a cluster without a name should fail
        // because every cluster needs a human-readable identifier.

        Action act = () => KubernetesCluster.Register("", "https://k8s.example.com", null);

        // Assert

        act.Should().Throw<ArgumentException>()
            .WithParameterName("name");
    }

    [Fact]
    public void Register_WithEmptyApiServerUrl_ThrowsArgumentException()
    {
        // Arrange & Act — Without an API URL, we can't communicate with the cluster.

        Action act = () => KubernetesCluster.Register("my-cluster", "", null);

        // Assert

        act.Should().Throw<ArgumentException>()
            .WithParameterName("apiServerUrl");
    }

    [Fact]
    public void MarkConnected_SetsStatusToConnected()
    {
        // Arrange — A freshly registered cluster in Pending state.

        KubernetesCluster cluster = KubernetesCluster.Register("test", "https://api.test", null);

        // Act — The health check confirms the cluster is reachable.

        cluster.MarkConnected();

        // Assert

        cluster.Status.Should().Be(ClusterStatus.Connected);
        cluster.LastHealthCheckAt.Should().NotBeNull();
    }

    [Fact]
    public void MarkUnreachable_SetsStatusToUnreachable()
    {
        // Arrange

        KubernetesCluster cluster = KubernetesCluster.Register("test", "https://api.test", null);
        cluster.MarkConnected();

        // Act — The health check fails.

        cluster.MarkUnreachable();

        // Assert

        cluster.Status.Should().Be(ClusterStatus.Unreachable);
        cluster.LastHealthCheckAt.Should().NotBeNull();
    }
}
