using System.Collections;
using Common;

namespace CommonTest;

/// <summary>
/// 针对 Common.Number 的单元测试，覆盖所有公开方法
/// </summary>
public class NumberTest
{
    /// <summary>
    /// 测试 NumberToBytes 的正常与异常情况
    /// </summary>
    [Fact]
    public void Test_NumberToBytes()
    {
        // 测试大端（isLowNumHigh=false）
        var result1 = Number.NumberToBytes(0x12345678ABCDEF01, 8, false);
        Assert.True(result1.IsSuccessful);
        Assert.Equal(new byte[] { 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0x01 }, result1.Value);

        // 测试小端（isLowNumHigh=true）
        var result2 = Number.NumberToBytes(0x12345678ABCDEF01, 8, true);
        Assert.True(result2.IsSuccessful);
        Assert.Equal(new byte[] { 0x01, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12 }, result2.Value);

        // 测试长度不足（4字节）
        var result3 = Number.NumberToBytes(0x12345678, 4, false);
        Assert.True(result3.IsSuccessful);
        Assert.Equal(new byte[] { 0x12, 0x34, 0x56, 0x78 }, result3.Value);

        // 测试超长
        var result4 = Number.NumberToBytes(0x1, 9, false);
        Assert.False(result4.IsSuccessful);
    }

    /// <summary>
    /// 测试 BytesToUInt64 的正常与异常情况，覆盖不同参数组合
    /// </summary>
    [Fact]
    public void Test_BytesToUInt64()
    {
        // 正常大端（isLowNumHigh=false）
        var bytes = new byte[] { 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0x01 };
        var result = Number.BytesToUInt64((byte[])bytes.Clone());
        Assert.True(result.IsSuccessful);
        Assert.Equal(0x12345678ABCDEF01UL, result.Value);

        // 正常小端（isLowNumHigh=true）
        var bytes2 = new byte[] { 0x01, 0xEF, 0xCD, 0xAB, 0x78, 0x56, 0x34, 0x12 };
        var result2 = Number.BytesToUInt64((byte[])bytes2.Clone(), true);
        Assert.True(result2.IsSuccessful);
        Assert.Equal(0x12345678ABCDEF01UL, result2.Value);

        // 长度不足8字节（numLength=4），大端
        var bytes3 = new byte[] { 0x12, 0x34, 0x56, 0x78 };
        var result3 = Number.BytesToUInt64((byte[])bytes3.Clone(), 0, 4, false);
        Assert.True(result3.IsSuccessful);
        Assert.Equal(0x1234567800000000UL, result3.Value);

        // 长度不足8字节（numLength=4），小端
        var bytes4 = new byte[] { 0x78, 0x56, 0x34, 0x12 };
        var result4 = Number.BytesToUInt64((byte[])bytes4.Clone(), 0, 4, true);
        Assert.True(result4.IsSuccessful);
        Assert.Equal(0x12345678UL, result4.Value);

        // numLength=0
        var bytes5 = new byte[] { 0x12, 0x34, 0x56, 0x78 };
        var result5 = Number.BytesToUInt64((byte[])bytes5.Clone(), 0, 0, false);
        Assert.True(result5.IsSuccessful);
        Assert.Equal(0UL, result5.Value);

        // offset测试
        var bytes6 = new byte[] { 0x00, 0x00, 0x12, 0x34, 0x56, 0x78, 0xAB, 0xCD, 0xEF, 0x01 };
        var result6 = Number.BytesToUInt64(bytes6, 2, 8, false);
        Assert.True(result6.IsSuccessful);
        Assert.Equal(0x12345678ABCDEF01UL, result6.Value);

        // numLength超限（>8），应返回异常
        var bytes7 = new byte[9];
        var result7 = Number.BytesToUInt64(bytes7, 0, 9, false);
        Assert.False(result7.IsSuccessful);

        // offset+numLength超限
        var bytes8 = new byte[] { 0x01, 0x02, 0x03, 0x04 };
        var result8 = Number.BytesToUInt64(bytes8, 2, 4, false);
        Assert.True(result8.IsSuccessful);
        Assert.Equal(0x0304000000000000UL, result8.Value);

        // bytes长度不足offset+numLength
        var bytes9 = new byte[] { 0x01, 0x02 };
        var result9 = Number.BytesToUInt64(bytes9, 1, 2, true);
        Assert.True(result9.IsSuccessful);
        Assert.Equal(0x02UL, result9.Value);

        // 空数组
        var result10 = Number.BytesToUInt64(new byte[0], 0, 0, false);
        Assert.True(result10.IsSuccessful);
        Assert.Equal(0UL, result10.Value);
    }

