using System.Collections.Concurrent;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;

namespace StellaOps.Scanner.Core.Security;

public sealed class RestartOnlyPluginGuard : IPluginCatalogGuard
{
    private readonly ConcurrentDictionary<string, byte> plugins = new(StringComparer.OrdinalIgnoreCase);
    private bool sealedState;

    public RestartOnlyPluginGuard(IEnumerable<string>? initialPlugins = null)
    {
        if (initialPlugins is not null)
        {
            foreach (var plugin in initialPlugins)
            {
                var normalized = Normalize(plugin);
                plugins.TryAdd(normalized, 0);
            }
        }
    }

    public IReadOnlyCollection<string> KnownPlugins => plugins.Keys.ToArray();

    public bool IsSealed => Volatile.Read(ref sealedState);

    public void EnsureRegistrationAllowed(string pluginPath)
    {
        ArgumentException.ThrowIfNullOrWhiteSpace(pluginPath);

        var normalized = Normalize(pluginPath);
        if (IsSealed && !plugins.ContainsKey(normalized))
        {
            throw new InvalidOperationException($"Plug-in '{pluginPath}' cannot be registered after startup. Restart required.");
        }

        plugins.TryAdd(normalized, 0);
    }

    public void Seal()
    {
        Volatile.Write(ref sealedState, true);
    }

    private static string Normalize(string path)
    {
        var full = Path.GetFullPath(path);
        return full.TrimEnd(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
    }
}
