namespace EntKube.Provisioning.Domain;

/// <summary>
/// A ServiceInstance represents a shared Kubernetes application (MinIO, CloudNativePG,
/// Keycloak, etc.) that has been provisioned on a specific cluster. It tracks the
/// service type, desired state, current state, and the cluster it's deployed to.
/// This is the aggregate root for provisioning operations.
/// </summary>
public class ServiceInstance
{
    public Guid Id { get; private set; }
    public Guid ClusterId { get; private set; }
    public ServiceType ServiceType { get; private set; }
    public string Name { get; private set; } = string.Empty;
    public string Namespace { get; private set; } = string.Empty;
    public ServiceState DesiredState { get; private set; }
    public ServiceState CurrentState { get; private set; }
    public DateTimeOffset CreatedAt { get; private set; }
    public DateTimeOffset? LastReconcileAt { get; private set; }

    private ServiceInstance() { }

    /// <summary>
    /// Requests provisioning of a new shared service on a given cluster.
    /// The service starts in a Pending state — the reconciliation loop will
    /// pick it up and deploy the necessary Helm chart or Kubernetes resources.
    /// </summary>
    public static ServiceInstance Provision(Guid clusterId, ServiceType serviceType, string name, string ns)
    {
        if (string.IsNullOrWhiteSpace(name))
        {
            throw new ArgumentException("Service name is required.", nameof(name));
        }

        if (string.IsNullOrWhiteSpace(ns))
        {
            throw new ArgumentException("Namespace is required.", nameof(ns));
        }

        return new ServiceInstance
        {
            Id = Guid.NewGuid(),
            ClusterId = clusterId,
            ServiceType = serviceType,
            Name = name,
            Namespace = ns,
            DesiredState = ServiceState.Running,
            CurrentState = ServiceState.Pending,
            CreatedAt = DateTimeOffset.UtcNow
        };
    }

    /// <summary>
    /// The reconciliation loop calls this after successfully deploying or verifying
    /// the service is running on the cluster.
    /// </summary>
    public void MarkRunning()
    {
        CurrentState = ServiceState.Running;
        LastReconcileAt = DateTimeOffset.UtcNow;
    }

    /// <summary>
    /// When the reconciliation loop detects the service is degraded or unreachable.
    /// </summary>
    public void MarkDegraded()
    {
        CurrentState = ServiceState.Degraded;
        LastReconcileAt = DateTimeOffset.UtcNow;
    }

    /// <summary>
    /// A tenant requests decommissioning of the service. We set the desired state
    /// to Decommissioned and the reconciliation loop will handle teardown.
    /// </summary>
    public void RequestDecommission()
    {
        DesiredState = ServiceState.Decommissioned;
    }
}

public enum ServiceType
{
    MinIO,
    CloudNativePG,
    Keycloak
}

public enum ServiceState
{
    Pending,
    Running,
    Degraded,
    Decommissioned
}
