using MBN_STOCK_WEBVIEW.Infrastructure;
using MMoneyCoderSharp.Data;

namespace MBN_STOCK_WEBVIEW;

public sealed partial class MainWindow
{
    private LegacyNamedNxtThemeRestoreService? _namedNxtThemeRestoreService;

    private async Task PostNamedNxtThemeRestoreAsync(
        string requestId,
        IReadOnlyList<NamedPlaylistStoredItem> items,
        CancellationToken cancellationToken)
    {
        var candidates = items
            .Select(static item => new LegacyNamedNxtThemeRestoreRow(
                item.ItemIndex,
                item.IsEnabled,
                item.Selection.GroupCode,
                item.Selection.Subject,
                item.Selection.GraphicType,
                item.Selection.Subtype,
                item.Page?.ToString() ?? string.Empty,
                item.Selection.DataCode))
            .Where(LegacyNamedNxtThemeRestoreService.IsCandidate)
            .ToArray();
        if (candidates.Length == 0)
        {
            return;
        }

        try
        {
            var runtime = _databaseRuntime;
            if (runtime is null)
            {
                PostNamedNxtThemeRestoreError(
                    requestId,
                    "DATABASE_UNAVAILABLE",
                    "현재 MariaDB를 사용할 수 없어 저장된 NXT 테마를 재검증하지 못했습니다.");
                return;
            }

            var service = _namedNxtThemeRestoreService ??=
                new LegacyNamedNxtThemeRestoreService(runtime.Executor);
            var result = await service.ResolveAsync(candidates, cancellationToken);
            cancellationToken.ThrowIfCancellationRequested();
            PostMessage("named-nxt-theme-restore-results", new
            {
                requestId,
                result.RetrievedAt,
                totalRowCount = result.Rows.Count,
                rows = result.Rows.Select(ToNamedNxtThemeRestoreWireRow)
            });
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            if (Volatile.Read(ref _playoutCommandInFlight) != 0 &&
                !_lifetimeCancellation.IsCancellationRequested)
            {
                PostNamedNxtThemeRestoreError(
                    requestId,
                    "PLAYOUT_PRIORITY",
                    "송출 명령 우선 처리로 NXT 테마 재검증을 취소했습니다. 자동 재시도하지 않습니다.");
            }

            throw;
        }
        catch (DatabaseOperationException)
        {
            PostNamedNxtThemeRestoreError(
                requestId,
                "DATABASE_UNAVAILABLE",
                "현재 MariaDB에서 NXT 테마를 재검증하지 못했습니다.");
            _ = PostDatabaseStatusAsync(_lifetimeCancellation.Token);
        }
        catch
        {
            PostNamedNxtThemeRestoreError(
                requestId,
                "RESTORE_FAILED",
                "저장된 NXT 테마 행을 안전한 현재 선택으로 복원하지 못했습니다.");
        }
    }

    private static object ToNamedNxtThemeRestoreWireRow(
        LegacyNamedNxtThemeRestoreOutcome outcome)
    {
        if (outcome.IsResolved)
        {
            var identity = outcome.Identity!;
            return new
            {
                outcome.ItemIndex,
                status = "resolved",
                identity.ActionId,
                identity.BuilderKey,
                identity.CutCode,
                identity.PageSize,
                identity.Sort,
                session = identity.Session switch
                {
                    ThemeSession.PreMarket => "PRE_MARKET",
                    ThemeSession.AfterMarket => "AFTER_MARKET",
                    _ => throw new InvalidOperationException("NXT theme session is invalid.")
                },
                identity.ThemeTitle,
                identity.StoredThemeCode,
                identity.CurrentThemeCode,
                identity.PreviewItemCount,
                identity.LiveItemCount,
                identity.PreviewIsTruncated,
                identity.CodeWasRemapped
            };
        }

        return new
        {
            outcome.ItemIndex,
            status = "failed",
            failure = outcome.Failure switch
            {
                LegacyNamedNxtThemeRestoreFailure.InvalidRow => "INVALID_ROW",
                LegacyNamedNxtThemeRestoreFailure.UnsupportedAction => "UNSUPPORTED_ACTION",
                LegacyNamedNxtThemeRestoreFailure.IdentityNotFound => "IDENTITY_NOT_FOUND",
                LegacyNamedNxtThemeRestoreFailure.IdentityAmbiguous => "IDENTITY_AMBIGUOUS",
                LegacyNamedNxtThemeRestoreFailure.PreviewEmpty => "PREVIEW_EMPTY",
                LegacyNamedNxtThemeRestoreFailure.LiveItemsEmpty => "LIVE_ITEMS_EMPTY",
                LegacyNamedNxtThemeRestoreFailure.DatabaseDataInvalid =>
                    "DATABASE_DATA_INVALID",
                _ => "RESTORE_FAILED"
            }
        };
    }

    private void PostNamedNxtThemeRestoreError(
        string requestId,
        string code,
        string message)
    {
        PostMessage("named-nxt-theme-restore-error", new
        {
            requestId,
            code,
            message,
            retryable = false
        });
    }
}
