using Microsoft.Extensions.DependencyInjection;
using ModelContextProtocol.Server;
using Nexus.Api.Services;
using Xunit;

namespace Nexus.Api.Tests;

/// <summary>
/// Verifies that the MCP server configuration is correct:
/// all tools are registered, the streamable-http transport is configured
/// via the service extensions, and MapMcp is called in Program.cs.
/// </summary>
public sealed class McpServerConfigurationTests
{
    [Fact]
    public void McpServer_CanBeRegistered_WithoutError()
    {
        var services = new ServiceCollection();
        services.AddLogging();
        services.AddOptions();
        services.AddHttpContextAccessor();

        // Simulate what AddNexusApplicationServices does
        services.AddMcpServer()
            .WithHttpTransport(options => options.Stateless = true)
            .WithTools<NexusMcpTools>();

        // Build the container — this should not throw
        var provider = services.BuildServiceProvider();

        // Verify the ToolType is properly decorated
        var attr = typeof(NexusMcpTools).GetCustomAttributes(
            typeof(McpServerToolTypeAttribute), inherit: false);
        Assert.Single(attr);
    }

    [Fact]
    public void McpServer_ToolTypeAttribute_IsPresent()
    {
        var attr = typeof(NexusMcpTools).GetCustomAttributes(
            typeof(McpServerToolTypeAttribute), inherit: false);
        Assert.Single(attr);
    }

    [Fact]
    public void McpEndpoint_MapMcp_IsCalledInProgram()
    {
        // Source path relative to the test output directory
        var programPath = ResolveSourcePath("backend", "Program.cs");
        Assert.True(File.Exists(programPath), $"Program.cs not found at {programPath}");
        var source = File.ReadAllText(programPath);
        Assert.Contains("MapMcp", source, StringComparison.Ordinal);
    }

    [Fact]
    public void McpServerRegistration_IsCalledInServiceExtensions()
    {
        var extPath = ResolveSourcePath("backend", "Extensions", "ServiceCollectionExtensions.cs");
        Assert.True(File.Exists(extPath), $"ServiceCollectionExtensions.cs not found at {extPath}");
        var source = File.ReadAllText(extPath);
        Assert.Contains("AddMcpServer", source, StringComparison.Ordinal);
        Assert.Contains("WithHttpTransport", source, StringComparison.Ordinal);
        Assert.Contains("Stateless", source, StringComparison.Ordinal);
        Assert.Contains("WithTools<NexusMcpTools>", source, StringComparison.Ordinal);
    }

    [Fact]
    public void NuGetPackage_ModelContextProtocol_AspNetCore_IsReferenced()
    {
        var csprojPath = ResolveSourcePath("backend", "Nexus.Api.csproj");
        Assert.True(File.Exists(csprojPath), $"Nexus.Api.csproj not found at {csprojPath}");
        var source = File.ReadAllText(csprojPath);
        Assert.Contains("ModelContextProtocol.AspNetCore", source, StringComparison.Ordinal);
    }

    private static string ResolveSourcePath(params string[] segments)
    {
        // Navigate from test output directory to the repo root
        // Test DLL is at: backend-tests/bin/Debug/net10.0/Nexus.Api.Tests.dll
        // We go up 4 levels (net10.0 → Debug → bin → backend-tests) to reach repo root
        var baseDir = AppContext.BaseDirectory;
        var repoRoot = Path.GetFullPath(Path.Combine(baseDir, "..", "..", "..", ".."));
        return Path.Combine(new[] { repoRoot }.Concat(segments).ToArray());
    }
}
