using AyCode.Core.Serializers.Binaries;

namespace AyCode.Core.Tests.Serialization;

/// <summary>
/// Basic serialization tests for primitive types.
/// </summary>
[TestClass]
public class AcBinarySerializerBasicTests
{
    [TestMethod]
    public void Serialize_Null_ReturnsSingleNullByte()
    {
        var result = AcBinarySerializer.Serialize<object?>(null);
        Assert.AreEqual(1, result.Length);
        Assert.AreEqual(BinaryTypeCode.Null, result[0]);
    }

    [TestMethod]
    public void Serialize_Int32_RoundTrip()
    {
        var value = 12345;
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<int>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_Int64_RoundTrip()
    {
        var value = 123456789012345L;
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<long>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_Double_RoundTrip()
    {
        var value = 3.14159265358979;
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<double>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_String_RoundTrip()
    {
        var value = "Hello, Binary World!";
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<string>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_Boolean_RoundTrip()
    {
        var trueResult = AcBinaryDeserializer.Deserialize<bool>(AcBinarySerializer.Serialize(true));
        var falseResult = AcBinaryDeserializer.Deserialize<bool>(AcBinarySerializer.Serialize(false));
        Assert.IsTrue(trueResult);
        Assert.IsFalse(falseResult);
    }

    [TestMethod]
    public void Serialize_DateTime_RoundTrip()
    {
        var value = new DateTime(2024, 12, 25, 10, 30, 45, DateTimeKind.Utc);
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<DateTime>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    [DataRow(DateTimeKind.Unspecified)]
    [DataRow(DateTimeKind.Utc)]
    [DataRow(DateTimeKind.Local)]
    public void Serialize_DateTime_PreservesKind(DateTimeKind kind)
    {
        var value = new DateTime(2024, 12, 25, 10, 30, 45, kind);
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<DateTime>(binary);

        Assert.AreEqual(value.Ticks, result.Ticks);
        Assert.AreEqual(value.Kind, result.Kind);
    }

    [TestMethod]
    public void Serialize_Guid_RoundTrip()
    {
        var value = Guid.NewGuid();
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<Guid>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_Decimal_RoundTrip()
    {
        var value = 123456.789012m;
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<decimal>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_TimeSpan_RoundTrip()
    {
        var value = TimeSpan.FromHours(2.5);
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<TimeSpan>(binary);
        Assert.AreEqual(value, result);
    }

    [TestMethod]
    public void Serialize_DateTimeOffset_RoundTrip()
    {
        var value = new DateTimeOffset(2024, 12, 25, 10, 30, 45, TimeSpan.FromHours(2));
        var binary = AcBinarySerializer.Serialize(value);
        var result = AcBinaryDeserializer.Deserialize<DateTimeOffset>(binary);

        Assert.AreEqual(value.UtcTicks, result.UtcTicks);
        Assert.AreEqual(value.Offset, result.Offset);
    }
}
