using System.Xml.Linq;

namespace GmRelay.Bot.Tests.Features.Sessions.CreateSession;

public sealed class SharedDapperAotConfigurationTests
{
    [Fact]
    public void SharedProject_ShouldEnableDapperAotForSessionInteractionHandlers()
    {
        var repoRoot = FindRepositoryRoot();
        var sharedProjectPath = Path.Combine(repoRoot, "src", "GmRelay.Shared", "GmRelay.Shared.csproj");
        var joinHandler = File.ReadAllText(Path.Combine(
            repoRoot,
            "src",
            "GmRelay.Shared",
            "Features",
            "Sessions",
            "CreateSession",
            "JoinSessionHandler.cs"));
        var leaveHandler = File.ReadAllText(Path.Combine(
            repoRoot,
            "src",
            "GmRelay.Shared",
            "Features",
            "Sessions",
            "CreateSession",
            "LeaveSessionHandler.cs"));

        Assert.Contains("using Dapper;", joinHandler, StringComparison.Ordinal);
        Assert.Contains("using Dapper;", leaveHandler, StringComparison.Ordinal);

        var project = XDocument.Load(sharedProjectPath);
        var packageReferences = project
            .Descendants("PackageReference")
            .Select(reference => reference.Attribute("Include")?.Value)
            .ToArray();
        var interceptorNamespaces = project
            .Descendants("InterceptorsPreviewNamespaces")
            .Select(element => element.Value)
            .ToArray();
        var moduleAttributeFiles = Directory
            .EnumerateFiles(Path.GetDirectoryName(sharedProjectPath)!, "*.cs", SearchOption.AllDirectories)
            .Select(File.ReadAllText)
            .ToArray();

        Assert.Contains("Dapper.AOT", packageReferences);
        Assert.Contains(interceptorNamespaces, value => value.Contains("Dapper.AOT", StringComparison.Ordinal));
        Assert.Contains(moduleAttributeFiles, source => source.Contains("[module: Dapper.DapperAot]", StringComparison.Ordinal));
    }

    private static string FindRepositoryRoot()
    {
        var directory = new DirectoryInfo(AppContext.BaseDirectory);
        while (directory is not null)
        {
            if (File.Exists(Path.Combine(directory.FullName, "Directory.Build.props")))
            {
                return directory.FullName;
            }

            directory = directory.Parent;
        }

        throw new InvalidOperationException("Could not locate repository root.");
    }
}