    /// <summary>
    /// 测试 BytesToUInt32 的正常与异常情况，覆盖不同参数组合
    /// </summary>
    [Fact]
    public void Test_BytesToUInt32()
    {
        // 正常大端（isLowNumHigh=false）
        var bytes = new byte[] { 0x12, 0x34, 0x56, 0x78 };
        var result = Number.BytesToUInt32((byte[])bytes.Clone());
        Assert.True(result.IsSuccessful);
        Assert.Equal(0x12345678U, result.Value);

        // 正常小端（isLowNumHigh=true）
        var bytes2 = new byte[] { 0x78, 0x56, 0x34, 0x12 };
        var result2 = Number.BytesToUInt32((byte[])bytes2.Clone(), true);
        Assert.True(result2.IsSuccessful);
        Assert.Equal(0x12345678U, result2.Value);

        // 长度不足4字节（numLength=2），大端
        var bytes3 = new byte[] { 0x12, 0x34 };
        var result3 = Number.BytesToUInt32((byte[])bytes3.Clone(), 0, 2, false);
        Assert.True(result3.IsSuccessful);
        Assert.Equal(0x12340000U, result3.Value);

        // 长度不足4字节（numLength=2），小端
        var bytes4 = new byte[] { 0x34, 0x12 };
        var result4 = Number.BytesToUInt32((byte[])bytes4.Clone(), 0, 2, true);
        Assert.True(result4.IsSuccessful);
        Assert.Equal(0x1234U, result4.Value);

        // numLength=0
        var bytes5 = new byte[] { 0x12, 0x34, 0x56, 0x78 };
        var result5 = Number.BytesToUInt32((byte[])bytes5.Clone(), 0, 0, false);
        Assert.True(result5.IsSuccessful);
        Assert.Equal(0U, result5.Value);

        // offset测试
        var bytes6 = new byte[] { 0x00, 0x00, 0x12, 0x34, 0x56, 0x78 };
        var result6 = Number.BytesToUInt32(bytes6, 2, 4, false);
        Assert.True(result6.IsSuccessful);
        Assert.Equal(0x12345678U, result6.Value);

        // numLength超限（>4），应返回异常
        var bytes7 = new byte[5];
        var result7 = Number.BytesToUInt32(bytes7, 0, 5, false);
        Assert.False(result7.IsSuccessful);

        // offset+numLength超限
        var bytes8 = new byte[] { 0x01, 0x02, 0x03, 0x04 };
        var result8 = Number.BytesToUInt32(bytes8, 2, 2, false);
        Assert.True(result8.IsSuccessful);
        Assert.Equal(0x03040000U, result8.Value);

        // bytes长度不足offset+numLength
        var bytes9 = new byte[] { 0x01, 0x02 };
        var result9 = Number.BytesToUInt32(bytes9, 1, 1, true);
        Assert.True(result9.IsSuccessful);
        Assert.Equal(0x02U, result9.Value);

        // 空数组
        var result10 = Number.BytesToUInt32(new byte[0], 0, 0, false);
        Assert.True(result10.IsSuccessful);
        Assert.Equal(0U, result10.Value);
    }

