using System.Reflection;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Raw;
using ZB.MOM.WW.OtOpcUa.Core.Abstractions;

namespace ZB.MOM.WW.OtOpcUa.AdminUI.Tests.Uns;

/// <summary>
///     Coverage guard for the <c>/raw</c> "New driver" dialog. <see cref="RawDriverTypeDialog"/> is the
///     ONLY surface that creates a <c>DriverInstance</c>, and its offered types are a hand-authored array
///     — so a driver whose factory is registered but whose entry was never added here is
///     <b>un-creatable in the AdminUI</b> with nothing failing anywhere (the MTConnect gap Task 16 found).
///     This test resolves through <see cref="DriverTypeNames.All"/>, so a newly registered driver type
///     fails here until the dialog offers it.
/// </summary>
/// <remarks>
///     There is no bUnit in this project, so the dialog's markup cannot be rendered. The offered set is
///     read by reflection off the private static <c>Types</c> table the markup enumerates — the same
///     substitute-for-a-component-test approach <c>DriverPageJsonConverterTests</c> uses.
/// </remarks>
public sealed class RawDriverTypeDialogCoverageTests
{
    private static IReadOnlyList<string> OfferedDriverTypes()
    {
        var field = typeof(RawDriverTypeDialog)
            .GetField("Types", BindingFlags.NonPublic | BindingFlags.Static);
        field.ShouldNotBeNull("RawDriverTypeDialog must expose its offered driver types as a static 'Types' table.");

        var table = (ValueTuple<string, string>[])field!.GetValue(null)!;
        return [.. table.Select(t => t.Item2)];
    }

    [Theory]
    [MemberData(nameof(AllDriverTypes))]
    public void New_driver_dialog_offers_every_registered_driver_type(string driverType)
        => OfferedDriverTypes().ShouldContain(
            driverType,
            $"RawDriverTypeDialog must offer DriverTypeNames.{driverType} — otherwise a driver of that " +
            "type can never be created in /raw, which is the only creation surface.");

    /// <summary>xUnit theory source over every registered driver-type constant.</summary>
    public static TheoryData<string> AllDriverTypes()
    {
        var data = new TheoryData<string>();
        foreach (var t in DriverTypeNames.All)
            data.Add(t);
        return data;
    }

    [Fact]
    public void Offered_driver_types_are_canonical_constants_and_unique()
    {
        var offered = OfferedDriverTypes();
        offered.Distinct(StringComparer.Ordinal).Count().ShouldBe(offered.Count, "duplicate driver-type entries");
        foreach (var t in offered)
            DriverTypeNames.All.ShouldContain(t, $"'{t}' is not a canonical DriverTypeNames constant.");
    }
}
