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

namespace LazyBear.MCP.Services.Kubernetes;

[McpServerToolType]
public sealed class K8sNetworkTools(
    K8sClientProvider clientProvider,
    IConfiguration configuration,
    ToolRegistryService registry,
    ILogger<K8sNetworkTools>? logger = null)
    : KubernetesToolsBase(clientProvider, configuration, registry, logger)
{
    [McpServerTool, Description("Список service в namespace")]
    public async Task<string> ListServices(
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("ListServices", 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 services = await client.CoreV1.ListNamespacedServiceAsync(ns, cancellationToken: cancellationToken);

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

            var lines = services.Items.Select(svc =>
            {
                var name = svc.Metadata?.Name ?? "unknown";
                var type = svc.Spec?.Type ?? "ClusterIP";
                var clusterIp = svc.Spec?.ClusterIP ?? "-";
                var ports = svc.Spec?.Ports is null
                    ? "-"
                    : string.Join(",", svc.Spec.Ports.Select(p => $"{p.Port}/{p.Protocol}"));

                return $"{name}: type={type}, clusterIp={clusterIp}, ports={ports}";
            });

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

    [McpServerTool, Description("Детали service")]
    public async Task<string> GetServiceDetails(
        [Description("Имя service")] string name,
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("GetServiceDetails", 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 service = await client.CoreV1.ReadNamespacedServiceAsync(name, ns, cancellationToken: cancellationToken);

            var type = service.Spec?.Type ?? "ClusterIP";
            var clusterIp = service.Spec?.ClusterIP ?? "-";
            var externalIps = service.Spec?.ExternalIPs is null ? "-" : string.Join(",", service.Spec.ExternalIPs);
            var selector = service.Spec?.Selector is null
                ? "-"
                : string.Join(",", service.Spec.Selector.Select(x => $"{x.Key}={x.Value}"));
            var ports = service.Spec?.Ports is null
                ? "-"
                : string.Join(",", service.Spec.Ports.Select(p => $"{p.Name ?? "port"}:{p.Port}->{p.TargetPort}"));

            return $"Service '{name}' namespace '{ns}': type={type}, clusterIp={clusterIp}, externalIps={externalIps}, selector={selector}, ports={ports}";
        }
        catch (Exception ex)
        {
            return FormatError("get_service_details", ns, ex, name);
        }
    }

    [McpServerTool, Description("Список ingress в namespace")]
    public async Task<string> ListIngresses(
        [Description("Namespace Kubernetes")] string? @namespace = null,
        CancellationToken cancellationToken = default)
    {
        if (!TryCheckEnabled("ListIngresses", 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 ingresses = await client.NetworkingV1.ListNamespacedIngressAsync(ns, cancellationToken: cancellationToken);

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

            var lines = ingresses.Items.Select(ing =>
            {
                var name = ing.Metadata?.Name ?? "unknown";
                var rules = ing.Spec?.Rules is null
                    ? "-"
                    : string.Join(";", ing.Spec.Rules.Select(r =>
                    {
                        var host = string.IsNullOrWhiteSpace(r.Host) ? "*" : r.Host;
                        var paths = r.Http?.Paths is null
                            ? "-"
                            : string.Join(",", r.Http.Paths.Select(p =>
                            {
                                var serviceName = p.Backend?.Service?.Name ?? "-";
                                var servicePort = p.Backend?.Service?.Port?.Number?.ToString() ?? p.Backend?.Service?.Port?.Name ?? "-";
                                return $"{p.Path ?? "/"}->{serviceName}:{servicePort}";
                            }));

                        return $"{host}:{paths}";
                    }));

                return $"{name}: rules={rules}";
            });

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