using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;

namespace MBN_STOCK_WEBVIEW.Core.Tests;

public sealed class LegacySceneDataSourceRouterTests
{
    [Fact]
    public async Task Router_DispatchesOnlyTheClosedRegisteredCutAlias()
    {
        LegacyPlaylistEntry? received = null;
        var router = new LegacySceneDataSourceRouter(
        [
            new LegacySceneDataSourceRoute(["5001", "N5001"], (entry, page, _) =>
            {
                received = entry;
                Assert.Equal(0, page);
                return Task.FromResult(new LegacySceneDataPage(
                    "s5085",
                    new S5085SceneData([]),
                    1));
            })
        ]);
        var request = new LegacyPlaylistEntry("entry", "N5001");

        var result = await router.LoadPageAsync(request, 0);

        Assert.Same(request, received);
        Assert.Equal("s5085", result.BuilderKey);
        Assert.Equal(["5001", "N5001"], router.CutCodes);
    }

    [Fact]
    public async Task Router_RejectsUnknownCutBeforeCallingAnyLoader()
    {
        var calls = 0;
        var router = new LegacySceneDataSourceRouter(
        [
            new LegacySceneDataSourceRoute(["5001"], (entry, page, _) =>
            {
                calls++;
                return Task.FromResult(new LegacySceneDataPage(
                    "s5085",
                    new S5085SceneData([]),
                    1));
            })
        ]);

        await Assert.ThrowsAsync<LegacySceneDataException>(() =>
            router.LoadPageAsync(new LegacyPlaylistEntry("entry", "9999"), 0));

        Assert.Equal(0, calls);
    }

    [Fact]
    public async Task Router_AlwaysRejectsUnresolvedNamedPlaylistEntryBeforeAnyLoader()
    {
        var pageCalls = 0;
        var planCalls = 0;
        var router = new LegacySceneDataSourceRouter(
        [
            new LegacySceneDataSourceRoute(
                ["5001"],
                (entry, page, _) =>
                {
                    pageCalls++;
                    return Task.FromResult(new LegacySceneDataPage(
                        "s5085",
                        new S5085SceneData([]),
                        1));
                },
                (entry, _) =>
                {
                    planCalls++;
                    return Task.FromResult(new LegacySceneDataPage(
                        "s5085",
                        new S5085SceneData([]),
                        1));
                })
        ]);
        var unresolved = new LegacyPlaylistEntry(
            "entry",
            LegacyPlaylistEntry.UnresolvedCutCode);

        await Assert.ThrowsAsync<LegacySceneDataException>(() =>
            router.LoadPageAsync(unresolved, 0));
        await Assert.ThrowsAsync<LegacySceneDataException>(() =>
            router.LoadPagePlanDataAsync(unresolved));

        Assert.Equal(0, pageCalls);
        Assert.Equal(0, planCalls);
    }

    [Fact]
    public void Constructor_RejectsDuplicateOrUnsafeRoutes()
    {
        static Task<LegacySceneDataPage> Load(
            LegacyPlaylistEntry entry,
            int page,
            CancellationToken token) => throw new NotSupportedException();

        Assert.Throws<ArgumentException>(() => new LegacySceneDataSourceRouter(
        [
            new LegacySceneDataSourceRoute(["5001"], Load),
            new LegacySceneDataSourceRoute(["5001"], Load)
        ]));
        Assert.Throws<ArgumentException>(() =>
            new LegacySceneDataSourceRoute(["../5001"], Load));
        Assert.Throws<ArgumentException>(() =>
            new LegacySceneDataSourceRoute([], Load));
    }
}
