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.AbLegacy;
using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy.PlcFamilies;

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

public sealed class AbLegacyDriverPageFormSerializationTests
{
    private static readonly JsonSerializerOptions _opts = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        WriteIndented = false,
    };

    private static readonly JsonSerializerOptions TestJsonOpts = new()
    {
        PropertyNamingPolicy = JsonNamingPolicy.CamelCase,
        UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
    };

    [Fact]
    public void RoundTrip_PreservesKnownFields()
    {
        var original = new AbLegacyDriverOptions
        {
            Timeout = TimeSpan.FromSeconds(4),
            Probe = new AbLegacyProbeOptions
            {
                Enabled = true,
                Interval = TimeSpan.FromSeconds(8),
                Timeout = TimeSpan.FromSeconds(3),
                ProbeAddress = "N7:0",
            },
            ProbeTimeoutSeconds = 10,
            Devices =
            [
                new AbLegacyDeviceOptions("10.0.0.10", AbLegacyPlcFamily.Slc500, "PLC-A"),
                new AbLegacyDeviceOptions("10.0.0.11", AbLegacyPlcFamily.MicroLogix),
            ],
        };

        var json = JsonSerializer.Serialize(original, _opts);
        var back = JsonSerializer.Deserialize<AbLegacyDriverOptions>(json, _opts);

        back.ShouldNotBeNull();
        back.Timeout.ShouldBe(TimeSpan.FromSeconds(4));
        back.Probe.Enabled.ShouldBeTrue();
        back.Probe.Interval.ShouldBe(TimeSpan.FromSeconds(8));
        back.Probe.Timeout.ShouldBe(TimeSpan.FromSeconds(3));
        back.Probe.ProbeAddress.ShouldBe("N7:0");
        back.ProbeTimeoutSeconds.ShouldBe(10);
        back.Devices.Count.ShouldBe(2);
        back.Devices[0].HostAddress.ShouldBe("10.0.0.10");
        back.Devices[0].PlcFamily.ShouldBe(AbLegacyPlcFamily.Slc500);
        back.Devices[0].DeviceName.ShouldBe("PLC-A");
        back.Devices[1].PlcFamily.ShouldBe(AbLegacyPlcFamily.MicroLogix);
    }

    [Fact]
    public void Deserialize_DropsUnknownFields()
    {
        var jsonWithExtra = """{"unknownField":"old-value","probeTimeoutSeconds":10}""";

        var optsWithSkip = new JsonSerializerOptions(_opts)
        {
            UnmappedMemberHandling = JsonUnmappedMemberHandling.Skip,
        };

        var back = JsonSerializer.Deserialize<AbLegacyDriverOptions>(jsonWithExtra, optsWithSkip);
        back.ShouldNotBeNull();
        back.ProbeTimeoutSeconds.ShouldBe(10);
    }

    // v3 Batch-2 (WP3): the embedded-Devices CollectionEditor + AbLegacyDeviceRow retired — devices are now
    // separate Device entities authored via the raw-tree DeviceModal (AbLegacyDeviceModel, HostAddress/PlcFamily
    // into DeviceConfig). The former DeviceRow_* / ValidateDeviceRow_* tests were removed. The channel-config
    // FormModel now lives in AbLegacyDriverForm; the multi-device Devices array it preserves is covered below.

    [Fact]
    public void Device_list_survives_form_serialize_round_trip()
    {
        var devices = new List<AbLegacyDeviceOptions>
        {
            new("10.0.0.10", AbLegacyPlcFamily.Slc500, "PLC-1"),
            new("10.0.0.11", AbLegacyPlcFamily.MicroLogix, "PLC-2"),
        };
        var opts = new AbLegacyDriverForm.FormModel().ToOptions(devices);
        var json = JsonSerializer.Serialize(opts, TestJsonOpts);
        var back = JsonSerializer.Deserialize<AbLegacyDriverOptions>(json, TestJsonOpts)!;
        back.Devices.Count.ShouldBe(2);
        back.Devices[0].HostAddress.ShouldBe("10.0.0.10");
        back.Devices[0].PlcFamily.ShouldBe(AbLegacyPlcFamily.Slc500);
        back.Devices[1].PlcFamily.ShouldBe(AbLegacyPlcFamily.MicroLogix);
    }
}