    /// <summary>
    /// 测试 UInt32ArrayToBytes 的正常与异常情况
    /// </summary>
    [Fact]
    public void Test_UInt32ArrayToBytes()
    {
        // 正常情况
        var arr = new UInt32[] { 0x12345678, 0xABCDEF01 };
        var result = Number.UInt32ArrayToBytes(arr);
        Assert.True(result.IsSuccessful);
        // BlockCopy 按小端序
        Assert.Equal(new byte[] { 0x78, 0x56, 0x34, 0x12, 0x01, 0xEF, 0xCD, 0xAB }, result.Value);

        // 空数组
        var result2 = Number.UInt32ArrayToBytes(new UInt32[0]);
        Assert.True(result2.IsSuccessful);
        Assert.Empty(result2.Value);
    }

    /// <summary>
    /// 测试 MultiBitsToBytes 和 MultiBitsToNumber (ulong)
    /// </summary>
    [Fact]
    public void Test_MultiBitsToBytesAndNumber_Ulong()
    {
        // 合并两个比特段
        var result = Number.MultiBitsToNumber(0b101UL, 3, 0b11UL, 2);
        Assert.True(result.IsSuccessful);
        Assert.Equal((ulong)0b10111, result.Value);

        // 合并为字节数组
        var bytesResult = Number.MultiBitsToBytes(0b101UL, 3, 0b11UL, 2);
        Assert.True(bytesResult.IsSuccessful);
        Assert.Equal(new byte[] { 0b10111 }, bytesResult.Value);

        // 超过64位
        var failResult = Number.MultiBitsToNumber(0xFFFFFFFFFFFFFFFF, 64, 1, 1);
        Assert.False(failResult.IsSuccessful);
    }

    /// <summary>
    /// 测试 MultiBitsToNumber (uint)
    /// </summary>
    [Fact]
    public void Test_MultiBitsToNumber_Uint()
    {
        var result = Number.MultiBitsToNumber(0b101U, 3, 0b11U, 2);
        Assert.True(result.IsSuccessful);
        Assert.Equal((uint)0b10111, result.Value);

        // 超过64位
        var failResult = Number.MultiBitsToNumber(uint.MaxValue, 64, 1, 1);
        Assert.False(failResult.IsSuccessful);
    }

    /// <summary>
    /// 测试 BitsCheck (ulong)
    /// </summary>
    [Fact]
    public void Test_BitsCheck_Ulong()
    {
        // 完全匹配
        Assert.True(Number.BitsCheck(0b1101UL, 0b1101UL));
        // 不匹配
        Assert.False(Number.BitsCheck(0b1101UL, 0b1001UL));
        // 掩码
        Assert.True(Number.BitsCheck(0b1101UL, 0b1001UL, 0b1001UL));
    }

    /// <summary>
    /// 测试 BitsCheck (uint)
    /// </summary>
    [Fact]
    public void Test_BitsCheck_Uint()
    {
        Assert.True(Number.BitsCheck(0b1011U, 0b1011U));
        Assert.False(Number.BitsCheck(0b1011U, 0b1001U));
        Assert.True(Number.BitsCheck(0b1011U, 0b1001U, 0b1001U));
    }

    /// <summary>
    /// 测试 ToBit
    /// </summary>
    [Fact]
    public void Test_ToBit()
    {
        // 取第0位
        var result = Number.ToBit(0b1010U, 0);
        Assert.True(result.IsSuccessful);
        Assert.False(result.Value);

        // 取第1位
        var result2 = Number.ToBit(0b1010U, 1);
        Assert.True(result2.IsSuccessful);
        Assert.True(result2.Value);

        // 负数位置
        var result3 = Number.ToBit(0b1010U, -1);
        Assert.False(result3.IsSuccessful);
    }

