using System.Collections.Concurrent;

namespace LazyBear.MCP.Services.ToolRegistry;

/// <summary>
/// Singleton. Хранит runtime-состояние включённости модулей и отдельных инструментов.
/// Thread-safe. Уведомляет подписчиков при любом изменении.
/// </summary>
public sealed class ToolRegistryService
{
    private readonly ConcurrentDictionary<string, bool> _moduleEnabled = new(StringComparer.OrdinalIgnoreCase);
    private readonly ConcurrentDictionary<string, bool> _toolEnabled = new(StringComparer.OrdinalIgnoreCase);
    private readonly List<IToolModule> _modules = [];
    private readonly Lock _modulesLock = new();

    /// <summary>Вызывается при любом изменении состояния.</summary>
    public event Action? StateChanged;

    // ── Регистрация ──────────────────────────────────────────────────────────

    public void RegisterModule(IToolModule module)
    {
        lock (_modulesLock)
        {
            if (_modules.Any(m => string.Equals(m.ModuleName, module.ModuleName, StringComparison.OrdinalIgnoreCase)))
                return;

            _modules.Add(module);
        }

        _moduleEnabled.TryAdd(module.ModuleName, true);

        foreach (var tool in module.ToolNames)
        {
            _toolEnabled.TryAdd(MakeKey(module.ModuleName, tool), true);
        }
    }

    // ── Запросы состояния ────────────────────────────────────────────────────

    public IReadOnlyList<IToolModule> GetModules()
    {
        lock (_modulesLock)
        {
            return _modules.ToList();
        }
    }

    public bool IsModuleEnabled(string moduleName) =>
        _moduleEnabled.GetValueOrDefault(moduleName, true);

    public bool IsToolConfiguredEnabled(string moduleName, string toolName) =>
        _toolEnabled.GetValueOrDefault(MakeKey(moduleName, toolName), true);

    public bool IsToolEnabled(string moduleName, string toolName) =>
        IsModuleEnabled(moduleName) &&
        IsToolConfiguredEnabled(moduleName, toolName);

    // ── Переключение ─────────────────────────────────────────────────────────

    public void SetModuleEnabled(string moduleName, bool enabled)
    {
        _moduleEnabled[moduleName] = enabled;
        StateChanged?.Invoke();
    }

    public void SetToolEnabled(string moduleName, string toolName, bool enabled)
    {
        _toolEnabled[MakeKey(moduleName, toolName)] = enabled;
        StateChanged?.Invoke();
    }

    public void ToggleModule(string moduleName) =>
        SetModuleEnabled(moduleName, !IsModuleEnabled(moduleName));

    public void ToggleTool(string moduleName, string toolName) =>
        SetToolEnabled(moduleName, toolName, !IsToolConfiguredEnabled(moduleName, toolName));

    // ── Счётчики для Overview ─────────────────────────────────────────────────

    public (int Active, int Total) GetToolCounts(string moduleName)
    {
        lock (_modulesLock)
        {
            var module = _modules.FirstOrDefault(m =>
                string.Equals(m.ModuleName, moduleName, StringComparison.OrdinalIgnoreCase));

            if (module is null) return (0, 0);

            var total = module.ToolNames.Count;
            var active = module.ToolNames.Count(t => IsToolEnabled(moduleName, t));
            return (active, total);
        }
    }

    public (int Enabled, int Total) GetConfiguredToolCounts(string moduleName)
    {
        lock (_modulesLock)
        {
            var module = _modules.FirstOrDefault(m =>
                string.Equals(m.ModuleName, moduleName, StringComparison.OrdinalIgnoreCase));

            if (module is null) return (0, 0);

            var total = module.ToolNames.Count;
            var enabled = module.ToolNames.Count(t => IsToolConfiguredEnabled(moduleName, t));
            return (enabled, total);
        }
    }

    // ── Helpers ───────────────────────────────────────────────────────────────

    private static string MakeKey(string module, string tool) => $"{module}::{tool}";
}
