using System.Globalization;
using MBN_STOCK_WEBVIEW.Core.Playout.Scenes;
using MBN_STOCK_WEBVIEW.LegacyApplication;
using MMoneyCoderSharp.Data;

internal static class NamedPlaylistOperatorCompatibilityAudit
{
    internal static async Task RunAsync(
        IDataQueryExecutor executor,
        CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(executor);
        var persistence = new LegacyNamedPlaylistPersistenceService(executor);
        var workflow = new LegacyNamedPlaylistWorkflowController(persistence);
        var controller = new LegacyOperatorController(
            new UnusedStockLookup(),
            namedPlaylistWorkflow: workflow);

        var listed = await controller.RefreshNamedPlaylistsAsync(cancellationToken)
            .ConfigureAwait(false);
        var definitions = listed.NamedPlaylist?.Definitions ?? [];
        if (definitions.Count == 0)
        {
            throw new InvalidDataException(
                "The operator compatibility audit did not receive a named-playlist definition.");
        }

        var rowCount = 0;
        var resolvedCount = 0;
        var unresolvedCount = 0;
        for (var definitionIndex = 0; definitionIndex < definitions.Count; definitionIndex++)
        {
            var definition = definitions[definitionIndex];
            cancellationToken.ThrowIfCancellationRequested();
            var loaded = await controller.LoadNamedPlaylistByIdAsync(
                    definition.DefinitionId,
                    cancellationToken)
                .ConfigureAwait(false);
            var boundary = loaded.CommandResult?.Succeeded != true
                ? "command"
                : loaded.Dialog is not null
                    ? "dialog"
                    : loaded.NamedPlaylist?.ReadStatus != LegacyNamedPlaylistReadStatus.Ready
                        ? "read-status"
                        : loaded.NamedPlaylist.DocumentFreshness !=
                            LegacyNamedPlaylistFreshness.Fresh
                            ? "freshness"
                            : loaded.Playlist.Count != loaded.NamedPlaylist.Rows.Count
                                ? "row-count"
                                : null;
            if (boundary is not null)
            {
                Console.WriteLine(
                    "PLIST_OPERATOR_COMPAT_BOUNDARY: " + boundary +
                    " definitionOrdinal=" +
                    definitionIndex.ToString(CultureInfo.InvariantCulture) +
                    " commandSucceeded=" + (loaded.CommandResult?.Succeeded == true) +
                    " dialog=" + (loaded.Dialog is not null) +
                    " status=" + loaded.StatusKind +
                    " read=" + loaded.NamedPlaylist?.ReadStatus +
                    " freshness=" + loaded.NamedPlaylist?.DocumentFreshness +
                    " loadedRows=" + loaded.Playlist.Count.ToString(CultureInfo.InvariantCulture) +
                    " documentRows=" +
                    (loaded.NamedPlaylist?.Rows.Count ?? -1).ToString(CultureInfo.InvariantCulture));
                throw new InvalidDataException(
                    "The operator compatibility audit failed its " + boundary +
                    " boundary at definition ordinal " +
                    definitionIndex.ToString(CultureInfo.InvariantCulture) + ".");
            }

            for (var rowIndex = 0; rowIndex < loaded.Playlist.Count; rowIndex++)
            {
                var row = loaded.Playlist[rowIndex];
                if (!row.RowId.StartsWith("legacy-named-", StringComparison.Ordinal))
                {
                    throw new InvalidDataException(
                        "The operator compatibility audit retained a previous row at definition " +
                        definitionIndex.ToString(CultureInfo.InvariantCulture) + ", row " +
                        rowIndex.ToString(CultureInfo.InvariantCulture) + ".");
                }

                var entry = row.ToPlayoutEntry();
                if (row.IsSceneResolved !=
                    !string.Equals(
                        entry.CutCode,
                        LegacyPlaylistEntry.UnresolvedCutCode,
                        StringComparison.Ordinal))
                {
                    throw new InvalidDataException(
                        "The operator compatibility audit found inconsistent scene state at definition " +
                        definitionIndex.ToString(CultureInfo.InvariantCulture) + ", row " +
                        rowIndex.ToString(CultureInfo.InvariantCulture) + ".");
                }

                if (row.IsSceneResolved)
                {
                    resolvedCount++;
                }
                else
                {
                    unresolvedCount++;
                }
            }

            rowCount += loaded.Playlist.Count;
        }

        Console.WriteLine(
            "PLIST_OPERATOR_COMPAT_AUDIT: " +
            $"definitions={definitions.Count.ToString(CultureInfo.InvariantCulture)} " +
            $"rowsLoaded={rowCount.ToString(CultureInfo.InvariantCulture)} " +
            $"sceneAliasResolved={resolvedCount.ToString(CultureInfo.InvariantCulture)} " +
            $"rowLevelDeferred={unresolvedCount.ToString(CultureInfo.InvariantCulture)} " +
            "wholeListRejected=0 playoutPreflightAsserted=false rawValuesPrinted=false");
    }

    private sealed class UnusedStockLookup : ILegacyStockLookup
    {
        public Task<LegacyStockSearchData> SearchAsync(
            string query,
            CancellationToken cancellationToken = default) =>
            Task.FromResult(new LegacyStockSearchData(query, [], []));
    }
}
