// file: kb_lib/src/dex_support_matrix.rs

//! Shared DEX support matrix.
//!
//! This module centralizes protocol metadata that was previously duplicated
//! across catalog, transaction classification, candidate recording and roadmap
//! surfaces. It intentionally does not decode instructions and does not decide
//! whether one decoded event is actionable.

/// Support matrix entry for one DEX, router, aggregator or launch surface.
#[derive(Debug, Copy, Clone, Eq, PartialEq, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct DexSupportMatrixEntry {
    /// Stable internal protocol or surface code.
    pub code: &'static str,
    /// Human-readable protocol or surface name.
    pub display_name: &'static str,
    /// Protocol family, for example `raydium`, `meteora` or `pump`.
    pub family: &'static str,
    /// Protocol version or `unknown` when not verified locally.
    pub version: &'static str,
    /// Surface type: `launch`, `bonding_curve`, `AMM`, `CLMM`, `DLMM`, `router`, `aggregator` or `unknown`.
    pub surface_type: &'static str,
    /// Primary Solana program id, when verified in local constants or docs.
    pub program_id: std::option::Option<&'static str>,
    /// Optional router program id, when this entry uses a distinct router.
    pub router_program_id: std::option::Option<&'static str>,
    /// Program id confidence: `known`, `to_verify` or `unknown`.
    pub program_id_status: &'static str,
    /// Whether this protocol has been observed in the local replay corpus.
    pub observed: bool,
    /// Whether the code currently contains a decoder for this protocol.
    pub decoded: bool,
    /// Whether decoded events are currently materialized beyond raw decoded rows.
    pub materialized: bool,
    /// Whether this protocol can currently produce trade candidates.
    pub trade_candidate: bool,
    /// Whether this protocol can currently produce candle candidates.
    pub candle_candidate: bool,
    /// Whether this protocol can currently produce pair candidates.
    pub pair_candidate: bool,
    /// Whether this protocol can currently produce pool candidates.
    pub pool_candidate: bool,
    /// Operational support status: `supported`, `partial`, `planned`, `ignored`, `to_verify` or `unknown`.
    pub status: &'static str,
    /// Confidence level attached to this matrix entry.
    pub confidence: &'static str,
    /// Optional explicit skip reason for partial or ignored entries.
    pub skip_reason: std::option::Option<&'static str>,
    /// Whether the entry should be inserted as an enabled DEX in the storage catalog.
    pub catalog_enabled: bool,
}

/// Owned DTO form of a DEX support matrix entry.
#[derive(Debug, Clone, Eq, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(rename_all = "camelCase")]
pub struct DexSupportMatrixEntryDto {
    /// Stable internal protocol or surface code.
    pub code: std::string::String,
    /// Human-readable protocol or surface name.
    pub display_name: std::string::String,
    /// Protocol family, for example `raydium`, `meteora` or `pump`.
    pub family: std::string::String,
    /// Protocol version or `unknown` when not verified locally.
    pub version: std::string::String,
    /// Surface type: `launch`, `bonding_curve`, `AMM`, `CLMM`, `DLMM`, `router`, `aggregator` or `unknown`.
    pub surface_type: std::string::String,
    /// Primary Solana program id, when verified in local constants or docs.
    pub program_id: std::option::Option<std::string::String>,
    /// Optional router program id, when this entry uses a distinct router.
    pub router_program_id: std::option::Option<std::string::String>,
    /// Program id confidence: `known`, `to_verify` or `unknown`.
    pub program_id_status: std::string::String,
    /// Whether this protocol has been observed in the local replay corpus.
    pub observed: bool,
    /// Whether the code currently contains a decoder for this protocol.
    pub decoded: bool,
    /// Whether decoded events are currently materialized beyond raw decoded rows.
    pub materialized: bool,
    /// Whether this protocol can currently produce trade candidates.
    pub trade_candidate: bool,
    /// Whether this protocol can currently produce candle candidates.
    pub candle_candidate: bool,
    /// Whether this protocol can currently produce pair candidates.
    pub pair_candidate: bool,
    /// Whether this protocol can currently produce pool candidates.
    pub pool_candidate: bool,
    /// Operational support status: `supported`, `partial`, `planned`, `ignored`, `to_verify` or `unknown`.
    pub status: std::string::String,
    /// Confidence level attached to this matrix entry.
    pub confidence: std::string::String,
    /// Optional explicit skip reason for partial or ignored entries.
    pub skip_reason: std::option::Option<std::string::String>,
    /// Whether the entry should be inserted as an enabled DEX in the storage catalog.
    pub catalog_enabled: bool,
}

