using System.Text.Json;
using System.Text.Json.Serialization;
using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.AdminUI.Components.Shared.Drivers.Forms;
using ZB.MOM.WW.OtOpcUa.Driver.Modbus;

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

/// <summary>
///     Round-trip + enum-serialization guard for the Modbus <b>driver</b> (channel/protocol) form model.
///     Reproduces the historical driver-enum-serialization bug: enums MUST serialize as their name strings
///     (JsonStringEnumConverter) with camelCase keys, or the runtime factory faults on the numeric form.
/// </summary>
public sealed class ModbusDriverFormModelTests
{
    private static readonly JsonSerializerOptions JsonOpts = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
        WriteIndented = false,
        Converters = { new JsonStringEnumConverter() },
    };

    [Fact]
    public void Round_trip_preserves_channel_fields_and_enum()
    {
        var form = new ModbusDriverForm.FormModel
        {
            Family = ModbusFamily.MELSEC,
            MelsecSubFamily = MelsecFamily.Q_L_iQR,
            TimeoutSeconds = 4,
            MaxRegistersPerRead = 100,
            WriteOnChangeOnly = true,
            KeepAliveRetryCount = 5,
            ReconnectBackoffMultiplier = 3.0,
            ProbeAddress = 40,
        };

        var json = JsonSerializer.Serialize(form.ToOptions(), JsonOpts);
        var back = ModbusDriverForm.FormModel.FromOptions(
            JsonSerializer.Deserialize<ModbusDriverOptions>(json, JsonOpts)!);

        back.Family.ShouldBe(ModbusFamily.MELSEC);
        back.MelsecSubFamily.ShouldBe(MelsecFamily.Q_L_iQR);
        back.TimeoutSeconds.ShouldBe(4);
        back.MaxRegistersPerRead.ShouldBe(100);
        back.WriteOnChangeOnly.ShouldBeTrue();
        back.KeepAliveRetryCount.ShouldBe(5);
        back.ReconnectBackoffMultiplier.ShouldBe(3.0);
        back.ProbeAddress.ShouldBe(40);
    }

    [Fact]
    public void Serialized_config_uses_camelCase_keys_and_enum_names()
    {
        var form = new ModbusDriverForm.FormModel { Family = ModbusFamily.MELSEC };

        var json = JsonSerializer.Serialize(form.ToOptions(), JsonOpts);

        json.ShouldContain("\"family\":\"MELSEC\"");           // enum-as-name (not a number), camelCase key
        json.ShouldNotContain("\"family\":0", Case.Sensitive); // never the numeric enum form
    }

    [Fact]
    public void Round_trip_preserves_Transport_mode()
    {
        var form = new ModbusDriverForm.FormModel { Transport = ModbusTransportMode.RtuOverTcp };
        var json = JsonSerializer.Serialize(form.ToOptions(), JsonOpts);
        var back = ModbusDriverForm.FormModel.FromOptions(
            JsonSerializer.Deserialize<ModbusDriverOptions>(json, JsonOpts)!);
        back.Transport.ShouldBe(ModbusTransportMode.RtuOverTcp);
        json.ShouldContain("\"transport\":\"RtuOverTcp\""); // name string, never a number
    }
}
