using System.Buffers.Binary;

namespace MBN_STOCK_WEBVIEW.LegacyWeb.Tests;

public sealed class LegacyAppIconContractTests
{
    private static readonly string RepositoryRoot = FindRepositoryRoot();
    private static readonly string AssetsRoot = Path.Combine(RepositoryRoot, "Assets");
    private static readonly string AppRoot = Path.Combine(
        RepositoryRoot,
        "src",
        "MBN_STOCK_WEBVIEW.LegacyParityApp");

    public static TheoryData<string, int, int> PackagePngAssets => new()
    {
        { "LockScreenLogo.scale-200.png", 48, 48 },
        { "SplashScreen.scale-200.png", 1240, 600 },
        { "Square150x150Logo.scale-200.png", 300, 300 },
        { "Square44x44Logo.scale-200.png", 88, 88 },
        { "Square44x44Logo.targetsize-16_altform-unplated.png", 16, 16 },
        { "Square44x44Logo.targetsize-24_altform-unplated.png", 24, 24 },
        { "Square44x44Logo.targetsize-32_altform-unplated.png", 32, 32 },
        { "Square44x44Logo.targetsize-48_altform-unplated.png", 48, 48 },
        { "Square44x44Logo.targetsize-256_altform-unplated.png", 256, 256 },
        { "StoreLogo.png", 50, 50 },
        { "Wide310x150Logo.scale-200.png", 620, 300 }
    };

    [Theory]
    [MemberData(nameof(PackagePngAssets))]
    public void PackageIconsAreExactRgbaPngAssets(string fileName, int width, int height)
    {
        var bytes = File.ReadAllBytes(Path.Combine(AssetsRoot, fileName));

        Assert.True(
            bytes.Length > Math.Max(500, (width * height) / 10),
            $"{fileName} still resembles an unrendered placeholder asset.");
        Assert.Equal(new byte[] { 137, 80, 78, 71, 13, 10, 26, 10 }, bytes[..8]);
        Assert.Equal("IHDR", System.Text.Encoding.ASCII.GetString(bytes, 12, 4));
        Assert.Equal(width, BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(16, 4)));
        Assert.Equal(height, BinaryPrimitives.ReadInt32BigEndian(bytes.AsSpan(20, 4)));
        Assert.Equal(8, bytes[24]);
        Assert.Equal(6, bytes[25]);
    }

    [Fact]
    public void ExecutableIconContainsEveryRequiredWindowsSize()
    {
        var bytes = File.ReadAllBytes(Path.Combine(AssetsRoot, "AppIcon.ico"));
        Assert.True(bytes.Length > 1000);
        Assert.Equal((ushort)0, BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(0, 2)));
        Assert.Equal((ushort)1, BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(2, 2)));
        var count = BinaryPrimitives.ReadUInt16LittleEndian(bytes.AsSpan(4, 2));
        Assert.Equal(6, count);

        var sizes = new List<int>();
        for (var index = 0; index < count; index++)
        {
            var width = bytes[6 + (index * 16)];
            var height = bytes[7 + (index * 16)];
            Assert.Equal(width, height);
            sizes.Add(width == 0 ? 256 : width);
        }

        Assert.Equal(new[] { 16, 24, 32, 48, 64, 256 }, sizes.Order());
    }

    [Fact]
    public void ProjectAndWindowUseTheSharedIconWithoutPackagingTheMasterArtwork()
    {
        var project = File.ReadAllText(Path.Combine(
            AppRoot,
            "MBN_STOCK_WEBVIEW.LegacyParityApp.csproj"));
        var window = File.ReadAllText(Path.Combine(AppRoot, "MainWindow.xaml.cs"));
        var manifest = File.ReadAllText(Path.Combine(AppRoot, "Package.appxmanifest"));

        Assert.Contains("<ApplicationIcon>..\\..\\Assets\\AppIcon.ico</ApplicationIcon>",
            project,
            StringComparison.Ordinal);
        Assert.Contains("Link=\"Assets\\AppIcon.ico\"", project, StringComparison.Ordinal);
        foreach (var targetSize in new[] { 16, 24, 32, 48, 256 })
        {
            Assert.Contains(
                $"Square44x44Logo.targetsize-{targetSize}_altform-unplated.png",
                project,
                StringComparison.Ordinal);
        }

        Assert.DoesNotContain("AppIconMaster.png", project, StringComparison.Ordinal);
        Assert.Contains(
            "Path.Combine(AppContext.BaseDirectory, \"Assets\", \"AppIcon.ico\")",
            window,
            StringComparison.Ordinal);
        Assert.Contains("appWindow.SetIcon(iconPath)", window, StringComparison.Ordinal);
        Assert.Contains("Square150x150Logo=\"Assets\\Square150x150Logo.png\"",
            manifest,
            StringComparison.Ordinal);
        Assert.Contains("Square44x44Logo=\"Assets\\Square44x44Logo.png\"",
            manifest,
            StringComparison.Ordinal);
        Assert.Contains("Wide310x150Logo=\"Assets\\Wide310x150Logo.png\"",
            manifest,
            StringComparison.Ordinal);
        Assert.Contains("<uap:SplashScreen Image=\"Assets\\SplashScreen.png\" />",
            manifest,
            StringComparison.Ordinal);
    }

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

            directory = directory.Parent;
        }

        throw new DirectoryNotFoundException("Repository root could not be located.");
    }
}
