using MBN_STOCK_WEBVIEW.Infrastructure;
using MMoneyCoderSharp.Data;

namespace MBN_STOCK_WEBVIEW;

public sealed partial class MainWindow
{
    private LegacyNamedComparisonRestoreService? _namedComparisonRestoreService;

    private async Task PostNamedComparisonRestoreAsync(
        string requestId,
        IReadOnlyList<NamedPlaylistStoredItem> items,
        CancellationToken cancellationToken)
    {
        var candidates = items
            .Select(static item => new LegacyNamedComparisonRestoreRow(
                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(LegacyNamedComparisonRestoreService.IsCandidate)
            .ToArray();
        if (candidates.Length == 0)
        {
            return;
        }

        try
        {
            var runtime = _databaseRuntime;
            if (runtime is null)
            {
                PostNamedComparisonRestoreError(
                    requestId,
                    "DATABASE_UNAVAILABLE",
                    "현재 종목 마스터 DB를 사용할 수 없어 비교 행을 재검증하지 못했습니다.");
                return;
            }

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

            throw;
        }
        catch (DatabaseOperationException)
        {
            PostNamedComparisonRestoreError(
                requestId,
                "DATABASE_UNAVAILABLE",
                "현재 종목 마스터 DB에서 비교 행을 재검증하지 못했습니다.");
            _ = PostDatabaseStatusAsync(_lifetimeCancellation.Token);
        }
        catch
        {
            PostNamedComparisonRestoreError(
                requestId,
                "RESTORE_FAILED",
                "저장된 비교 행을 현재 명시적 선택으로 안전하게 복원하지 못했습니다.");
        }
    }

    private static object ToNamedComparisonRestoreWireRow(
        LegacyNamedComparisonRestoreOutcome outcome)
    {
        if (outcome.IsResolved)
        {
            return new
            {
                outcome.ItemIndex,
                status = "resolved",
                outcome.ActionId,
                first = ToLegacyComparisonImportWireTarget(outcome.First!),
                second = ToLegacyComparisonImportWireTarget(outcome.Second!)
            };
        }

        return new
        {
            outcome.ItemIndex,
            status = "failed",
            failure = outcome.Failure switch
            {
                LegacyNamedComparisonRestoreFailure.InvalidRow => "INVALID_ROW",
                LegacyNamedComparisonRestoreFailure.MissingMarketIdentity =>
                    "MISSING_MARKET_IDENTITY",
                LegacyNamedComparisonRestoreFailure.IdentityNotFound => "IDENTITY_NOT_FOUND",
                LegacyNamedComparisonRestoreFailure.IdentityAmbiguous => "IDENTITY_AMBIGUOUS",
                LegacyNamedComparisonRestoreFailure.UnsupportedAction => "UNSUPPORTED_ACTION",
                LegacyNamedComparisonRestoreFailure.DatabaseDataInvalid =>
                    "DATABASE_DATA_INVALID",
                _ => "RESTORE_FAILED"
            }
        };
    }

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