// Copyright 2026 The NATS Authors
// Licensed under the Apache License, Version 2.0

using Shouldly;
using ZB.MOM.NatsNet.Server.Internal;

namespace ZB.MOM.NatsNet.Server.Tests.Internal;

public sealed class ServiceManagerTests
{
    public ServiceManagerTests()
    {
        ServiceManager.Init(static _ => null);
        ServiceManager.SetServiceName("nats-server");
    }

    [Fact]
    public void SetServiceName_WhenProvided_StoresConfiguredName()
    {
        ServiceManager.SetServiceName("custom-svc");

        ServiceManager.CurrentServiceName.ShouldBe("custom-svc");
    }

    [Fact]
    public void IsWindowsService_WhenDockerized_ReturnsFalse()
    {
        ServiceManager.Init(static key => key == "NATS_DOCKERIZED" ? "1" : null);

        ServiceManager.IsWindowsService(() => true).ShouldBeFalse();
    }

    [Fact]
    public void Run_WhenNotRunningAsWindowsService_InvokesStartAction()
    {
        var called = false;

        var error = ServiceManager.Run(() => called = true, () => false);

        error.ShouldBeNull();
        called.ShouldBeTrue();
    }

    [Fact]
    public void Execute_WhenServerNotReady_ReturnsFailureExitCode()
    {
        using var started = new ManualResetEventSlim(false);
        var reloadCalls = 0;
        var shutdownCalls = 0;

        var result = ServiceManager.Execute(
            startServer: () => started.Set(),
            readyForConnections: _ => false,
            changes: [],
            reloadConfig: () => reloadCalls++,
            shutdown: () => shutdownCalls++,
            reopenLogFile: () => { },
            enterLameDuckMode: () => { });

        result.exitCode.ShouldBe((uint)1);
        result.serviceSpecificExitCode.ShouldBeFalse();
        started.Wait(TimeSpan.FromSeconds(1)).ShouldBeTrue();
        reloadCalls.ShouldBe(0);
        shutdownCalls.ShouldBe(0);
    }

    [Fact]
    public void Execute_WhenCommandsReceived_DispatchesControlHandlers()
    {
        var reloadCalls = 0;
        var shutdownCalls = 0;
        var reopenCalls = 0;
        var ldmCalled = false;
        using var ldmInvoked = new ManualResetEventSlim(false);

        var result = ServiceManager.Execute(
            startServer: () => { },
            readyForConnections: _ => true,
            changes: [ServiceControlCommand.ReopenLog, ServiceControlCommand.ParamChange, ServiceControlCommand.LameDuckMode, ServiceControlCommand.Stop],
            reloadConfig: () => reloadCalls++,
            shutdown: () => shutdownCalls++,
            reopenLogFile: () => reopenCalls++,
            enterLameDuckMode: () =>
            {
                ldmCalled = true;
                ldmInvoked.Set();
            });

        result.exitCode.ShouldBe((uint)0);
        result.serviceSpecificExitCode.ShouldBeFalse();
        reloadCalls.ShouldBe(1);
        reopenCalls.ShouldBe(1);
        shutdownCalls.ShouldBe(1);
        ldmInvoked.Wait(TimeSpan.FromSeconds(1)).ShouldBeTrue();
        ldmCalled.ShouldBeTrue();
    }
}
