using Opc.Ua;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
using ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.Fakes;

namespace ZB.MOM.WW.OtOpcUa.Client.CLI.Tests;

public class DisableCommandTests
{
    /// <summary>Verifies that a successful disable prints a success message and targets the node.</summary>
    [Fact]
    public async Task Execute_Success_PrintsSuccessMessage()
    {
        var fakeService = new FakeOpcUaClientService
        {
            DisableResult = StatusCodes.Good
        };
        var factory = new FakeOpcUaClientServiceFactory(fakeService);
        var command = new DisableCommand(factory)
        {
            Url = "opc.tcp://localhost:4840",
            NodeId = "ns=2;s=MyAlarm"
        };

        using var console = TestConsoleHelper.CreateConsole();
        await command.ExecuteAsync(console);

        var output = TestConsoleHelper.GetOutput(console);
        output.ShouldContain("Disable successful");
        fakeService.DisableCalls.Count.ShouldBe(1);
        fakeService.DisableCalls[0].ShouldBe("ns=2;s=MyAlarm");
    }

    /// <summary>Verifies that a bad StatusCode from the service prints a failure message.</summary>
    [Fact]
    public async Task Execute_BadStatus_PrintsFailureMessage()
    {
        var fakeService = new FakeOpcUaClientService
        {
            DisableResult = StatusCodes.BadConditionAlreadyDisabled
        };
        var factory = new FakeOpcUaClientServiceFactory(fakeService);
        var command = new DisableCommand(factory)
        {
            Url = "opc.tcp://localhost:4840",
            NodeId = "ns=2;s=MyAlarm"
        };

        using var console = TestConsoleHelper.CreateConsole();
        await command.ExecuteAsync(console);

        var output = TestConsoleHelper.GetOutput(console);
        output.ShouldContain("Disable failed");
    }

    /// <summary>Verifies that the command disconnects and disposes in the finally block.</summary>
    [Fact]
    public async Task Execute_DisconnectsInFinally()
    {
        var fakeService = new FakeOpcUaClientService();
        var factory = new FakeOpcUaClientServiceFactory(fakeService);
        var command = new DisableCommand(factory)
        {
            Url = "opc.tcp://localhost:4840",
            NodeId = "ns=2;s=MyAlarm"
        };

        using var console = TestConsoleHelper.CreateConsole();
        await command.ExecuteAsync(console);

        fakeService.DisconnectCalled.ShouldBeTrue();
        fakeService.DisposeCalled.ShouldBeTrue();
    }
}
