using System.Text.Json;
using MBN_STOCK_WEBVIEW.LegacyApplication;
using MBN_STOCK_WEBVIEW.LegacyBridge;

namespace MBN_STOCK_WEBVIEW.LegacyBridge.Tests;

public sealed class LegacyInteractionMetricsBridgeTests
{
    [Fact]
    public void SerializeState_ProjectsExplicitSystemDragMetricsWithCamelCaseNames()
    {
        var json = LegacyBridgeProtocol.SerializeState(
            CreateSnapshot(),
            interactionMetrics: new LegacyInteractionMetrics(7, 9, 96, 1.5, 725));

        using var document = JsonDocument.Parse(json);
        var payload = document.RootElement.GetProperty("payload");
        var metrics = payload.GetProperty("interactionMetrics");

        Assert.Equal(7, metrics.GetProperty("cutDragWidthDips").GetInt32());
        Assert.Equal(9, metrics.GetProperty("cutDragHeightDips").GetInt32());
        Assert.Equal("host-dip", metrics.GetProperty("coordinateSpace").GetString());
        Assert.Equal(96u, metrics.GetProperty("sourceDpi").GetUInt32());
        Assert.Equal(1.5d, metrics.GetProperty("hostRasterizationScale").GetDouble());
        Assert.Equal(725, metrics.GetProperty("doubleClickTimeMilliseconds").GetInt32());
        Assert.False(metrics.TryGetProperty("CutDragWidthDips", out _));
        Assert.False(metrics.TryGetProperty("CutDragHeightDips", out _));
    }

    [Theory]
    [InlineData(6, 9, 144u, 4, 6)]
    [InlineData(5, 5, 120u, 4, 4)]
    [InlineData(7, 7, 168u, 4, 4)]
    public void FromPixelsAtDpi_ConvertsWindowsPixelsToCssPixelCoordinates(
        int physicalWidth,
        int physicalHeight,
        uint dpi,
        int expectedCssWidth,
        int expectedCssHeight)
    {
        var metrics = LegacyInteractionMetrics.FromPixelsAtDpi(
            physicalWidth,
            physicalHeight,
            dpi);

        Assert.Equal(expectedCssWidth, metrics.CutDragWidthDips);
        Assert.Equal(expectedCssHeight, metrics.CutDragHeightDips);
        Assert.Equal(dpi, metrics.SourceDpi);
    }

    [Fact]
    public void FromPixelsAtDpi_RejectsUnknownDpiAndInvalidAxesSafely()
    {
        var unknownDpi = LegacyInteractionMetrics.FromPixelsAtDpi(8, 8, 0, 1.5);
        Assert.Equal(4, unknownDpi.CutDragWidthDips);
        Assert.Equal(4, unknownDpi.CutDragHeightDips);
        Assert.Equal(1.5d, unknownDpi.HostRasterizationScale);
        Assert.Equal(500, unknownDpi.DoubleClickTimeMilliseconds);

        var metrics = LegacyInteractionMetrics.FromPixelsAtDpi(0, -1, 192);
        Assert.Equal(4, metrics.CutDragWidthDips);
        Assert.Equal(4, metrics.CutDragHeightDips);
        Assert.Equal(192u, metrics.SourceDpi);
        Assert.Equal(500, metrics.DoubleClickTimeMilliseconds);
    }

    [Fact]
    public void SerializeState_NormalizesInvalidSystemMetricsPerAxisToFourPixels()
    {
        var json = LegacyBridgeProtocol.SerializeState(
            CreateSnapshot(),
            interactionMetrics: new LegacyInteractionMetrics(0, -1, 0, double.NaN, 5_001));

        using var document = JsonDocument.Parse(json);
        var metrics = document.RootElement
            .GetProperty("payload")
            .GetProperty("interactionMetrics");

        Assert.Equal(4, metrics.GetProperty("cutDragWidthDips").GetInt32());
        Assert.Equal(4, metrics.GetProperty("cutDragHeightDips").GetInt32());
        Assert.Equal("host-dip", metrics.GetProperty("coordinateSpace").GetString());
        Assert.Equal(96u, metrics.GetProperty("sourceDpi").GetUInt32());
        Assert.Equal(1d, metrics.GetProperty("hostRasterizationScale").GetDouble());
        Assert.Equal(500, metrics.GetProperty("doubleClickTimeMilliseconds").GetInt32());
    }

    [Fact]
    public void SerializeState_ExistingCallShapeReceivesSafeDefaultMetrics()
    {
        var json = LegacyBridgeProtocol.SerializeState(CreateSnapshot());

        using var document = JsonDocument.Parse(json);
        var metrics = document.RootElement
            .GetProperty("payload")
            .GetProperty("interactionMetrics");

        Assert.Equal(4, metrics.GetProperty("cutDragWidthDips").GetInt32());
        Assert.Equal(4, metrics.GetProperty("cutDragHeightDips").GetInt32());
        Assert.Equal("host-dip", metrics.GetProperty("coordinateSpace").GetString());
        Assert.Equal(96u, metrics.GetProperty("sourceDpi").GetUInt32());
        Assert.Equal(1d, metrics.GetProperty("hostRasterizationScale").GetDouble());
        Assert.Equal(500, metrics.GetProperty("doubleClickTimeMilliseconds").GetInt32());
    }

    [Theory]
    [InlineData(1)]
    [InlineData(350)]
    [InlineData(5_000)]
    public void FromPixelsAtDpi_PreservesValidWindowsDoubleClickTime(int milliseconds)
    {
        var metrics = LegacyInteractionMetrics.FromPixelsAtDpi(
            4,
            4,
            96,
            doubleClickTimeMilliseconds: milliseconds);

        Assert.Equal(milliseconds, metrics.DoubleClickTimeMilliseconds);
    }

    private static LegacyOperatorSnapshot CreateSnapshot() => new(
        1,
        string.Empty,
        [],
        null,
        [],
        [],
        null,
        string.Empty,
        LegacyOperatorStatusKind.Neutral);
}
