using NATS.Server;
using NATS.Server.Auth;
using NATS.Server.Configuration;

namespace NATS.Server.Core.Tests;

public class ConfigReloadTests
{
    [Fact]
    public void Diff_NoChanges_ReturnsEmpty()
    {
        var old = new NatsOptions { Port = 4222, Debug = true };
        var @new = new NatsOptions { Port = 4222, Debug = true };
        var changes = ConfigReloader.Diff(old, @new);
        changes.ShouldBeEmpty();
    }

    [Fact]
    public void Diff_ReloadableChange_ReturnsChange()
    {
        var old = new NatsOptions { Debug = false };
        var @new = new NatsOptions { Debug = true };
        var changes = ConfigReloader.Diff(old, @new);
        changes.Count.ShouldBe(1);
        changes[0].Name.ShouldBe("Debug");
        changes[0].IsLoggingChange.ShouldBeTrue();
    }

    [Fact]
    public void Diff_NonReloadableChange_ReturnsNonReloadableChange()
    {
        var old = new NatsOptions { Port = 4222 };
        var @new = new NatsOptions { Port = 5222 };
        var changes = ConfigReloader.Diff(old, @new);
        changes.Count.ShouldBe(1);
        changes[0].IsNonReloadable.ShouldBeTrue();
    }

    [Fact]
    public void Diff_MultipleChanges_ReturnsAll()
    {
        var old = new NatsOptions { Debug = false, MaxPayload = 1024 };
        var @new = new NatsOptions { Debug = true, MaxPayload = 2048 };
        var changes = ConfigReloader.Diff(old, @new);
        changes.Count.ShouldBe(2);
    }

    [Fact]
    public void Diff_AuthChange_MarkedCorrectly()
    {
        var old = new NatsOptions { Username = "alice" };
        var @new = new NatsOptions { Username = "bob" };
        var changes = ConfigReloader.Diff(old, @new);
        changes[0].IsAuthChange.ShouldBeTrue();
    }

    [Fact]
    public void Diff_TlsChange_MarkedCorrectly()
    {
        var old = new NatsOptions { TlsCert = "/old/cert.pem" };
        var @new = new NatsOptions { TlsCert = "/new/cert.pem" };
        var changes = ConfigReloader.Diff(old, @new);
        changes[0].IsTlsChange.ShouldBeTrue();
    }

    [Fact]
    public void Validate_NonReloadableChanges_ReturnsErrors()
    {
        var changes = new List<IConfigChange>
        {
            new ConfigChange("Port", isNonReloadable: true),
        };
        var errors = ConfigReloader.Validate(changes);
        errors.Count.ShouldBe(1);
        errors[0].ShouldContain("Port");
    }

    [Fact]
    public void MergeWithCli_CliOverridesConfig()
    {
        var fromConfig = new NatsOptions { Port = 5222, Debug = true };
        var cliFlags = new HashSet<string> { "Port" };
        var cliValues = new NatsOptions { Port = 4222 };

        ConfigReloader.MergeCliOverrides(fromConfig, cliValues, cliFlags);
        fromConfig.Port.ShouldBe(4222); // CLI wins
        fromConfig.Debug.ShouldBeTrue(); // config value kept (not in CLI)
    }
}
