using System.Text.Json;
using PolyTrader.Modules.Supervisor.Agent;
using PolyTrader.Modules.Supervisor.Mcp;
using Xunit;

namespace PolyTrader.Tests
{
    /// <summary>
    /// Sicherheitsnetz für MCP-Light (S-4): JSON-RPC-Handling (initialize, tools/list, tools/call,
    /// Notifications, Fehlerfälle) über die read-only Tool-Registry — pur, ohne HTTP.
    /// </summary>
    public class McpJsonRpcTests
    {
        private static SupervisorToolRegistry Registry()
        {
            var reg = new SupervisorToolRegistry();
            reg.Register(new SupervisorTool("echo", "Echo-Tool",
                """{"type":"object","properties":{"text":{"type":"string"}}}""",
                args => "ECHO:" + (SupervisorToolRegistry.GetString(args, "text") ?? "")));
            return reg;
        }

        [Fact]
        public void Initialize_returns_protocol_and_serverinfo()
        {
            string? resp = McpJsonRpc.Handle(
                """{"jsonrpc":"2.0","id":1,"method":"initialize","params":{"protocolVersion":"2025-03-26"}}""",
                Registry());

            Assert.NotNull(resp);
            using var doc = JsonDocument.Parse(resp!);
            var result = doc.RootElement.GetProperty("result");
            Assert.Equal(McpJsonRpc.ProtocolVersion, result.GetProperty("protocolVersion").GetString());
            Assert.Equal(McpJsonRpc.ServerName, result.GetProperty("serverInfo").GetProperty("name").GetString());
            Assert.True(result.GetProperty("capabilities").TryGetProperty("tools", out _));
        }

        [Fact]
        public void ToolsList_exposes_registry_tools_with_schema()
        {
            string? resp = McpJsonRpc.Handle("""{"jsonrpc":"2.0","id":2,"method":"tools/list"}""", Registry());
            using var doc = JsonDocument.Parse(resp!);
            var tools = doc.RootElement.GetProperty("result").GetProperty("tools");
            Assert.Equal(1, tools.GetArrayLength());
            Assert.Equal("echo", tools[0].GetProperty("name").GetString());
            Assert.Equal("object", tools[0].GetProperty("inputSchema").GetProperty("type").GetString());
        }

        [Fact]
        public void ToolsCall_executes_and_wraps_result_as_text_content()
        {
            string? resp = McpJsonRpc.Handle(
                """{"jsonrpc":"2.0","id":3,"method":"tools/call","params":{"name":"echo","arguments":{"text":"hallo"}}}""",
                Registry());
            using var doc = JsonDocument.Parse(resp!);
            var result = doc.RootElement.GetProperty("result");
            Assert.Equal("ECHO:hallo", result.GetProperty("content")[0].GetProperty("text").GetString());
            Assert.False(result.GetProperty("isError").GetBoolean());
        }

        [Fact]
        public void ToolsCall_unknown_tool_sets_isError()
        {
            string? resp = McpJsonRpc.Handle(
                """{"jsonrpc":"2.0","id":4,"method":"tools/call","params":{"name":"nix","arguments":{}}}""",
                Registry());
            using var doc = JsonDocument.Parse(resp!);
            Assert.True(doc.RootElement.GetProperty("result").GetProperty("isError").GetBoolean());
        }

        [Fact]
        public void Notification_returns_null_and_unknown_method_returns_error()
        {
            Assert.Null(McpJsonRpc.Handle("""{"jsonrpc":"2.0","method":"notifications/initialized"}""", Registry()));

            string? resp = McpJsonRpc.Handle("""{"jsonrpc":"2.0","id":5,"method":"gibtsnicht"}""", Registry());
            using var doc = JsonDocument.Parse(resp!);
            Assert.Equal(-32601, doc.RootElement.GetProperty("error").GetProperty("code").GetInt32());
        }

        [Fact]
        public void Parse_error_returns_minus32700()
        {
            string? resp = McpJsonRpc.Handle("{kaputt", Registry());
            using var doc = JsonDocument.Parse(resp!);
            Assert.Equal(-32700, doc.RootElement.GetProperty("error").GetProperty("code").GetInt32());
        }
    }
}