impl DexSupportMatrixEntryDto {
    /// Builds an owned DTO from one static support matrix entry.
    pub fn from_entry(entry: &crate::DexSupportMatrixEntry) -> Self {
        return Self {
            code: entry.code.to_string(),
            display_name: entry.display_name.to_string(),
            family: entry.family.to_string(),
            version: entry.version.to_string(),
            surface_type: entry.surface_type.to_string(),
            program_id: match entry.program_id {
                Some(program_id) => Some(program_id.to_string()),
                None => None,
            },
            router_program_id: match entry.router_program_id {
                Some(router_program_id) => Some(router_program_id.to_string()),
                None => None,
            },
            program_id_status: entry.program_id_status.to_string(),
            observed: entry.observed,
            decoded: entry.decoded,
            materialized: entry.materialized,
            trade_candidate: entry.trade_candidate,
            candle_candidate: entry.candle_candidate,
            pair_candidate: entry.pair_candidate,
            pool_candidate: entry.pool_candidate,
            status: entry.status.to_string(),
            confidence: entry.confidence.to_string(),
            skip_reason: match entry.skip_reason {
                Some(skip_reason) => Some(skip_reason.to_string()),
                None => None,
            },
            catalog_enabled: entry.catalog_enabled,
        };
    }
}

const DEX_SUPPORT_MATRIX_ENTRIES: &[DexSupportMatrixEntry] = &[
    DexSupportMatrixEntry {
        code: "pump_fun",
        display_name: "Pump.fun",
        family: "pump",
        version: "bonding_curve",
        surface_type: "launch",
        program_id: Some(crate::PUMP_FUN_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "high",
        skip_reason: Some("launch_surface_requires_migration_linking_before_live_trading"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "pump_swap",
        display_name: "PumpSwap",
        family: "pump",
        version: "amm",
        surface_type: "AMM",
        program_id: Some(crate::PUMP_SWAP_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: true,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "supported",
        confidence: "high",
        skip_reason: None,
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "raydium_cpmm",
        display_name: "Raydium CPMM",
        family: "raydium",
        version: "cpmm",
        surface_type: "AMM",
        program_id: Some(crate::RAYDIUM_CPMM_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: true,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "supported",
        confidence: "high",
        skip_reason: None,
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "raydium_clmm",
        display_name: "Raydium CLMM",
        family: "raydium",
        version: "clmm",
        surface_type: "CLMM",
        program_id: Some(crate::RAYDIUM_CLMM_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: true,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "supported",
        confidence: "high",
        skip_reason: None,
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "raydium_amm_v4",
        display_name: "Raydium AMM v4",
        family: "raydium",
        version: "amm_v4",
        surface_type: "AMM",
        program_id: Some(crate::RAYDIUM_AMM_V4_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("not_observed_in_0_7_28_replay"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "raydium",
        display_name: "Raydium AMM v4",
        family: "raydium",
        version: "amm_v4_alias",
        surface_type: "AMM",
        program_id: Some(crate::RAYDIUM_AMM_V4_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("legacy_catalog_alias_for_raydium_amm_v4"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "raydium_launchlab",
        display_name: "Raydium LaunchLab",
        family: "raydium",
        version: "launchlab",
        surface_type: "launch",
        program_id: Some(crate::RAYDIUM_LAUNCHLAB_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "medium",
        skip_reason: Some("decoder_and_materialization_not_enabled"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "raydium_launchpad",
        display_name: "Raydium Launchpad",
        family: "raydium",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "to_verify",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "to_verify",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "raydium_router",
        display_name: "Raydium Router",
        family: "raydium",
        version: "router",
        surface_type: "router",
        program_id: Some(crate::RAYDIUM_AMM_ROUTING_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: false,
        pool_candidate: false,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("router_not_materialized_as_direct_trade_surface"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "raydium_stable_swap",
        display_name: "Raydium Stable Swap AMM",
        family: "raydium",
        version: "stable_swap",
        surface_type: "AMM",
        program_id: Some(crate::RAYDIUM_STABLE_SWAP_AMM_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: false,
        pool_candidate: false,
        status: "planned",
        confidence: "medium",
        skip_reason: Some("deprecated_program_not_prioritized"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "meteora_dlmm",
        display_name: "Meteora DLMM",
        family: "meteora",
        version: "dlmm",
        surface_type: "DLMM",
        program_id: Some(crate::METEORA_DLMM_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: true,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "supported",
        confidence: "high",
        skip_reason: None,
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "meteora_dlc",
        display_name: "Meteora DLC",
        family: "meteora",
        version: "unknown",
        surface_type: "unknown",
        program_id: None,
        router_program_id: None,
        program_id_status: "to_verify",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: false,
        pool_candidate: false,
        status: "to_verify",
        confidence: "low",
        skip_reason: Some("surface_and_program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "meteora_damm_v1",
        display_name: "Meteora DAMM v1",
        family: "meteora",
        version: "damm_v1",
        surface_type: "AMM",
        program_id: Some(crate::METEORA_DAMM_V1_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: true,
        decoded: true,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("meteora_damm_v1_swap_without_amount_payload"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "meteora_damm_v2",
        display_name: "Meteora DAMM v2",
        family: "meteora",
        version: "damm_v2",
        surface_type: "AMM",
        program_id: Some(crate::METEORA_DAMM_V2_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("not_observed_in_0_7_28_replay"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "meteora_dbc",
        display_name: "Meteora DBC",
        family: "meteora",
        version: "dbc",
        surface_type: "bonding_curve",
        program_id: Some(crate::METEORA_DBC_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("not_observed_in_0_7_28_replay"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "orca_whirlpools",
        display_name: "Orca Whirlpools",
        family: "orca",
        version: "whirlpools",
        surface_type: "CLMM",
        program_id: Some(crate::ORCA_WHIRLPOOLS_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("not_observed_in_0_7_28_replay"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "fluxbeam",
        display_name: "FluxBeam",
        family: "fluxbeam",
        version: "unknown",
        surface_type: "AMM",
        program_id: Some(crate::FLUXBEAM_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("not_observed_in_0_7_28_replay"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "dexlab",
        display_name: "DexLab Swap/Pool",
        family: "dexlab",
        version: "unknown",
        surface_type: "AMM",
        program_id: Some(crate::DEXLAB_PROGRAM_ID),
        router_program_id: None,
        program_id_status: "known",
        observed: false,
        decoded: true,
        materialized: true,
        trade_candidate: true,
        candle_candidate: true,
        pair_candidate: true,
        pool_candidate: true,
        status: "partial",
        confidence: "medium",
        skip_reason: Some("not_observed_in_0_7_28_replay"),
        catalog_enabled: true,
    },
    DexSupportMatrixEntry {
        code: "bags",
        display_name: "Bags",
        family: "bags",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "letsbonk",
        display_name: "LetsBonk / Bonk.fun",
        family: "bonk",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "bonk",
        display_name: "Bonk launch surface",
        family: "bonk",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "okx_dex",
        display_name: "OKX DEX",
        family: "okx",
        version: "unknown",
        surface_type: "aggregator",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: false,
        pool_candidate: false,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "boop_fun",
        display_name: "Boop.fun",
        family: "boop",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "moonshot",
        display_name: "Moonshot",
        family: "moonshot",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "believe",
        display_name: "Believe",
        family: "believe",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "zora",
        display_name: "Zora",
        family: "zora",
        version: "unknown",
        surface_type: "unknown",
        program_id: None,
        router_program_id: None,
        program_id_status: "to_verify",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: false,
        pool_candidate: false,
        status: "to_verify",
        confidence: "low",
        skip_reason: Some("surface_and_program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "moonit",
        display_name: "Moonit",
        family: "moonit",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "launchbeam",
        display_name: "LaunchBeam",
        family: "launchbeam",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
    DexSupportMatrixEntry {
        code: "heaven",
        display_name: "Heaven",
        family: "heaven",
        version: "unknown",
        surface_type: "launch",
        program_id: None,
        router_program_id: None,
        program_id_status: "unknown",
        observed: false,
        decoded: false,
        materialized: false,
        trade_candidate: false,
        candle_candidate: false,
        pair_candidate: true,
        pool_candidate: true,
        status: "planned",
        confidence: "low",
        skip_reason: Some("program_id_to_verify"),
        catalog_enabled: false,
    },
];

/// Returns all static DEX support matrix entries.
pub fn dex_support_matrix_entries() -> &'static [crate::DexSupportMatrixEntry] {
    return DEX_SUPPORT_MATRIX_ENTRIES;
}

/// Returns all DEX support matrix entries as owned DTOs.
pub fn dex_support_matrix_entry_dtos() -> std::vec::Vec<crate::DexSupportMatrixEntryDto> {
    let mut entries = std::vec::Vec::new();
    for entry in crate::dex_support_matrix_entries() {
        entries.push(crate::DexSupportMatrixEntryDto::from_entry(entry));
    }
    return entries;
}

/// Looks up one DEX support matrix entry by internal code.
pub fn dex_support_matrix_entry_by_code(
    code: &str,
) -> std::option::Option<&'static crate::DexSupportMatrixEntry> {
    for entry in crate::dex_support_matrix_entries() {
        if entry.code == code {
            return Some(entry);
        }
    }
    return None;
}

/// Looks up one DEX support matrix entry by primary or router program id.
pub fn dex_support_matrix_entry_by_program_id(
    program_id: &str,
) -> std::option::Option<&'static crate::DexSupportMatrixEntry> {
    for entry in crate::dex_support_matrix_entries() {
        if let Some(entry_program_id) = entry.program_id {
            if entry_program_id == program_id {
                return Some(entry);
            }
        }
        if let Some(entry_router_program_id) = entry.router_program_id {
            if entry_router_program_id == program_id {
                return Some(entry);
            }
        }
    }
    return None;
}

#[cfg(test)]
mod tests {
    #[test]
    fn matrix_contains_required_0_7_29_entries() {
        let codes = [
            "pump_fun",
            "pump_swap",
            "raydium_cpmm",
            "raydium_clmm",
            "raydium_amm_v4",
            "raydium_launchlab",
            "raydium_launchpad",
            "meteora_dlmm",
            "meteora_dlc",
            "meteora_damm_v1",
            "meteora_damm_v2",
            "bags",
            "bonk",
            "okx_dex",
            "boop_fun",
            "moonshot",
            "believe",
            "zora",
            "moonit",
            "launchbeam",
            "heaven",
            "dexlab",
        ];
        for code in codes {
            let entry = crate::dex_support_matrix_entry_by_code(code);
            assert!(entry.is_some(), "missing matrix entry for {}", code);
        }
    }

    #[test]
    fn matrix_does_not_invent_program_ids_for_unverified_planned_surfaces() {
        let codes = [
            "bags",
            "bonk",
            "okx_dex",
            "boop_fun",
            "moonshot",
            "believe",
            "zora",
            "moonit",
            "launchbeam",
            "heaven",
        ];
        for code in codes {
            let entry = match crate::dex_support_matrix_entry_by_code(code) {
                Some(entry) => entry,
                None => panic!("missing matrix entry for {}", code),
            };
            assert!(entry.program_id.is_none(), "{} should not have invented program id", code);
            assert!(!entry.catalog_enabled, "{} should not be enabled before verification", code);
        }
    }

    #[test]
    fn matrix_lookup_by_program_id_returns_expected_protocol() {
        let entry = match crate::dex_support_matrix_entry_by_program_id(crate::METEORA_DLMM_PROGRAM_ID)
        {
            Some(entry) => entry,
            None => panic!("expected meteora_dlmm program id lookup"),
        };
        assert_eq!(entry.code, "meteora_dlmm");

        let raydium_entry = match crate::dex_support_matrix_entry_by_program_id(
            crate::RAYDIUM_AMM_V4_PROGRAM_ID,
        ) {
            Some(entry) => entry,
            None => panic!("expected raydium AMM v4 program id lookup"),
        };
        assert_eq!(raydium_entry.code, "raydium_amm_v4");
    }

    #[test]
    fn matrix_marks_partial_meteora_damm_v1_correctly() {
        let entry = match crate::dex_support_matrix_entry_by_code("meteora_damm_v1") {
            Some(entry) => entry,
            None => panic!("expected meteora_damm_v1 matrix entry"),
        };
        assert_eq!(entry.status, "partial");
        assert!(entry.observed);
        assert!(entry.decoded);
        assert!(!entry.trade_candidate);
        assert!(!entry.candle_candidate);
        assert_eq!(entry.skip_reason, Some("meteora_damm_v1_swap_without_amount_payload"));
    }

    #[test]
    fn matrix_marks_launch_surfaces_as_launch_or_bonding_curve() {
        let codes = ["pump_fun", "raydium_launchlab", "bags", "moonshot", "moonit"];
        for code in codes {
            let entry = match crate::dex_support_matrix_entry_by_code(code) {
                Some(entry) => entry,
                None => panic!("missing matrix entry for {}", code),
            };
            assert!(
                entry.surface_type == "launch" || entry.surface_type == "bonding_curve",
                "{} has unexpected surface type {}",
                code,
                entry.surface_type
            );
        }
    }

    #[test]
    fn matrix_dto_preserves_core_fields() {
        let entry = match crate::dex_support_matrix_entry_by_code("pump_swap") {
            Some(entry) => entry,
            None => panic!("expected pump_swap matrix entry"),
        };
        let dto = crate::DexSupportMatrixEntryDto::from_entry(entry);
        assert_eq!(dto.code, "pump_swap");
        assert_eq!(dto.program_id, Some(crate::PUMP_SWAP_PROGRAM_ID.to_string()));
        assert!(dto.trade_candidate);
        assert!(dto.candle_candidate);
    }
}
