using System.Collections;
using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;
using MBN_STOCK_WEBVIEW.LegacyApplication;

namespace MBN_STOCK_WEBVIEW.LegacyApplication.Tests;

public sealed class LegacyOverseasActionCatalogTests
{
    private static readonly string[] ExpectedFixedNames =
    [
        "다우존스",
        "나스닥",
        "S&P500",
        "독일 DAX 30",
        "영국 FTSE 100",
        "프랑스 CAC 40",
        "일본 니케이",
        "중국 상해종합",
        "홍콩 항셍",
        "대만 가권"
    ];

    private static readonly string[] ExpectedSymbols =
    [
        "DJI@DJI",
        "NAS@IXIC",
        "SPI@SPX",
        "XTR@DAX30",
        "LNS@FTSE100",
        "PAS@CAC40",
        "NII@NI225",
        "SHS@000001",
        "HSI@HSI",
        "TWS@TI01"
    ];

    private static readonly string[] ExpectedActionIds =
    [
        "index-candle-5d",
        "index-candle-20d",
        "index-candle-60d",
        "index-candle-120d",
        "index-candle-240d",
        "industry-current",
        "stock-current",
        "stock-candle-5d",
        "stock-candle-20d",
        "stock-candle-60d",
        "stock-candle-120d",
        "stock-candle-240d"
    ];

    [Fact]
    public void FixedIndexListMatchesUc5OrderAndClosedIdentity()
    {
        var targets = LegacyOverseasActionCatalog.FixedIndexTargets;

        Assert.Equal(LegacyOverseasActionCatalog.FixedIndexTargetCount, targets.Count);
        Assert.Equal(ExpectedFixedNames, targets.Select(target => target.DisplayName));
        Assert.Equal(ExpectedFixedNames, targets.Select(target => target.InputName));
        Assert.Equal(ExpectedSymbols, targets.Select(target => target.Symbol));
        Assert.Equal(
            ["US", "US", "US", "DE", "GB", "FR", "JP", "CN", "HK", "TW"],
            targets.Select(target => target.NationCode));
        Assert.All(targets, target => Assert.Equal("0", target.ForeignDomesticCode));
        Assert.Equal(
            targets.Count,
            targets.Select(target => target.TargetId).Distinct(StringComparer.Ordinal).Count());

        var list = Assert.IsAssignableFrom<IList<LegacyOverseasFixedIndexTarget>>(targets);
        Assert.True(list.IsReadOnly);
        Assert.Throws<NotSupportedException>(() => list.RemoveAt(0));
    }

    [Fact]
    public void ActionsMatchUc5ButtonOrderAliasesAndPaging()
    {
        var actions = LegacyOverseasActionCatalog.Actions;

        Assert.Equal(LegacyOverseasActionCatalog.ActionCount, actions.Count);
        Assert.Equal(ExpectedActionIds, actions.Select(action => action.ActionId));
        Assert.Equal(
            ["8061", "8040", "8046", "8051", "8056"],
            actions.Take(5).Select(action => action.SceneAlias));
        Assert.Equal("5001", actions[5].SceneAlias);
        Assert.Equal("5001", actions[6].SceneAlias);
        Assert.Equal(
            ["8061", "8040", "8046", "8051", "8056"],
            actions.Skip(7).Select(action => action.SceneAlias));
        Assert.All(actions, action =>
        {
            Assert.Equal(0, action.PageSize);
            Assert.Equal([action.SceneAlias], action.Aliases);
            Assert.Contains(
                LegacySceneCatalog.FindByCutAlias(action.SceneAlias),
                scene => scene.BuilderKey == action.BuilderKey && (int)scene.PageSize == 0);
        });
        Assert.Equal(5, actions.Count(action => action.Source == LegacyOverseasActionSource.FixedIndex));
        Assert.Single(actions, action => action.Source == LegacyOverseasActionSource.Industry);
        Assert.Equal(6, actions.Count(action => action.Source == LegacyOverseasActionSource.Stock));
        Assert.Equal(10, actions.Count(action => action.SupportsMovingAverages));

        var list = Assert.IsAssignableFrom<IList<LegacyOverseasActionDefinition>>(actions);
        Assert.True(list.IsReadOnly);
        Assert.Throws<NotSupportedException>(() => list.RemoveAt(0));
        var aliases = Assert.IsAssignableFrom<IList<string>>(actions[0].Aliases);
        Assert.True(aliases.IsReadOnly);
    }

    [Theory]
    [InlineData("index-candle-5d", LegacyOverseasActionSource.FixedIndex, 5, "s8010", "8061")]
    [InlineData("index-candle-240d", LegacyOverseasActionSource.FixedIndex, 240, "s8010", "8056")]
    [InlineData("industry-current", LegacyOverseasActionSource.Industry, null, "s5001", "5001")]
    [InlineData("stock-current", LegacyOverseasActionSource.Stock, null, "s5001", "5001")]
    [InlineData("stock-candle-120d", LegacyOverseasActionSource.Stock, 120, "s8010", "8051")]
    public void LookupReturnsExactClosedDefinition(
        string actionId,
        LegacyOverseasActionSource source,
        int? periodDays,
        string builderKey,
        string sceneAlias)
    {
        var action = LegacyOverseasActionCatalog.GetAction(actionId);

        Assert.Same(action, LegacyOverseasActionCatalog.FindAction(actionId));
        Assert.Equal(source, action.Source);
        Assert.Equal(periodDays, action.PeriodDays);
        Assert.Equal(builderKey, action.BuilderKey);
        Assert.Equal(sceneAlias, action.SceneAlias);
    }

    [Fact]
    public void SourceViewsAndUnknownValuesFailClosed()
    {
        Assert.Equal(
            5,
            LegacyOverseasActionCatalog.GetActions(LegacyOverseasActionSource.FixedIndex).Count);
        Assert.Single(LegacyOverseasActionCatalog.GetActions(LegacyOverseasActionSource.Industry));
        Assert.Equal(
            6,
            LegacyOverseasActionCatalog.GetActions(LegacyOverseasActionSource.Stock).Count);
        Assert.Equal(
            "독일 DAX 30",
            LegacyOverseasActionCatalog.GetFixedIndexTarget("germany-dax-30").DisplayName);
        Assert.Null(LegacyOverseasActionCatalog.FindAction("../8010"));
        Assert.Null(LegacyOverseasActionCatalog.FindFixedIndexTarget("DOW-JONES"));
        Assert.Throws<KeyNotFoundException>(() =>
            LegacyOverseasActionCatalog.GetAction("../8010"));
        Assert.Throws<KeyNotFoundException>(() =>
            LegacyOverseasActionCatalog.GetFixedIndexTarget("DOW-JONES"));
        Assert.Throws<ArgumentOutOfRangeException>(() =>
            LegacyOverseasActionCatalog.GetActions((LegacyOverseasActionSource)99));
    }
}
