using System.Text.Json;
using ColaFlow.Modules.Mcp.Contracts.JsonRpc;
using FluentAssertions;

namespace ColaFlow.Modules.Mcp.Tests.Contracts;

/// <summary>
/// Unit tests for JsonRpcRequest
/// </summary>
public class JsonRpcRequestTests
{
    [Fact]
    public void IsValid_WithValidRequest_ReturnsTrue()
    {
        // Arrange
        var request = new JsonRpcRequest
        {
            JsonRpc = "2.0",
            Method = "test_method",
            Id = 1
        };

        // Act
        var isValid = request.IsValid(out var errorMessage);

        // Assert
        isValid.Should().BeTrue();
        errorMessage.Should().BeNull();
    }

    [Fact]
    public void IsValid_WithInvalidJsonRpcVersion_ReturnsFalse()
    {
        // Arrange
        var request = new JsonRpcRequest
        {
            JsonRpc = "1.0",
            Method = "test_method"
        };

        // Act
        var isValid = request.IsValid(out var errorMessage);

        // Assert
        isValid.Should().BeFalse();
        errorMessage.Should().Contain("jsonrpc must be exactly '2.0'");
    }

    [Fact]
    public void IsValid_WithEmptyMethod_ReturnsFalse()
    {
        // Arrange
        var request = new JsonRpcRequest
        {
            JsonRpc = "2.0",
            Method = ""
        };

        // Act
        var isValid = request.IsValid(out var errorMessage);

        // Assert
        isValid.Should().BeFalse();
        errorMessage.Should().Contain("method is required");
    }

    [Fact]
    public void IsNotification_WithNoId_ReturnsTrue()
    {
        // Arrange
        var request = new JsonRpcRequest
        {
            JsonRpc = "2.0",
            Method = "notification_method",
            Id = null
        };

        // Act & Assert
        request.IsNotification.Should().BeTrue();
    }

    [Fact]
    public void IsNotification_WithId_ReturnsFalse()
    {
        // Arrange
        var request = new JsonRpcRequest
        {
            JsonRpc = "2.0",
            Method = "regular_method",
            Id = 1
        };

        // Act & Assert
        request.IsNotification.Should().BeFalse();
    }

    [Fact]
    public void Deserialize_WithValidJson_CreatesRequest()
    {
        // Arrange
        var json = @"{
            ""jsonrpc"": ""2.0"",
            ""method"": ""test_method"",
            ""params"": { ""key"": ""value"" },
            ""id"": 1
        }";

        // Act
        var request = JsonSerializer.Deserialize<JsonRpcRequest>(json);

        // Assert
        request.Should().NotBeNull();
        request!.JsonRpc.Should().Be("2.0");
        request.Method.Should().Be("test_method");
        request.Params.Should().NotBeNull();
        // Id can be number or string, System.Text.Json deserializes number to JsonElement
        // Just check it's not null
        request.Id.Should().NotBeNull();
    }

    [Fact]
    public void Deserialize_WithoutParams_CreatesRequestWithNullParams()
    {
        // Arrange
        var json = @"{
            ""jsonrpc"": ""2.0"",
            ""method"": ""test_method"",
            ""id"": 1
        }";

        // Act
        var request = JsonSerializer.Deserialize<JsonRpcRequest>(json);

        // Assert
        request.Should().NotBeNull();
        request!.Params.Should().BeNull();
    }

    [Fact]
    public void Serialize_IncludesAllFields()
    {
        // Arrange
        var request = new JsonRpcRequest
        {
            JsonRpc = "2.0",
            Method = "test_method",
            Params = new { key = "value" },
            Id = 1
        };

        // Act
        var json = JsonSerializer.Serialize(request);

        // Assert
        json.Should().Contain("\"jsonrpc\":\"2.0\"");
        json.Should().Contain("\"method\":\"test_method\"");
        json.Should().Contain("\"params\":");
        json.Should().Contain("\"id\":1");
    }
}
