-- file: validation_sql/SQL_VALIDATION_DEX_COVERAGE_GLOBAL_0_7_53.sql

-- Global DEX coverage watchlist for the 0.7.53 PumpSwap closure.
-- Run after a forced local replay when the goal is to detect:
-- - decoded local events without coverage entries;
-- - upstream_git fallbacks that still need a local decoder or an explicit deferral;
-- - instruction observations not covered by k_sol_dex_event_coverage_entries;
-- - unattributed discriminators that need program-id classification;
-- - PumpSwap/Raydium non-regression after future backfills.

-- 01. Local decoded events without coverage.
-- Expected after 0.7.53 closure: no pump_swap or validated Raydium rows.
-- Known deferred rows at closure time: small Meteora gaps, intentionally not fixed in 0.7.53.
SELECT
    de.protocol_name,
    de.event_kind,
    COUNT(*) AS decoded_count,
    COUNT(DISTINCT de.transaction_id) AS tx_count,
    MIN(tx.signature) AS sample_signature
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_chain_transactions tx
    ON tx.id = de.transaction_id
LEFT JOIN k_sol_dex_event_coverage_entries ce
    ON ce.decoder_code = de.protocol_name
   AND ce.local_event_kind = de.event_kind
WHERE de.protocol_name <> 'upstream_git'
  AND ce.id IS NULL
GROUP BY
    de.protocol_name,
    de.event_kind
ORDER BY
    decoded_count DESC,
    de.protocol_name,
    de.event_kind;

