using MBN_STOCK_WEBVIEW.Core.Playout;
using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;

namespace MBN_STOCK_WEBVIEW.Core.Tests;

public sealed class LegacyPriceDirectionMutationsTests
{
    [Theory]
    [InlineData("상한", ScenePriceDirection.LimitUp)]
    [InlineData("상승", ScenePriceDirection.Up)]
    [InlineData("+", ScenePriceDirection.Up)]
    [InlineData("보합", ScenePriceDirection.Flat)]
    [InlineData(" ", ScenePriceDirection.Flat)]
    [InlineData("하락", ScenePriceDirection.Down)]
    [InlineData("-", ScenePriceDirection.Down)]
    [InlineData("하한", ScenePriceDirection.LimitDown)]
    [InlineData("unknown", ScenePriceDirection.Unknown)]
    public void Parse_matches_legacy_direction_values(
        string value,
        ScenePriceDirection expected)
    {
        Assert.Equal(expected, LegacyPriceDirectionMutations.Parse(value));
    }

    [Fact]
    public void Build_up_variant_one_matches_original_object_order()
    {
        var mutations = LegacyPriceDirectionMutations.Build(ScenePriceDirection.Up, 1);

        Assert.Collection(
            mutations,
            mutation => Visible(mutation, "upup1", false),
            mutation => Visible(mutation, "up1", false),
            mutation => Visible(mutation, "flat1", false),
            mutation => Visible(mutation, "down1", false),
            mutation => Visible(mutation, "downdown1", false),
            mutation => Visible(mutation, "up1", true),
            mutation => Visible(mutation, "bg1_1", true),
            mutation => Visible(mutation, "changePrice1_1", true),
            mutation => Visible(mutation, "wonText1_1", true),
            mutation => Visible(mutation, "rate1_1", true),
            mutation => Visible(mutation, "percent1_1", true),
            mutation => Visible(mutation, "bg2_1", false),
            mutation => Visible(mutation, "changePrice2_1", false),
            mutation => Visible(mutation, "wonText2_1", false),
            mutation => Visible(mutation, "rate2_1", false),
            mutation => Visible(mutation, "percent2_1", false),
            mutation => Visible(mutation, "bg3_1", false),
            mutation => Visible(mutation, "changePrice3_1", false),
            mutation => Visible(mutation, "wonText3_1", false),
            mutation => Visible(mutation, "rate3_1", false),
            mutation => Visible(mutation, "percent3_1", false),
            mutation => Visible(mutation, "unit1_1", true),
            mutation => Visible(mutation, "unit2_1", false),
            mutation => Visible(mutation, "unit3_1", false),
            mutation => Asset(mutation, "pattern1", @"Images\그림_빨강.png"));
    }

    [Fact]
    public void Build_flat_variant_three_includes_original_price_switch()
    {
        var mutations = LegacyPriceDirectionMutations.Build(ScenePriceDirection.Flat, 3);

        Assert.Collection(
            mutations.Skip(24),
            mutation => Visible(mutation, "price1_", false),
            mutation => Visible(mutation, "price2_", true),
            mutation => Visible(mutation, "price3_", false),
            mutation => Asset(mutation, "pattern", @"Images\그림_검정.png"));
    }

    [Fact]
    public void Build_unknown_only_hides_direction_objects()
    {
        var mutations = LegacyPriceDirectionMutations.Build(ScenePriceDirection.Unknown, 0);

        Assert.Collection(
            mutations,
            mutation => Visible(mutation, "upup", false),
            mutation => Visible(mutation, "up", false),
            mutation => Visible(mutation, "flat", false),
            mutation => Visible(mutation, "down", false),
            mutation => Visible(mutation, "downdown", false));
    }

    [Theory]
    [InlineData(-1)]
    [InlineData(4)]
    public void Build_rejects_unknown_variant_index(int value)
    {
        Assert.Throws<ArgumentOutOfRangeException>(() =>
            LegacyPriceDirectionMutations.Build(ScenePriceDirection.Up, value));
    }

    private static void Visible(PlayoutMutation mutation, string name, bool visible)
    {
        var actual = Assert.IsType<PlayoutSetVisible>(mutation);
        Assert.Equal(name, actual.ObjectName);
        Assert.Equal(visible, actual.IsVisible);
    }

    private static void Asset(PlayoutMutation mutation, string name, string path)
    {
        var actual = Assert.IsType<PlayoutSetAssetValue>(mutation);
        Assert.Equal(name, actual.ObjectName);
        Assert.Equal(path, actual.AssetPath);
    }
}
