using MBN_STOCK_WEBVIEW.Infrastructure;
using MMoneyCoderSharp.Data;

namespace MBN_STOCK_WEBVIEW;

public sealed partial class MainWindow
{
    private LegacyForeignIndexCandleRestoreService? _namedForeignIndexCandleRestoreService;

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

        try
        {
            var runtime = _databaseRuntime;
            if (runtime is null)
            {
                PostNamedForeignIndexCandleRestoreError(
                    requestId,
                    "DATABASE_UNAVAILABLE",
                    "현재 해외지수 master DB를 사용할 수 없어 캔들 행을 재검증하지 못했습니다.");
                return;
            }

            var service = _namedForeignIndexCandleRestoreService ??=
                new LegacyForeignIndexCandleRestoreService(runtime.Executor);
            var result = await service.ResolveAsync(candidates, cancellationToken);
            cancellationToken.ThrowIfCancellationRequested();
            PostMessage("named-foreign-index-candle-restore-results", new
            {
                requestId,
                result.RetrievedAt,
                totalRowCount = result.Rows.Count,
                rows = result.Rows.Select(ToNamedForeignIndexCandleRestoreWireRow)
            });
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            if (Volatile.Read(ref _playoutCommandInFlight) != 0 &&
                !_lifetimeCancellation.IsCancellationRequested)
            {
                PostNamedForeignIndexCandleRestoreError(
                    requestId,
                    "PLAYOUT_PRIORITY",
                    "송출 명령 우선 처리로 해외지수 캔들 재검증을 취소했습니다. 자동 재시도하지 않습니다.");
            }

            throw;
        }
        catch (DatabaseOperationException)
        {
            PostNamedForeignIndexCandleRestoreError(
                requestId,
                "DATABASE_UNAVAILABLE",
                "현재 해외지수 master DB에서 캔들 행을 재검증하지 못했습니다.");
            _ = PostDatabaseStatusAsync(_lifetimeCancellation.Token);
        }
        catch
        {
            PostNamedForeignIndexCandleRestoreError(
                requestId,
                "RESTORE_FAILED",
                "저장된 해외지수 캔들 행을 안전한 s8010 선택으로 복원하지 못했습니다.");
        }
    }

    private static object ToNamedForeignIndexCandleRestoreWireRow(
        LegacyForeignIndexCandleRestoreOutcome outcome)
    {
        if (outcome.IsResolved)
        {
            var identity = outcome.Identity!;
            return new
            {
                outcome.ItemIndex,
                status = "resolved",
                identity.TargetKey,
                identity.InputName,
                identity.Symbol,
                identity.NationCode,
                identity.ForeignDomesticCode,
                identity.SceneCode,
                identity.ValueType,
                identity.PeriodDays,
                identity.CutCode
            };
        }

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

    private void PostNamedForeignIndexCandleRestoreError(
        string requestId,
        string code,
        string message)
    {
        PostMessage("named-foreign-index-candle-restore-error", new
        {
            requestId,
            code,
            message,
            retryable = false
        });
    }
}