-- 02. Upstream fallback backlog to promote or defer.
-- This is a roadmap queue, not a local decoder error by itself.
SELECT
    json_extract(de.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
    json_extract(de.payload_json, '$.upstreamEntryName') AS upstream_entry_name,
    json_extract(de.payload_json, '$.upstreamDiscriminatorHex') AS upstream_discriminator_hex,
    COUNT(*) AS decoded_count,
    COUNT(DISTINCT de.transaction_id) AS tx_count,
    MIN(tx.signature) AS sample_signature
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_chain_transactions tx
    ON tx.id = de.transaction_id
WHERE de.protocol_name = 'upstream_git'
  AND de.event_kind = 'upstream_git.instruction_match'
GROUP BY
    upstream_decoder_code,
    upstream_entry_name,
    upstream_discriminator_hex
ORDER BY
    decoded_count DESC,
    upstream_decoder_code,
    upstream_entry_name;

-- 03. Instruction observations with decoder_code but no coverage, normalized.
-- Handles both instruction_name='swap_base_input' and instruction_name='raydium_cpmm.swap_base_input'.
WITH normalized_io AS (
    SELECT
        io.decoder_code,
        io.instruction_name,
        CASE
            WHEN io.decoder_code IS NOT NULL
             AND TRIM(io.decoder_code) <> ''
             AND io.instruction_name LIKE (io.decoder_code || '.%')
            THEN SUBSTR(io.instruction_name, LENGTH(io.decoder_code) + 2)
            ELSE io.instruction_name
        END AS normalized_entry_name,
        io.discriminator_hex,
        io.signature
    FROM k_sol_instruction_observations io
    WHERE io.discriminator_hex IS NOT NULL
      AND io.discriminator_hex <> ''
      AND io.discriminator_hex <> 'e445a52e51cb9a1d'
      AND io.decoder_code IS NOT NULL
      AND TRIM(io.decoder_code) <> ''
)
SELECT
    nio.decoder_code,
    nio.instruction_name,
    nio.normalized_entry_name,
    nio.discriminator_hex,
    COUNT(*) AS observed_count,
    COUNT(DISTINCT nio.signature) AS tx_count,
    MIN(nio.signature) AS sample_signature
FROM normalized_io nio
LEFT JOIN k_sol_dex_event_coverage_entries ce
    ON ce.decoder_code = nio.decoder_code
   AND COALESCE(ce.discriminator_hex, '') = COALESCE(nio.discriminator_hex, '')
   AND (
       ce.entry_name = nio.instruction_name
       OR ce.entry_name = nio.normalized_entry_name
       OR ce.local_event_kind = nio.instruction_name
       OR ce.local_event_kind = (nio.decoder_code || '.' || nio.normalized_entry_name)
   )
WHERE ce.id IS NULL
GROUP BY
    nio.decoder_code,
    nio.instruction_name,
    nio.normalized_entry_name,
    nio.discriminator_hex
ORDER BY
    observed_count DESC,
    nio.decoder_code,
    nio.discriminator_hex;

-- 04. Unattributed instruction observations.
-- Treat as classification backlog: discriminator alone is not enough; inspect sample_signature/program_id first.
SELECT
    io.discriminator_hex,
    COUNT(*) AS observed_count,
    COUNT(DISTINCT io.signature) AS tx_count,
    MIN(io.signature) AS sample_signature
FROM k_sol_instruction_observations io
WHERE io.discriminator_hex IS NOT NULL
  AND io.discriminator_hex <> ''
  AND io.discriminator_hex <> 'e445a52e51cb9a1d'
  AND (
      io.decoder_code IS NULL
      OR TRIM(io.decoder_code) = ''
  )
GROUP BY
    io.discriminator_hex
ORDER BY
    observed_count DESC,
    io.discriminator_hex;

-- 05. PumpSwap local closure check.
-- Expected result: empty.
WITH normalized_io AS (
    SELECT
        io.decoder_code,
        io.instruction_name,
        CASE
            WHEN io.instruction_name LIKE 'pump_swap.%'
            THEN SUBSTR(io.instruction_name, LENGTH('pump_swap') + 2)
            ELSE io.instruction_name
        END AS normalized_entry_name,
        io.discriminator_hex,
        io.signature
    FROM k_sol_instruction_observations io
    WHERE io.decoder_code = 'pump_swap'
      AND io.discriminator_hex IS NOT NULL
      AND io.discriminator_hex <> ''
      AND io.discriminator_hex <> 'e445a52e51cb9a1d'
)
SELECT
    nio.decoder_code,
    nio.instruction_name,
    nio.normalized_entry_name,
    nio.discriminator_hex,
    COUNT(*) AS observed_count,
    COUNT(DISTINCT nio.signature) AS tx_count,
    MIN(nio.signature) AS sample_signature
FROM normalized_io nio
LEFT JOIN k_sol_dex_event_coverage_entries ce
    ON ce.decoder_code = 'pump_swap'
   AND COALESCE(ce.discriminator_hex, '') = COALESCE(nio.discriminator_hex, '')
   AND (
       ce.entry_name = nio.instruction_name
       OR ce.entry_name = nio.normalized_entry_name
       OR ce.local_event_kind = nio.instruction_name
       OR ce.local_event_kind = ('pump_swap.' || nio.normalized_entry_name)
   )
WHERE ce.id IS NULL
GROUP BY
    nio.decoder_code,
    nio.instruction_name,
    nio.normalized_entry_name,
    nio.discriminator_hex
ORDER BY observed_count DESC;

-- 06. Raydium AMM v4 / CLMM / CPMM targeted non-regression.
-- Expected result after 0.7.53 closure: empty.
WITH normalized_io AS (
    SELECT
        io.decoder_code,
        io.instruction_name,
        CASE
            WHEN io.decoder_code IS NOT NULL
             AND TRIM(io.decoder_code) <> ''
             AND io.instruction_name LIKE (io.decoder_code || '.%')
            THEN SUBSTR(io.instruction_name, LENGTH(io.decoder_code) + 2)
            ELSE io.instruction_name
        END AS normalized_entry_name,
        io.discriminator_hex,
        io.signature
    FROM k_sol_instruction_observations io
    WHERE io.decoder_code IN (
        'raydium_amm_v4',
        'raydium_clmm',
        'raydium_cpmm'
    )
      AND io.discriminator_hex IS NOT NULL
      AND io.discriminator_hex <> ''
)
SELECT
    nio.decoder_code,
    nio.instruction_name,
    nio.normalized_entry_name,
    nio.discriminator_hex,
    COUNT(*) AS observed_count,
    COUNT(DISTINCT nio.signature) AS tx_count,
    MIN(nio.signature) AS sample_signature
FROM normalized_io nio
LEFT JOIN k_sol_dex_event_coverage_entries ce
    ON ce.decoder_code = nio.decoder_code
   AND COALESCE(ce.discriminator_hex, '') = COALESCE(nio.discriminator_hex, '')
   AND (
       ce.entry_name = nio.instruction_name
       OR ce.entry_name = nio.normalized_entry_name
       OR ce.local_event_kind = nio.instruction_name
       OR ce.local_event_kind = (nio.decoder_code || '.' || nio.normalized_entry_name)
   )
WHERE ce.id IS NULL
GROUP BY
    nio.decoder_code,
    nio.instruction_name,
    nio.normalized_entry_name,
    nio.discriminator_hex
ORDER BY
    observed_count DESC,
    nio.decoder_code,
    nio.discriminator_hex;

-- 07. Raydium swap/trade coverage overview.
-- This is informational. Entries with observed_count=0 are unobserved registry coverage, not failures.
SELECT
    decoder_code,
    entry_kind,
    entry_name,
    event_family,
    local_event_kind,
    discriminator_hex,
    expected_db_target,
    proof_status,
    observed_count,
    materialized_count,
    trade_count
FROM k_sol_dex_event_coverage_entries
WHERE decoder_code IN (
    'raydium_amm_v4',
    'raydium_clmm',
    'raydium_cpmm',
    'raydium_stable_swap',
    'raydium_launchpad'
)
  AND (
      event_family IN ('swap', 'swap_event_audit')
      OR expected_db_target = 'k_sol_trade_events'
  )
ORDER BY
    decoder_code,
    entry_kind,
    entry_name,
    discriminator_hex;

-- 08. Upstream backlog by decoder_code.
SELECT
    json_extract(de.payload_json, '$.upstreamDecoderCode') AS upstream_decoder_code,
    COUNT(*) AS decoded_count,
    COUNT(DISTINCT de.transaction_id) AS tx_count,
    COUNT(DISTINCT json_extract(de.payload_json, '$.upstreamEntryName')) AS distinct_entry_count,
    MIN(tx.signature) AS sample_signature
FROM k_sol_dex_decoded_events de
LEFT JOIN k_sol_chain_transactions tx
    ON tx.id = de.transaction_id
WHERE de.protocol_name = 'upstream_git'
  AND de.event_kind = 'upstream_git.instruction_match'
GROUP BY upstream_decoder_code
ORDER BY decoded_count DESC, upstream_decoder_code;
