using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Client.CLI.Commands;
using ZB.MOM.WW.OtOpcUa.Client.CLI.Tests.Fakes;
using ZB.MOM.WW.OtOpcUa.Client.Shared.Models;

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

public class RedundancyCommandTests
{
    /// <summary>Verifies that Execute prints redundancy information correctly.</summary>
    [Fact]
    public async Task Execute_PrintsRedundancyInfo()
    {
        var fakeService = new FakeOpcUaClientService
        {
            RedundancyInfoResult = new RedundancyInfo(
                "Hot", 250, ["urn:server:primary", "urn:server:secondary"], "urn:app:myserver")
        };
        var factory = new FakeOpcUaClientServiceFactory(fakeService);
        var command = new RedundancyCommand(factory)
        {
            Url = "opc.tcp://localhost:4840"
        };

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

        var output = TestConsoleHelper.GetOutput(console);
        output.ShouldContain("Redundancy Mode:  Hot");
        output.ShouldContain("Service Level:    250");
        output.ShouldContain("Server URIs:");
        output.ShouldContain("  - urn:server:primary");
        output.ShouldContain("  - urn:server:secondary");
        output.ShouldContain("Application URI:  urn:app:myserver");
    }

    /// <summary>Verifies that Execute omits the Server URIs section when none are present.</summary>
    [Fact]
    public async Task Execute_NoServerUris_OmitsUriSection()
    {
        var fakeService = new FakeOpcUaClientService
        {
            RedundancyInfoResult = new RedundancyInfo(
                "None", 100, [], "urn:app:standalone")
        };
        var factory = new FakeOpcUaClientServiceFactory(fakeService);
        var command = new RedundancyCommand(factory)
        {
            Url = "opc.tcp://localhost:4840"
        };

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

        var output = TestConsoleHelper.GetOutput(console);
        output.ShouldContain("Redundancy Mode:  None");
        output.ShouldContain("Service Level:    100");
        output.ShouldNotContain("Server URIs:");
        output.ShouldContain("Application URI:  urn:app:standalone");
    }

    /// <summary>Verifies that Execute calls GetRedundancyInfo on the service.</summary>
    [Fact]
    public async Task Execute_CallsGetRedundancyInfo()
    {
        var fakeService = new FakeOpcUaClientService();
        var factory = new FakeOpcUaClientServiceFactory(fakeService);
        var command = new RedundancyCommand(factory)
        {
            Url = "opc.tcp://localhost:4840"
        };

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

        fakeService.GetRedundancyInfoCalled.ShouldBeTrue();
    }

    /// <summary>Verifies that Execute 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 RedundancyCommand(factory)
        {
            Url = "opc.tcp://localhost:4840"
        };

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

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