using System.Text.Json;
using ColaFlow.Modules.Mcp.Application.Handlers;
using ColaFlow.Modules.Mcp.Contracts.Mcp;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using NSubstitute;

namespace ColaFlow.Modules.Mcp.Tests.Handlers;

/// <summary>
/// Unit tests for InitializeMethodHandler
/// </summary>
public class InitializeMethodHandlerTests
{
    private readonly ILogger<InitializeMethodHandler> _logger;
    private readonly InitializeMethodHandler _sut;

    public InitializeMethodHandlerTests()
    {
        _logger = Substitute.For<ILogger<InitializeMethodHandler>>();
        _sut = new InitializeMethodHandler(_logger);
    }

    [Fact]
    public void MethodName_ReturnsInitialize()
    {
        // Assert
        _sut.MethodName.Should().Be("initialize");
    }

    [Fact]
    public async Task HandleAsync_WithValidRequest_ReturnsInitializeResponse()
    {
        // Arrange
        var initRequest = new McpInitializeRequest
        {
            ProtocolVersion = "1.0",
            ClientInfo = new McpClientInfo
            {
                Name = "Claude Desktop",
                Version = "1.0.0"
            }
        };

        // Act
        var result = await _sut.HandleAsync(initRequest, CancellationToken.None);

        // Assert
        result.Should().NotBeNull();
        result.Should().BeOfType<McpInitializeResponse>();

        var response = (McpInitializeResponse)result!;
        response.ProtocolVersion.Should().Be("1.0");
        response.ServerInfo.Should().NotBeNull();
        response.ServerInfo.Name.Should().Be("ColaFlow MCP Server");
        response.ServerInfo.Version.Should().Be("1.0.0");
        response.Capabilities.Should().NotBeNull();
    }

    [Fact]
    public async Task HandleAsync_ReturnsCapabilitiesWithAllFeaturesSupported()
    {
        // Arrange
        var initRequest = new McpInitializeRequest
        {
            ProtocolVersion = "1.0",
            ClientInfo = new McpClientInfo { Name = "Test", Version = "1.0" }
        };

        // Act
        var result = await _sut.HandleAsync(initRequest, CancellationToken.None);

        // Assert
        var response = (McpInitializeResponse)result!;
        response.Capabilities.Resources.Should().NotBeNull();
        response.Capabilities.Resources!.Supported.Should().BeTrue();
        response.Capabilities.Tools.Should().NotBeNull();
        response.Capabilities.Tools!.Supported.Should().BeTrue();
        response.Capabilities.Prompts.Should().NotBeNull();
        response.Capabilities.Prompts!.Supported.Should().BeTrue();
    }

    [Fact]
    public async Task HandleAsync_WithNullParams_ReturnsValidResponse()
    {
        // Act
        var result = await _sut.HandleAsync(null, CancellationToken.None);

        // Assert
        result.Should().NotBeNull();
        result.Should().BeOfType<McpInitializeResponse>();
    }

    [Fact]
    public async Task HandleAsync_WithObjectParams_DeserializesCorrectly()
    {
        // Arrange - Simulate how JSON deserialization works with object params
        var paramsObj = new
        {
            protocolVersion = "1.0",
            clientInfo = new
            {
                name = "Claude Desktop",
                version = "1.0.0"
            }
        };

        // Act
        var result = await _sut.HandleAsync(paramsObj, CancellationToken.None);

        // Assert
        result.Should().NotBeNull();
        var response = (McpInitializeResponse)result!;
        response.ProtocolVersion.Should().Be("1.0");
    }

    [Fact]
    public async Task HandleAsync_WithUnsupportedProtocolVersion_StillReturnsResponse()
    {
        // Arrange
        var initRequest = new McpInitializeRequest
        {
            ProtocolVersion = "2.0", // Unsupported version
            ClientInfo = new McpClientInfo { Name = "Test", Version = "1.0" }
        };

        // Act
        var result = await _sut.HandleAsync(initRequest, CancellationToken.None);

        // Assert
        result.Should().NotBeNull();
        var response = (McpInitializeResponse)result!;
        response.ProtocolVersion.Should().Be("1.0"); // Server returns its supported version
    }
}
