using System.Xml.Linq;

namespace ZB.MOM.WW.MxGateway.Tests.ProjectStructure;

public sealed class GatewayProjectReferenceTests
{
    /// <summary>Verifies that the gateway project targets .NET 10.0.</summary>
    [Fact]
    public void GatewayProject_TargetsNet10()
    {
        XDocument project = LoadProject("ZB.MOM.WW.MxGateway.Server");

        Assert.Equal("net10.0", ElementValue(project, "TargetFramework"));
    }

    /// <summary>Verifies that the gateway project does not reference MXAccess COM.</summary>
    [Fact]
    public void GatewayProject_DoesNotReferenceMxAccessCom()
    {
        XDocument project = LoadProject("ZB.MOM.WW.MxGateway.Server");

        IReadOnlyList<string> referenceNames = project
            .Descendants()
            .Where(element => element.Name.LocalName is "Reference" or "COMReference" or "COMFileReference" or "PackageReference")
            .Select(element => (string?)element.Attribute("Include") ?? string.Empty)
            .ToArray();

        Assert.DoesNotContain(referenceNames, reference =>
            reference.Contains("MxAccess", StringComparison.OrdinalIgnoreCase)
            || reference.Contains("ArchestrA.MXAccess", StringComparison.OrdinalIgnoreCase)
            || reference.Contains("LMXProxy", StringComparison.OrdinalIgnoreCase));
    }

    private static XDocument LoadProject(string projectName)
    {
        DirectoryInfo repositoryRoot = FindRepositoryRoot();
        string projectPath = Path.Combine(repositoryRoot.FullName, projectName, $"{projectName}.csproj");

        return XDocument.Load(projectPath);
    }

    private static string ElementValue(XDocument project, string elementName)
    {
        return project
            .Descendants()
            .Single(element => element.Name.LocalName == elementName)
            .Value;
    }

    private static DirectoryInfo FindRepositoryRoot()
    {
        DirectoryInfo? current = new(AppContext.BaseDirectory);

        while (current is not null)
        {
            if (File.Exists(Path.Combine(current.FullName, "ZB.MOM.WW.MxGateway.slnx")))
            {
                return current;
            }

            current = current.Parent;
        }

        throw new DirectoryNotFoundException("Could not locate src/ZB.MOM.WW.MxGateway.slnx from the test output directory.");
    }
}
