using MBN_STOCK_WEBVIEW.Infrastructure;
using MMoneyCoderSharp.Data;

namespace MBN_STOCK_WEBVIEW;

public sealed partial class MainWindow
{
    private LegacyNamedForeignStockRestoreService? _namedForeignStockRestoreService;

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

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

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

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

    private static object ToNamedForeignStockRestoreWireRow(
        LegacyNamedForeignStockRestoreOutcome outcome)
    {
        if (outcome.IsResolved)
        {
            var identity = outcome.Identity!;
            return new
            {
                outcome.ItemIndex,
                status = "resolved",
                identity.ActionId,
                identity.InputName,
                identity.Symbol,
                identity.NationCode,
                identity.ForeignDomesticCode,
                identity.BuilderKey,
                identity.CutCode,
                identity.ValueType,
                identity.PeriodDays
            };
        }

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

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