using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Commons.Browsing;
using ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser;

namespace ZB.MOM.WW.OtOpcUa.Driver.OpcUaClient.Browser.IntegrationTests;

/// <summary>
///     End-to-end test against opc-plc Docker fixture. Validates that NodeId strings returned
///     by RootAsync/ExpandAsync round-trip cleanly through ExpandAsync — the regression test
///     for namespace-stable address encoding.
/// </summary>
[Trait("Category", "Integration"), Trait("Fixture", "opc-plc")]
public class BrowseRoundTripTests
{
    [Fact]
    public async Task Three_level_expand_round_trips_resolve_back()
    {
        var endpoint = Environment.GetEnvironmentVariable("OPCUA_SIM_ENDPOINT")
                       ?? "opc.tcp://10.100.0.35:50000";
        // Numeric ordinals because the production browser uses default System.Text.Json
        // without a JsonStringEnumConverter (SecurityPolicy.None=0, SecurityMode.None=0,
        // AuthType.Anonymous=0).
        var json = $$"""
            {
                "EndpointUrl":"{{endpoint}}",
                "SecurityPolicy":0,"SecurityMode":0,"AuthType":0,
                "SessionTimeout":"00:01:00","Timeout":"00:00:10","PerEndpointConnectTimeout":"00:00:10"
            }
            """;

        var browser = new OpcUaClientDriverBrowser();
        await using var session = await browser.OpenAsync(json, TestContext.Current.CancellationToken);

        var roots = await session.RootAsync(TestContext.Current.CancellationToken);
        var current = roots.FirstOrDefault(n => n.HasChildrenHint);
        current.ShouldNotBeNull("expected at least one Folder under ObjectsFolder on opc-plc");

        // Drill down up to 2 more levels by alternately expanding the first Folder
        for (var depth = 0; depth < 2; depth++)
        {
            var next = await session.ExpandAsync(current!.NodeId, TestContext.Current.CancellationToken);
            var step = next.FirstOrDefault(n => n.HasChildrenHint);
            if (step is null) break;
            current = step;
        }

        // Round-trip the leaf-most reachable folder string — must resolve back through the
        // namespace map, prove the nsu= encoding survives.
        var children = await session.ExpandAsync(current!.NodeId, TestContext.Current.CancellationToken);
        children.ShouldNotBeNull();
    }
}
