using System.ComponentModel;
using System.Text.Json;
using k8s;
using k8s.Autorest;
using k8s.Models;
using LazyBear.MCP.Services.ToolRegistry;
using ModelContextProtocol.Server;

namespace LazyBear.MCP.Services.Kubernetes;

[McpServerToolType]
public sealed class K8sDeploymentTools(
    K8sClientProvider clientProvider,
    IConfiguration configuration,
    ToolRegistryService registry,
    ILogger<K8sDeploymentTools>? logger = null)
    : KubernetesToolsBase(clientProvider, configuration, registry, logger)
{
    private const int MinReplicas = 0;
    private const int MaxReplicas = 100;

    [McpServerTool, Description("Список deployment в namespace")]
    public async Task<string> ListDeployments(
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("ListDeployments", out var enabledError)) return enabledError;

        ValidateNamespace(@namespace ?? _defaultNamespace, nameof(@namespace));
        var ns = ResolveNamespace(@namespace);
        if (!TryGetClient(out var client, out var clientError))
        {
            return clientError;
        }

        try
        {
            var deployments = await client.AppsV1.ListNamespacedDeploymentAsync(ns, cancellationToken: cancellationToken);

            if (deployments.Items.Count == 0)
            {
                return $"В namespace '{ns}' deployment не найдены.";
            }

            var lines = deployments.Items.Select(dep =>
            {
                var name = dep.Metadata?.Name ?? "unknown";
                var desired = dep.Spec?.Replicas ?? 0;
                var ready = dep.Status?.ReadyReplicas ?? 0;
                var available = dep.Status?.AvailableReplicas ?? 0;
                return $"{name}: desired={desired}, ready={ready}, available={available}";
            });

            return $"Deployment namespace '{ns}':\n{string.Join('\n', lines)}";
        }
        catch (Exception ex)
        {
            return FormatError("list_deployments", ns, ex);
        }
    }

    [McpServerTool, Description("Масштабировать deployment")]
    public async Task<string> ScaleDeployment(
        [Description("Имя deployment")] string name,
        [Description("Новое количество реплик")] int replicas,
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("ScaleDeployment", out var enabledError)) return enabledError;

        ValidateResourceName(name, nameof(name));
        ValidateNamespace(@namespace ?? _defaultNamespace, nameof(@namespace));
        
        if (replicas < MinReplicas || replicas > MaxReplicas)
        {
            return $"Invalid replicas value: {replicas}. Must be between {MinReplicas} and {MaxReplicas}.";
        }
        
        var ns = ResolveNamespace(@namespace);
        if (!TryGetClient(out var client, out var clientError))
        {
            return clientError;
        }

        try
        {
            var deployment = await client.AppsV1.ReadNamespacedDeploymentAsync(name, ns, cancellationToken: cancellationToken);

            deployment.Spec ??= new V1DeploymentSpec();
            deployment.Spec.Replicas = replicas;

            await client.AppsV1.ReplaceNamespacedDeploymentAsync(deployment, name, ns, cancellationToken: cancellationToken);

            return $"Deployment '{name}' в namespace '{ns}' масштабирован до {replicas} реплик.";
        }
        catch (Exception ex)
        {
            return FormatError("scale_deployment", ns, ex, name);
        }
    }

    [McpServerTool, Description("Статус rollout deployment")]
    public async Task<string> GetRolloutStatus(
        [Description("Имя deployment")] string name,
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("GetRolloutStatus", out var enabledError)) return enabledError;

        ValidateResourceName(name, nameof(name));
        ValidateNamespace(@namespace ?? _defaultNamespace, nameof(@namespace));
        var ns = ResolveNamespace(@namespace);
        if (!TryGetClient(out var client, out var clientError))
        {
            return clientError;
        }

        try
        {
            var deployment = await client.AppsV1.ReadNamespacedDeploymentStatusAsync(name, ns, cancellationToken: cancellationToken);

            var desired = deployment.Spec?.Replicas ?? 0;
            var updated = deployment.Status?.UpdatedReplicas ?? 0;
            var ready = deployment.Status?.ReadyReplicas ?? 0;
            var available = deployment.Status?.AvailableReplicas ?? 0;

            return $"Rollout '{name}' в namespace '{ns}': desired={desired}, updated={updated}, ready={ready}, available={available}";
        }
        catch (Exception ex)
        {
            return FormatError("get_rollout_status", ns, ex, name);
        }
    }

    [McpServerTool, Description("Перезапустить deployment (rolling restart)")]
    public async Task<string> RestartDeployment(
        [Description("Имя deployment")] string name,
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("RestartDeployment", out var enabledError)) return enabledError;

        ValidateResourceName(name, nameof(name));
        ValidateNamespace(@namespace ?? _defaultNamespace, nameof(@namespace));
        var ns = ResolveNamespace(@namespace);
        if (!TryGetClient(out var client, out var clientError))
        {
            return clientError;
        }

        try
        {
            var patchJson = JsonSerializer.Serialize(new
            {
                spec = new
                {
                    template = new
                    {
                        metadata = new
                        {
                            annotations = new Dictionary<string, string>
                            {
                                ["kubectl.kubernetes.io/restartedAt"] = DateTimeOffset.UtcNow.ToString("O")
                            }
                        }
                    }
                }
            });

            var patch = new V1Patch(patchJson, V1Patch.PatchType.StrategicMergePatch);
            await client.AppsV1.PatchNamespacedDeploymentAsync(patch, name, ns, cancellationToken: cancellationToken);

            return $"Deployment '{name}' в namespace '{ns}' отправлен на rolling restart.";
        }
        catch (Exception ex)
        {
            return FormatError("restart_deployment", ns, ex, name);
        }
    }
}
