using System.Text.Json;
using System.Text.Json.Serialization;
using Shouldly;
using Xunit;

namespace ZB.MOM.WW.OtOpcUa.Driver.Modbus.Tests;

/// <summary>
///     v3 factory RawTags binding. Under v3 tags are delivered as authored raw tags
///     (<c>{rawPath, tagConfig, writeIdempotent}</c>) — the tag's address enums live INSIDE the opaque
///     <c>tagConfig</c> blob (authored by the AdminUI <c>ModbusTagConfigModel</c>), not in the driver
///     config DTO. This proves the factory binds a <c>rawTags</c> array and documents that the legacy
///     structured/AddressString <c>tags</c> path (and the FB-9 numeric-vs-string tag-enum bug class it
///     carried) is retired.
/// </summary>
public sealed class ModbusDriverConfigEnumSerializationTests
{
    // Mirrors the AdminUI ModbusDriverPage._jsonOpts: camelCase + string enums.
    private static readonly JsonSerializerOptions _adminPageOpts = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        Converters = { new JsonStringEnumConverter() },
    };

    /// <summary>Verifies the factory binds an AdminUI-authored Modbus config carrying an Int64
    /// holding-register raw tag (string enums inside the tagConfig blob) without throwing.</summary>
    [Fact]
    public void Factory_binds_admin_authored_rawTags_config()
    {
        var tag = new ModbusTagDefinition("cell/modbus/dev1/Int64Tag", ModbusRegion.HoldingRegisters, (ushort)100, ModbusDataType.Int64);
        var opts = new ModbusDriverOptions { Host = "10.0.0.5", Port = 502, UnitId = 1, RawTags = ModbusRawTags.Entries(new[] { tag }) };
        var blob = JsonSerializer.Serialize(opts, _adminPageOpts);
        // The raw tag serialises as {rawPath, tagConfig, writeIdempotent}; the address enums live
        // inside the (string-encoded) tagConfig blob.
        blob.ShouldContain("\"rawPath\":\"cell/modbus/dev1/Int64Tag\"");
        blob.ShouldContain("Int64");

        using var driver = ModbusDriverFactoryExtensions.CreateInstance("mb-test", blob);
        driver.DriverType.ShouldBe("Modbus");
    }

    /// <summary>Documents the retirement of the legacy structured <c>tags</c> path: a legacy tag array
    /// (including the pre-fix numeric-enum shape) is no longer a recognised property, so it binds nothing
    /// and the factory succeeds rather than throwing on its enum shape.</summary>
    [Fact]
    public void Factory_ignores_the_retired_structured_tags_array()
    {
        const string legacyBlob =
            "{\"host\":\"10.0.0.5\",\"port\":502,\"unitId\":1,\"tags\":[" +
            "{\"name\":\"Int64Tag\",\"region\":3,\"address\":100,\"dataType\":5}]}";
        using var driver = ModbusDriverFactoryExtensions.CreateInstance("mb-test", legacyBlob);
        driver.DriverType.ShouldBe("Modbus");
    }
}