    /// <summary>
    /// 测试 BitsToNumber
    /// </summary>
    [Fact]
    public void Test_BitsToNumber()
    {
        // 5位BitArray
        var bits = new BitArray(new bool[] { true, true, false, true, false }); // 0b01011
        var result = Number.BitsToNumber(bits);
        Assert.True(result.IsSuccessful);
        Assert.Equal((uint)0b01011, result.Value);

        // 超过32位
        var bits2 = new BitArray(33);
        Assert.Throws<ArgumentException>(() => Number.BitsToNumber(bits2));
    }

    /// <summary>
    /// 测试 StringToBytes
    /// </summary>
    [Fact]
    public void Test_StringToBytes()
    {
        // 16进制字符串
        var bytes = Number.StringToBytes("1234ABCD");
        Assert.Equal(new byte[] { 0x12, 0x34, 0xAB, 0xCD }, bytes);

        // 8位字符串
        var bytes2 = Number.StringToBytes("01020304");
        Assert.Equal(new byte[] { 0x01, 0x02, 0x03, 0x04 }, bytes2);
    }

    /// <summary>
    /// 测试 ReverseBytes
    /// </summary>
    [Fact]
    public void Test_ReverseBytes()
    {
        // 步长为2
        var src = new byte[] { 0x01, 0x02, 0x03, 0x04 };
        var result = Number.ReverseBytes(src, 2);
        Assert.True(result.IsSuccessful);
        Assert.Equal(new byte[] { 0x02, 0x01, 0x04, 0x03 }, result.Value);

        // 步长为4
        var src2 = new byte[] { 0x01, 0x02, 0x03, 0x04 };
        var result2 = Number.ReverseBytes(src2, 4);
        Assert.True(result2.IsSuccessful);
        Assert.Equal(new byte[] { 0x04, 0x03, 0x02, 0x01 }, result2.Value);

        // 步长为1（无变化）
        var src3 = new byte[] { 0x01, 0x02, 0x03, 0x04 };
        var result3 = Number.ReverseBytes(src3, 1);
        Assert.True(result3.IsSuccessful);
        Assert.Equal(src3, result3.Value);

        // 步长为0（异常）
        var result4 = Number.ReverseBytes(src3, 0);
        Assert.False(result4.IsSuccessful);

        // 步长不能整除
        var result5 = Number.ReverseBytes(src3, 3);
        Assert.False(result5.IsSuccessful);
    }

    /// <summary>
    /// 测试 ReverseBits (byte)
    /// </summary>
    [Fact]
    public void Test_ReverseBits_Byte()
    {
        // 0b00010010 -> 0b01001000
        byte src = 0b00010010;
        byte reversed = Number.ReverseBits(src);
        Assert.Equal(0b01001000, reversed);

        // 0b11110000 -> 0b00001111
        Assert.Equal(0b00001111, Number.ReverseBits(0b11110000));
    }

    /// <summary>
    /// 测试 ReverseBits (byte[])
    /// </summary>
    [Fact]
    public void Test_ReverseBits_ByteArray()
    {
        var src = new byte[] { 0b00010010, 0b11110000 };
        var reversed = Number.ReverseBits(src);
        Assert.Equal(new byte[] { 0b01001000, 0b00001111 }, reversed);

        // 空数组
        var reversed2 = Number.ReverseBits(new byte[0]);
        Assert.Empty(reversed2);
    }

    /// <summary>
    /// 测试 GetLength
    /// </summary>
    [Fact]
    public void Test_GetLength()
    {
        Assert.Equal(5, Number.GetLength(12345));
        Assert.Equal(4, Number.GetLength(-123));
        Assert.Equal(1, Number.GetLength(0));
    }

    /// <summary>
    /// 测试 IntPow
    /// </summary>
    [Fact]
    public void Test_IntPow()
    {
        Assert.Equal(8, Number.IntPow(2, 3));
        Assert.Equal(1, Number.IntPow(5, 0));
        Assert.Equal(0, Number.IntPow(0, 5));
        Assert.Equal(7, Number.IntPow(7, 1));
        Assert.Equal(81, Number.IntPow(3, 4));
    }
}
