#nullable enable

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

internal static class RealSceneDbSmoke
{
    public static async Task RunAsync(
        IDataQueryExecutor executor,
        CancellationToken cancellationToken)
    {
        ArgumentNullException.ThrowIfNull(executor);
        cancellationToken.ThrowIfCancellationRequested();

        var traced = new QueryTracingDataQueryExecutor(executor);
        var run = new SceneSmokeRun();

        Console.WriteLine("DB_SMOKE_STEP: bounded scene selectors");
        var pieName = await SelectOneAsync(
            traced,
            "SELECTOR_INPUT_PIE",
            "SELECT STOCK_NAME FROM INPUT_PIE WHERE STOCK_NAME IS NOT NULL AND ROWNUM = 1",
            "STOCK_NAME",
            cancellationToken).ConfigureAwait(false);
        var profitName = await SelectOneAsync(
            traced,
            "SELECTOR_INPUT_PROFIT",
            "SELECT STOCK_NAME FROM INPUT_PROFIT WHERE STOCK_NAME IS NOT NULL AND ROWNUM = 1",
            "STOCK_NAME",
            cancellationToken).ConfigureAwait(false);
        var growthName = await SelectOneAsync(
            traced,
            "SELECTOR_INPUT_GROW",
            "SELECT STOCK_NAME FROM INPUT_GROW WHERE STOCK_NAME IS NOT NULL AND ROWNUM = 1",
            "STOCK_NAME",
            cancellationToken).ConfigureAwait(false);
        var salesName = await SelectOneAsync(
            traced,
            "SELECTOR_INPUT_SELL",
            "SELECT STOCK_NAME FROM INPUT_SELL WHERE STOCK_NAME IS NOT NULL AND ROWNUM = 1",
            "STOCK_NAME",
            cancellationToken).ConfigureAwait(false);
        var nxtStockCode = await SelectOneAsync(
            traced,
            DataSourceKind.MariaDb,
            "SELECTOR_NXT_STOCK",
            """
            SELECT a.f_stock_code STOCK_CODE
            FROM n_online a
            JOIN n_stock b ON a.f_stock_code = b.f_stock_code
            JOIN n_batch_his c ON a.f_stock_code = c.f_stock_code
            WHERE a.f_curr_price <> 0
              AND c.f_data_day = (
                  SELECT MAX(h.f_data_day)
                  FROM n_batch_his h
                  WHERE h.f_stock_code = a.f_stock_code)
            LIMIT 1
            """,
            "STOCK_CODE",
            cancellationToken).ConfigureAwait(false);
        var domesticStock = await SelectStockAsync(
            traced,
            "SELECTOR_DOMESTIC_STOCK",
            """
            SELECT STOCK_CODE, STOCK_NAME
            FROM (
                SELECT a.f_stock_code STOCK_CODE, b.f_stock_wanname STOCK_NAME
                FROM t_online1 a
                JOIN t_stock b ON a.f_stock_code = b.f_stock_code
                WHERE a.f_curr_price <> 0
                  AND b.f_mkt_halt = 'N'
                  AND b.f_stock_wanname IS NOT NULL
                ORDER BY a.f_stock_code
            )
            WHERE ROWNUM = 1
            """,
            cancellationToken).ConfigureAwait(false);
        var themeIdentity = await SelectStockAsync(
            traced,
            "SELECTOR_THEME_IDENTITY",
            """
            SELECT STOCK_CODE, STOCK_NAME
            FROM (
                SELECT l.SB_CODE STOCK_CODE, l.SB_TITLE STOCK_NAME
                FROM SB_LIST l
                WHERE l.SB_MARKET = 'KRX'
                  AND l.SB_TITLE IS NOT NULL
                  AND l.SB_TITLE = TRIM(l.SB_TITLE)
                  AND LENGTH(l.SB_TITLE) BETWEEN 1 AND 128
                  AND REGEXP_LIKE(l.SB_CODE, '^[0-9]{3,8}$', 'c')
                  AND (SELECT COUNT(*) FROM SB_LIST d
                       WHERE d.SB_MARKET = l.SB_MARKET
                         AND d.SB_TITLE = l.SB_TITLE) = 1
                  AND (SELECT COUNT(*) FROM SB_LIST d
                       WHERE d.SB_MARKET = l.SB_MARKET
                         AND d.SB_CODE = l.SB_CODE) = 1
                  AND EXISTS (SELECT 1 FROM SB_ITEM i WHERE i.SB_M_CODE = l.SB_CODE)
                ORDER BY l.SB_CODE
            )
            WHERE ROWNUM = 1
            """,
            cancellationToken).ConfigureAwait(false);
        var nxtThemeIdentity = await SelectIdentityAsync(
            traced,
            DataSourceKind.MariaDb,
            "SELECTOR_NXT_THEME_IDENTITY",
            """
            SELECT l.SB_CODE STOCK_CODE, l.SB_TITLE STOCK_NAME
            FROM SB_LIST l
            WHERE l.SB_MARKET = 'NXT'
              AND l.SB_TITLE IS NOT NULL
              AND BINARY l.SB_TITLE = BINARY TRIM(l.SB_TITLE)
              AND CHAR_LENGTH(l.SB_TITLE) BETWEEN 1 AND 128
              AND l.SB_CODE REGEXP BINARY '^[0-9]{3,8}$'
              AND (SELECT COUNT(*) FROM SB_LIST d
                   WHERE d.SB_MARKET = l.SB_MARKET
                     AND BINARY d.SB_TITLE = BINARY l.SB_TITLE) = 1
              AND (SELECT COUNT(*) FROM SB_LIST d
                   WHERE d.SB_MARKET = l.SB_MARKET
                     AND BINARY d.SB_CODE = BINARY l.SB_CODE) = 1
              AND EXISTS (
                  SELECT 1
                  FROM SB_ITEM i
                  JOIN v_all_stock b
                    ON SUBSTRING(i.SB_I_CODE, 2, 12) = b.f_stock_code
                  WHERE i.SB_M_CODE = l.SB_CODE
                    AND b.f_stop_gubun = 'N'
                    AND b.f_curr_price != 0)
            ORDER BY l.SB_CODE
            LIMIT 1
            """,
            cancellationToken).ConfigureAwait(false);
        var comparisonNames = await SelectManyAsync(
            traced,
            "SELECTOR_COMPARISON_STOCKS",
            """
            SELECT STOCK_CODE || CHR(31) || STOCK_NAME STOCK_IDENTITY
            FROM (
                SELECT b.f_stock_code STOCK_CODE, b.f_stock_wanname STOCK_NAME
                FROM t_online1 a
                JOIN t_stock b ON a.f_stock_code = b.f_stock_code
                WHERE a.f_curr_price <> 0
                  AND b.f_mkt_halt = 'N'
                  AND b.f_stock_wanname IS NOT NULL
                  AND EXISTS (
                      SELECT 1
                      FROM t_candle_history h
                      WHERE h.f_stock_code = a.f_stock_code)
                ORDER BY a.f_stock_code
            )
            WHERE ROWNUM <= 2
            """,
            "STOCK_IDENTITY",
            maximumRows: 2,
            cancellationToken).ConfigureAwait(false);
        var dealerStockName = await SelectOneAsync(
            traced,
            "SELECTOR_DEALER_STOCK",
            """
            SELECT STOCK_NAME
            FROM (
                SELECT b.f_stock_wanname STOCK_NAME
                FROM t_online1 a
                JOIN t_stock b ON a.f_stock_code = b.f_stock_code
                JOIN t_dealer d ON a.f_stock_code = d.f_stock_code
                WHERE a.f_curr_price <> 0
                  AND b.f_mkt_halt = 'N'
                  AND d.f_buy_dealer_no_1 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_buy_dealer_no_2 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_buy_dealer_no_3 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_buy_dealer_no_4 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_buy_dealer_no_5 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_sell_dealer_no_1 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_sell_dealer_no_2 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_sell_dealer_no_3 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_sell_dealer_no_4 IN (SELECT f_sale_no FROM t_sale_member)
                  AND d.f_sell_dealer_no_5 IN (SELECT f_sale_no FROM t_sale_member)
                ORDER BY a.f_stock_code
            )
            WHERE ROWNUM = 1
            """,
            "STOCK_NAME",
            cancellationToken).ConfigureAwait(false);
        var orderBookStockCode = await SelectOneAsync(
            traced,
            "SELECTOR_ORDER_BOOK_STOCK",
            """
            SELECT STOCK_CODE
            FROM (
                SELECT a.f_stock_code STOCK_CODE
                FROM t_online1 a
                JOIN t_stock b ON a.f_stock_code = b.f_stock_code
                JOIN t_online1_call c ON a.f_stock_code = c.f_stock_code
                WHERE a.f_curr_price > 0
                  AND b.f_mkt_halt = 'N'
                  AND c.f_call_sell_1 IS NOT NULL
                  AND c.f_call_sell_2 IS NOT NULL
                  AND c.f_call_sell_3 IS NOT NULL
                  AND c.f_call_sell_jan_1 IS NOT NULL
                  AND c.f_call_sell_jan_2 IS NOT NULL
                  AND c.f_call_sell_jan_3 IS NOT NULL
                  AND c.f_call_buy_1 IS NOT NULL
                  AND c.f_call_buy_2 IS NOT NULL
                  AND c.f_call_buy_3 IS NOT NULL
                  AND c.f_call_buy_jan_1 IS NOT NULL
                  AND c.f_call_buy_jan_2 IS NOT NULL
                  AND c.f_call_buy_jan_3 IS NOT NULL
                  AND c.f_t_call_sell_jan IS NOT NULL
                  AND c.f_t_call_buy_jan IS NOT NULL
                ORDER BY a.f_stock_code
            )
            WHERE ROWNUM = 1
            """,
            "STOCK_CODE",
            cancellationToken).ConfigureAwait(false);

        var domesticCode = domesticStock?.Code;
        var pageRequest = new DomesticPagedQuoteLoadRequest(
            PagedQuoteMarket.Kospi,
            DomesticPagedQuoteList.MarketCapitalization,
            DateOnly.FromDateTime(DateTime.Today));

        await run.RequiredAsync(
            "s5001",
            "Oracle/BalticDryIndex",
            () => new S5001SceneDataLoader(traced).LoadAsync(
                new S5001BalticDryIndexLoadRequest(), cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5006",
            "Oracle/domestic",
            () => new S5006DomesticSceneDataLoader(traced).LoadAsync(
                new S5006DomesticSceneDataRequest(
                    LegacyDomesticEquityMarket.Kospi,
                    RequireSelector(domesticCode, "domestic stock code")),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5006",
            "MariaDb/NXT",
            () => new S5006NxtSceneDataLoader(traced).LoadAsync(
                LegacyDomesticEquityMarket.NxtKospi,
                RequireSelector(nxtStockCode, "NXT stock code"),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5011",
            "Oracle/face-value",
            () => new S5011SceneDataLoader(traced).LoadAsync(
                new S5011SceneDataRequest(
                    LegacyDomesticEquityMarket.Kospi,
                    S5011DetailBranch.FaceValue,
                    RequireSelector(domesticCode, "domestic stock code")),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5016",
            "Oracle/US-indices",
            () => new S5016SceneDataLoader(traced).LoadAsync(
                S5016PanelTarget.UnitedStatesIndices,
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s50160",
            "Oracle/cotton",
            () => new S50160SceneDataLoader(traced).LoadAsync(
                S50160PanelTarget.Cotton,
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5023",
            "Oracle/Kospi",
            () => new S5023SceneDataLoader(traced).LoadAsync(
                new S5023SceneLoadRequest(LegacyDomesticMarket.Kospi),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5024",
            "Oracle/Kospi",
            () => new S5024SceneDataLoader(traced).LoadAsync(
                new S5024SceneLoadRequest(LegacyDomesticMarket.Kospi),
                cancellationToken)).ConfigureAwait(false);

        var manualDirectory = Environment.GetEnvironmentVariable(
            S5025TrustedManualFileDataSource.DirectoryEnvironmentVariable);
        var manualConfigured = !string.IsNullOrWhiteSpace(manualDirectory);
        if (manualConfigured)
        {
            await run.RequiredAsync(
                "s5025",
                "trusted-external/manual-individual",
                () => new S5025SceneDataLoader(
                    S5025TrustedManualFileDataSource.CreateFromEnvironment()).LoadAsync(
                        new S5025ManualSceneLoadRequest(S5025ManualAudience.Individual),
                        cancellationToken)).ConfigureAwait(false);
            await run.RequiredAsync(
                "s5025",
                "trusted-external/manual-foreign",
                () => new S5025SceneDataLoader(
                    S5025TrustedManualFileDataSource.CreateFromEnvironment()).LoadAsync(
                        new S5025ManualSceneLoadRequest(S5025ManualAudience.Foreign),
                        cancellationToken)).ConfigureAwait(false);
            await run.RequiredAsync(
                "s5025",
                "trusted-external/manual-institution",
                () => new S5025SceneDataLoader(
                    S5025TrustedManualFileDataSource.CreateFromEnvironment()).LoadAsync(
                        new S5025ManualSceneLoadRequest(S5025ManualAudience.Institution),
                        cancellationToken)).ConfigureAwait(false);
        }
        else
        {
            Console.WriteLine(
                "SCENE_SMOKE:s5025:PREREQUISITE - trusted external manual-data directory is not configured");
        }

        await run.RequiredAsync(
            "s5026",
            "Oracle/five-day-candle-pair",
            () => new S5026SceneDataLoader(traced).LoadAsync(
                new ComparisonPairSceneLoadRequest(
                    ComparisonGraphPeriod.FiveDays,
                    RequireComparisonSelector(comparisonNames, 0),
                    RequireComparisonSelector(comparisonNames, 1)),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5029",
            "Oracle/five-day-yield-pair",
            () => new S5029SceneDataLoader(traced).LoadAsync(
                new ComparisonPairSceneLoadRequest(
                    ComparisonGraphPeriod.FiveDays,
                    RequireComparisonSelector(comparisonNames, 0),
                    RequireComparisonSelector(comparisonNames, 1)),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5032",
            "Oracle/index-and-futures",
            () => new S5032SceneDataLoader(traced).LoadAsync(
                new S5032IndexAndFuturesLoadRequest(LegacyMarketQuoteTarget.Kospi),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5037",
            "Oracle/dealer-quote",
            () => new S5037SceneDataLoader(traced).LoadAsync(
                new S5037SceneLoadRequest(
                    LegacyDomesticMarket.Kospi,
                    RequireSelector(dealerStockName, "dealer stock name")),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5074",
            "Oracle/paged-5",
            () => new S5074SceneDataLoader(traced).LoadAsync(
                pageRequest,
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5074",
            "Oracle/theme-code-title-identity",
            () => new S5074SceneDataLoader(traced).LoadAsync(
                new ThemePagedQuoteLoadRequest(
                    RequireSelector(themeIdentity?.Code, "theme code"),
                    RequireSelector(themeIdentity?.Name, "theme title"),
                    PagedQuoteThemeSort.InputOrder,
                    PagedQuoteThemeValueKind.Current),
                cancellationToken)).ConfigureAwait(false);
        if (nxtThemeIdentity is null)
        {
            Console.WriteLine(
                "SCENE_SMOKE:s5074:PREREQUISITE - no NXT theme currently has an eligible live quote");
        }
        else
        {
            await run.RequiredAsync(
                "s5074",
                "MariaDb/NXT-theme-code-title-identity",
                () => new S5074SceneDataLoader(traced).LoadAsync(
                    new NxtThemePagedQuoteLoadRequest(
                        nxtThemeIdentity.Code,
                        nxtThemeIdentity.Name + "(NXT)",
                        PagedQuoteThemeSort.InputOrder,
                        DateTime.Now.Hour <= 12
                            ? NxtMarketSession.PreMarket
                            : NxtMarketSession.AfterMarket),
                    cancellationToken)).ConfigureAwait(false);
        }
        await run.RequiredAsync(
            "s5076",
            "Oracle/manual-pie",
            () => new S5076SceneDataLoader(traced).LoadAsync(
                RequireSelector(pieName, "INPUT_PIE stock name"),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5077",
            "Oracle/paged-6",
            () => new S5077SceneDataLoader(traced).LoadAsync(
                pageRequest,
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5078",
            "Oracle/Kospi-sectors",
            () => new S5078SceneDataLoader(traced).LoadAsync(
                new S5078SceneDataRequest(SectorIndexMarket.Kospi),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5079",
            "Oracle/manual-growth",
            () => new S5079SceneDataLoader(traced).LoadAsync(
                new S5079SceneDataRequest(RequireSelector(growthName, "INPUT_GROW stock name")),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5080",
            "Oracle/manual-sales",
            () => new S5080SceneDataLoader(traced).LoadAsync(
                new S5080SceneDataRequest(RequireSelector(salesName, "INPUT_SELL stock name")),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5081",
            "Oracle/manual-profit",
            () => new S5081SceneDataLoader(traced).LoadAsync(
                RequireSelector(profitName, "INPUT_PROFIT stock name"),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5082",
            "Oracle/grid",
            () => new S5082SceneDataLoader(traced).LoadAsync(cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5083",
            "Oracle/investor-flow",
            () => new S5083SceneDataLoader(traced).LoadAsync(
                new S5083SceneDataRequest(InvestorFlowParticipant.Individual),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5084",
            "Oracle/index-flow",
            () => new S5084SceneDataLoader(traced).LoadAsync(
                new S5084SceneDataRequest(InvestorFlowIndex.Kospi),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5085",
            "Oracle/program-trading",
            () => new S5085SceneDataLoader(traced).LoadAsync(cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5086",
            "Oracle/five-day-FX-yield",
            () => new S5086SceneDataLoader(traced).LoadAsync(
                new YieldSceneLoadRequest(
                    YieldGraphPeriod.FiveDays,
                    new YieldGraphInstrument(YieldGraphInstrumentKind.WonDollar)),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s50860",
            "Oracle/five-day-quoted-FX-yield",
            () => new S50860SceneDataLoader(traced).LoadAsync(
                new YieldSceneLoadRequest(
                    YieldGraphPeriod.FiveDays,
                    new YieldGraphInstrument(YieldGraphInstrumentKind.WonDollar)),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5087",
            "Oracle/five-day-comparison",
            () => new S5087SceneDataLoader(traced).LoadAsync(
                new ComparisonPairSceneLoadRequest(
                    ComparisonGraphPeriod.FiveDays,
                    RequireComparisonSelector(comparisonNames, 0),
                    RequireComparisonSelector(comparisonNames, 1)),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s5088",
            "Oracle/paged-12",
            () => new S5088SceneDataLoader(traced).LoadAsync(
                pageRequest,
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s6001",
            "Oracle/DowJones",
            () => new S6001SceneDataLoader(traced).LoadAsync(
                S6001QuoteTarget.DowJones,
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s6067",
            "Oracle/institution-grid",
            () => new S6067SceneDataLoader(traced).LoadAsync(cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s8001",
            "Oracle/Kospi-sector-map",
            () => new S8001SceneDataLoader(traced).LoadAsync(
                new S8001SceneLoadRequest(S8001Market.Kospi),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s8003",
            "Oracle/order-book",
            () => new S8003SceneDataLoader(traced).LoadAsync(
                new S8003SceneLoadRequest(
                    LegacyDomesticMarket.Kospi,
                    RequireSelector(orderBookStockCode, "order-book stock code")),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s8010",
            "Oracle/Kospi-index-candle",
            () => new S8010SceneDataLoader(traced).LoadAsync(
                new S8010SceneDataRequest(
                    CandleCutAlias.Cut8061,
                    CandleMarketTarget.KospiIndex,
                    CandleChartMode.Price,
                    InstrumentName: null,
                    ShowMovingAverage5: false,
                    ShowMovingAverage20: false),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s8018",
            "Oracle/current-market-pair",
            () => new S8018SceneDataLoader(traced).LoadAsync(
                new S8018MarketPairLoadRequest(
                    S8018MarketDataMode.Current,
                    LegacyMarketQuoteTarget.Kospi,
                    LegacyMarketQuoteTarget.Kosdaq),
                cancellationToken)).ConfigureAwait(false);
        await run.RequiredAsync(
            "s8067",
            "Oracle/world-map",
            () => new S8067SceneDataLoader(traced).LoadAsync(cancellationToken)).ConfigureAwait(false);

        await run.DiagnosticAsync(
            "s8086",
            "Oracle/unreachable-no-cut-alias",
            () => new S8086DiagnosticSceneDataLoader(traced).LoadAsync(
                S8086DiagnosticTarget.Gold,
                cancellationToken)).ConfigureAwait(false);

        run.Complete(manualConfigured);
    }

    private static async Task<string?> SelectOneAsync(
        IDataQueryExecutor executor,
        string tableName,
        string sql,
        string column,
        CancellationToken cancellationToken) =>
        await SelectOneAsync(
            executor,
            DataSourceKind.Oracle,
            tableName,
            sql,
            column,
            cancellationToken).ConfigureAwait(false);

    private static async Task<string?> SelectOneAsync(
        IDataQueryExecutor executor,
        DataSourceKind source,
        string tableName,
        string sql,
        string column,
        CancellationToken cancellationToken)
    {
        try
        {
            var table = await executor.ExecuteAsync(
                source,
                tableName,
                new DataQuerySpec(sql),
                cancellationToken).ConfigureAwait(false);
            var value = table.Rows.Count == 1 && table.Columns.Contains(column)
                ? Convert.ToString(table.Rows[0][column], CultureInfo.InvariantCulture)?.Trim()
                : null;
            Console.WriteLine(
                string.IsNullOrEmpty(value)
                    ? $"DB_SMOKE_SELECTOR:{tableName}:NO_ELIGIBLE_ROW"
                    : $"DB_SMOKE_SELECTOR:{tableName}:PASS");
            return string.IsNullOrEmpty(value) ? null : value;
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            throw;
        }
        catch (Exception exception)
        {
            Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:FAIL:{SafeFailure(exception)}");
            return null;
        }
    }

    private static async Task<StockSelector?> SelectStockAsync(
        IDataQueryExecutor executor,
        string tableName,
        string sql,
        CancellationToken cancellationToken) =>
        await SelectIdentityAsync(
            executor,
            DataSourceKind.Oracle,
            tableName,
            sql,
            cancellationToken).ConfigureAwait(false);

    private static async Task<StockSelector?> SelectIdentityAsync(
        IDataQueryExecutor executor,
        DataSourceKind source,
        string tableName,
        string sql,
        CancellationToken cancellationToken)
    {
        try
        {
            var table = await executor.ExecuteAsync(
                source,
                tableName,
                new DataQuerySpec(sql),
                cancellationToken).ConfigureAwait(false);
            if (table.Rows.Count != 1 ||
                !table.Columns.Contains("STOCK_CODE") ||
                !table.Columns.Contains("STOCK_NAME"))
            {
                Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:NO_ELIGIBLE_ROW");
                return null;
            }

            var code = Convert.ToString(table.Rows[0]["STOCK_CODE"], CultureInfo.InvariantCulture)?.Trim();
            var name = Convert.ToString(table.Rows[0]["STOCK_NAME"], CultureInfo.InvariantCulture)?.Trim();
            if (string.IsNullOrEmpty(code) || string.IsNullOrEmpty(name))
            {
                Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:NO_ELIGIBLE_ROW");
                return null;
            }

            Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:PASS");
            return new StockSelector(code, name);
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            throw;
        }
        catch (Exception exception)
        {
            Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:FAIL:{SafeFailure(exception)}");
            return null;
        }
    }

    private static async Task<IReadOnlyList<string>> SelectManyAsync(
        IDataQueryExecutor executor,
        string tableName,
        string sql,
        string column,
        int maximumRows,
        CancellationToken cancellationToken)
    {
        try
        {
            var table = await executor.ExecuteAsync(
                DataSourceKind.Oracle,
                tableName,
                new DataQuerySpec(sql),
                cancellationToken).ConfigureAwait(false);
            if (!table.Columns.Contains(column) || table.Rows.Count > maximumRows)
            {
                Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:INVALID_RESULT");
                return [];
            }

            var values = table.Rows.Cast<DataRow>()
                .Select(row => Convert.ToString(row[column], CultureInfo.InvariantCulture)?.Trim())
                .Where(value => !string.IsNullOrEmpty(value))
                .Cast<string>()
                .Distinct(StringComparer.Ordinal)
                .ToArray();
            Console.WriteLine(
                values.Length == 0
                    ? $"DB_SMOKE_SELECTOR:{tableName}:NO_ELIGIBLE_ROW"
                    : $"DB_SMOKE_SELECTOR:{tableName}:PASS:{values.Length.ToString(CultureInfo.InvariantCulture)}");
            return values;
        }
        catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
        {
            throw;
        }
        catch (Exception exception)
        {
            Console.WriteLine($"DB_SMOKE_SELECTOR:{tableName}:FAIL:{SafeFailure(exception)}");
            return [];
        }
    }

    private static string RequireSelector(string? value, string selector)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            throw new LegacySceneDataException(
                $"The {selector} selector returned no eligible database row.");
        }

        return value;
    }

    private static ComparisonStockSelection RequireComparisonSelector(
        IReadOnlyList<string> values,
        int index)
    {
        if (values.Count != 2 || index is < 0 or > 1)
        {
            _ = RequireSelector(null, "comparison stock pair");
        }

        var parts = values[index].Split('\u001f');
        if (parts.Length != 2)
        {
            _ = RequireSelector(null, "comparison stock identity");
        }

        return new ComparisonStockSelection(
            ComparisonEquityMarket.Kospi,
            parts[1],
            parts[0]);
    }

    private static string SafeFailure(Exception exception) => exception switch
    {
        LegacySceneDataException => "DATA_UNAVAILABLE_OR_INVALID",
        DatabaseOperationException operation when operation.ProviderErrorCode.HasValue =>
            "DATABASE_QUERY_FAILED_CODE_" +
            operation.ProviderErrorCode.Value.ToString(CultureInfo.InvariantCulture),
        DatabaseInfrastructureException => "DATABASE_QUERY_FAILED",
        S5025TrustedManualDataException => "TRUSTED_MANUAL_DATA_UNAVAILABLE",
        _ => exception.GetType().Name.ToUpperInvariant()
    };

    private sealed record StockSelector(string Code, string Name);

    private sealed class SceneSmokeRun
    {
        private readonly HashSet<string> _covered = new(StringComparer.Ordinal);
        private readonly List<string> _requiredFailures = [];

        public async Task RequiredAsync<TData>(
            string builderKey,
            string caseName,
            Func<Task<TData>> loadAsync)
            where TData : ILegacySceneData =>
            await VerifyAsync(builderKey, caseName, loadAsync, required: true).ConfigureAwait(false);

        public async Task DiagnosticAsync<TData>(
            string builderKey,
            string caseName,
            Func<Task<TData>> loadAsync)
            where TData : ILegacySceneData =>
            await VerifyAsync(builderKey, caseName, loadAsync, required: false).ConfigureAwait(false);

        public void Complete(bool manualConfigured)
        {
            var expected = LegacySceneMutationBuilderRegistry.Default.Registrations
                .Select(registration => registration.BuilderKey)
                .Where(key => !string.Equals(key, "s8086", StringComparison.Ordinal))
                .Where(key => manualConfigured || !string.Equals(key, "s5025", StringComparison.Ordinal))
                .ToHashSet(StringComparer.Ordinal);
            var missing = expected.Except(_covered, StringComparer.Ordinal)
                .OrderBy(key => key, StringComparer.Ordinal)
                .ToArray();
            var requiredCovered = expected.Count(_covered.Contains);
            var diagnosticStatus = _covered.Contains("s8086")
                ? "pass-unreachable-no-cut-alias"
                : "failed-unreachable-no-cut-alias";

            Console.WriteLine(
                $"SCENE_SMOKE_SUMMARY: requiredCovered={requiredCovered.ToString(CultureInfo.InvariantCulture)} " +
                $"required={expected.Count.ToString(CultureInfo.InvariantCulture)} " +
                $"requiredFailures={_requiredFailures.Count.ToString(CultureInfo.InvariantCulture)} " +
                $"diagnostic={diagnosticStatus} " +
                $"manualS5025={(manualConfigured ? "configured" : "prerequisite")}");
            if (missing.Length > 0)
            {
                Console.WriteLine("SCENE_SMOKE_MISSING: " + string.Join(",", missing));
            }

            if (_requiredFailures.Count > 0 || missing.Length > 0)
            {
                throw new DatabaseConfigurationException(
                    "One or more required real-data scene loader cases did not produce validated mutations.");
            }
        }

        private async Task VerifyAsync<TData>(
            string builderKey,
            string caseName,
            Func<Task<TData>> loadAsync,
            bool required)
            where TData : ILegacySceneData
        {
            Console.WriteLine($"SCENE_SMOKE:{builderKey}:{caseName}:START");
            try
            {
                var data = await loadAsync().ConfigureAwait(false);
                var mutations = LegacySceneMutationBuilderRegistry.Default.Build(builderKey, data);
                if (mutations.Count == 0)
                {
                    throw new LegacySceneDataException(
                        "The scene mutation builder produced no mutations.");
                }

                _covered.Add(builderKey);
                Console.WriteLine(
                    $"SCENE_SMOKE:{builderKey}:{caseName}:PASS:" +
                    mutations.Count.ToString(CultureInfo.InvariantCulture));
            }
            catch (OperationCanceledException)
            {
                throw;
            }
            catch (Exception exception)
            {
                var failure = SafeFailure(exception);
                Console.WriteLine($"SCENE_SMOKE:{builderKey}:{caseName}:FAIL:{failure}");
                if (required)
                {
                    _requiredFailures.Add(builderKey + "/" + caseName);
                }
            }
        }
    }

    private sealed class QueryTracingDataQueryExecutor : IDataQueryExecutor
    {
        private readonly IDataQueryExecutor _inner;
        private int _sequence;

        public QueryTracingDataQueryExecutor(IDataQueryExecutor inner)
        {
            _inner = inner ?? throw new ArgumentNullException(nameof(inner));
        }

        public DataTable Execute(DataSourceKind source, string tableName, string query)
        {
            var sequence = Start(source, tableName);
            try
            {
                var result = _inner.Execute(source, tableName, query);
                End(sequence, result);
                return result;
            }
            catch (Exception exception)
            {
                Fail(sequence, exception);
                throw;
            }
        }

        public async Task<DataTable> ExecuteAsync(
            DataSourceKind source,
            string tableName,
            string query,
            CancellationToken cancellationToken = default)
        {
            var sequence = Start(source, tableName);
            try
            {
                var result = await _inner.ExecuteAsync(
                    source,
                    tableName,
                    query,
                    cancellationToken).ConfigureAwait(false);
                End(sequence, result);
                return result;
            }
            catch (Exception exception)
            {
                Fail(sequence, exception);
                throw;
            }
        }

        public async Task<DataTable> ExecuteAsync(
            DataSourceKind source,
            string tableName,
            DataQuerySpec query,
            CancellationToken cancellationToken = default)
        {
            var sequence = Start(source, tableName);
            try
            {
                var result = await _inner.ExecuteAsync(
                    source,
                    tableName,
                    query,
                    cancellationToken).ConfigureAwait(false);
                End(sequence, result);
                return result;
            }
            catch (Exception exception)
            {
                Fail(sequence, exception);
                throw;
            }
        }

        private int Start(DataSourceKind source, string tableName)
        {
            var sequence = Interlocked.Increment(ref _sequence);
            Console.WriteLine(
                $"DB_SMOKE_QUERY:{sequence.ToString(CultureInfo.InvariantCulture)}:" +
                $"START:{source}:{tableName}");
            return sequence;
        }

        private static void End(int sequence, DataTable result) =>
            Console.WriteLine(
                $"DB_SMOKE_QUERY:{sequence.ToString(CultureInfo.InvariantCulture)}:" +
                $"PASS:rows={result.Rows.Count.ToString(CultureInfo.InvariantCulture)}");

        private static void Fail(int sequence, Exception exception) =>
            Console.WriteLine(
                $"DB_SMOKE_QUERY:{sequence.ToString(CultureInfo.InvariantCulture)}:" +
                $"FAIL:{SafeFailure(exception)}");
    }
}
