using Shouldly;
using Xunit;
using ZB.MOM.WW.OtOpcUa.Driver.AbLegacy;

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

[Trait("Category", "Unit")]
public sealed class AbLegacyAddressTests
{
    [Theory]
    [InlineData("N7:0", "N", 7, 0, null, null)]
    [InlineData("N7:15", "N", 7, 15, null, null)]
    [InlineData("F8:5", "F", 8, 5, null, null)]
    [InlineData("B3:0/0", "B", 3, 0, 0, null)]
    [InlineData("B3:2/7", "B", 3, 2, 7, null)]
    [InlineData("ST9:0", "ST", 9, 0, null, null)]
    [InlineData("L9:3", "L", 9, 3, null, null)]
    [InlineData("I:0/0", "I", null, 0, 0, null)]
    [InlineData("O:1/2", "O", null, 1, 2, null)]
    [InlineData("S:1", "S", null, 1, null, null)]
    [InlineData("T4:0.ACC", "T", 4, 0, null, "ACC")]
    [InlineData("T4:0.PRE", "T", 4, 0, null, "PRE")]
    [InlineData("C5:2.CU", "C", 5, 2, null, "CU")]
    [InlineData("R6:0.LEN", "R", 6, 0, null, "LEN")]
    [InlineData("N7:0/3", "N", 7, 0, 3, null)]
    public void TryParse_accepts_valid_pccc_addresses(string input, string letter, int? file, int word, int? bit, string? sub)
    {
        var a = AbLegacyAddress.TryParse(input);
        a.ShouldNotBeNull();
        a.FileLetter.ShouldBe(letter);
        a.FileNumber.ShouldBe(file);
        a.WordNumber.ShouldBe(word);
        a.BitIndex.ShouldBe(bit);
        a.SubElement.ShouldBe(sub);
    }

    [Theory]
    [InlineData(null)]
    [InlineData("")]
    [InlineData("   ")]
    [InlineData("N7")]              // missing :word
    [InlineData(":0")]              // missing file
    [InlineData("X7:0")]            // unknown file letter
    [InlineData("N7:-1")]           // negative word
    [InlineData("N7:abc")]          // non-numeric word
    [InlineData("N7:0/-1")]         // negative bit
    [InlineData("N7:0/32")]         // bit out of range
    [InlineData("Nabc:0")]          // non-numeric file number
    public void TryParse_rejects_invalid_forms(string? input)
    {
        AbLegacyAddress.TryParse(input).ShouldBeNull();
    }

    [Theory]
    [InlineData("N7:0")]
    [InlineData("F8:5")]
    [InlineData("B3:0/0")]
    [InlineData("ST9:0")]
    [InlineData("T4:0.ACC")]
    [InlineData("I:0/0")]
    [InlineData("S:1")]
    public void ToLibplctagName_roundtrips(string input)
    {
        var a = AbLegacyAddress.TryParse(input);
        a.ShouldNotBeNull();
        a.ToLibplctagName().ShouldBe(input);
    }
}
