namespace EntKube.Clusters.Domain;

/// <summary>
/// A KubernetesCluster represents a registered cluster that EntKube manages.
/// It holds the connection details, health state, and metadata needed to
/// interact with the cluster's API server. This is the aggregate root for
/// all cluster-related operations.
/// </summary>
public class KubernetesCluster
{
    public Guid Id { get; private set; }
    public string Name { get; private set; } = string.Empty;
    public string ApiServerUrl { get; private set; } = string.Empty;
    public ClusterStatus Status { get; private set; }
    public string? KubeConfigSecret { get; private set; }
    public DateTimeOffset RegisteredAt { get; private set; }
    public DateTimeOffset? LastHealthCheckAt { get; private set; }

    private KubernetesCluster() { }

    /// <summary>
    /// Registers a new cluster in the platform. At this point, we know the cluster
    /// exists and we have connection details — but we haven't verified connectivity yet.
    /// The cluster starts in a Pending state until a health check confirms it's reachable.
    /// </summary>
    public static KubernetesCluster Register(string name, string apiServerUrl, string? kubeConfigSecret)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("Cluster name is required.", nameof(name));
        }

        if (string.IsNullOrWhiteSpace(apiServerUrl))
        {
            throw new ArgumentException("API server URL is required.", nameof(apiServerUrl));
        }

        return new KubernetesCluster
        {
            Id = Guid.NewGuid(),
            Name = name,
            ApiServerUrl = apiServerUrl,
            KubeConfigSecret = kubeConfigSecret,
            Status = ClusterStatus.Pending,
            RegisteredAt = DateTimeOffset.UtcNow
        };
    }

    /// <summary>
    /// After a successful health check, we mark the cluster as connected.
    /// This means the platform can now schedule work against this cluster.
    /// </summary>
    public void MarkConnected()
    {
        Status = ClusterStatus.Connected;
        LastHealthCheckAt = DateTimeOffset.UtcNow;
    }

    /// <summary>
    /// When a health check fails, we mark the cluster as unreachable.
    /// Existing workloads keep running, but no new provisioning can happen
    /// until connectivity is restored.
    /// </summary>
    public void MarkUnreachable()
    {
        Status = ClusterStatus.Unreachable;
        LastHealthCheckAt = DateTimeOffset.UtcNow;
    }
}

public enum ClusterStatus
{
    Pending,
    Connected,
    Unreachable
}
