// file: kb_lib/src/dex_detection_route.rs

//! Routing from decoded DEX events to business-level detection handlers.

/// Internal route selected for one decoded DEX event.
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub(crate) enum DexDetectionRoute {
    /// Raydium AMM v4 initialize2 pool route.
    RaydiumAmmV4Initialize2Pool,
    /// Raydium AMM v4 trade route.
    RaydiumAmmV4Trade,
    /// Raydium CPMM trade route.
    RaydiumCpmmTrade,
    /// Raydium CLMM trade route.
    RaydiumClmmTrade,
    /// Pump.fun create token route.
    PumpFunCreateV2Token,
    /// Pump.fun trade route.
    PumpFunTrade,
    /// PumpSwap trade route.
    PumpSwapTrade,
    /// Incomplete PumpSwap event route.
    SkipIncompletePumpSwapTrade,
    /// Meteora DBC pool route.
    MeteoraDbcPool,
    /// Meteora DLMM pool route.
    MeteoraDlmmPool,
    /// Meteora DAMM v1 pool route.
    MeteoraDammV1Pool,
    /// Meteora DAMM v2 pool route.
    MeteoraDammV2Pool,
    /// Orca Whirlpools pool route.
    OrcaWhirlpoolsPool,
    /// FluxBeam pool route.
    FluxbeamPool,
    /// DexLab pool route.
    DexlabPool,
}

/// Selects the business-level detection route for one decoded DEX event.
pub(crate) fn dex_detection_route(
    decoded_event: &crate::DexDecodedEventDto,
) -> std::option::Option<crate::dex_detection_route::DexDetectionRoute> {
    match (decoded_event.protocol_name.as_str(), decoded_event.event_kind.as_str()) {
        ("raydium_amm_v4", "raydium_amm_v4.initialize2_pool") => {
            return Some(
                crate::dex_detection_route::DexDetectionRoute::RaydiumAmmV4Initialize2Pool,
            );
        },
        ("raydium_amm_v4", "raydium_amm_v4.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumAmmV4Trade);
        },
        ("raydium_cpmm", "raydium_cpmm.swap_base_input") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumCpmmTrade);
        },
        ("raydium_cpmm", "raydium_cpmm.swap_base_output") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumCpmmTrade);
        },
        ("raydium_clmm", "raydium_clmm.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade);
        },
        ("raydium_clmm", "raydium_clmm.swap_v2") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::RaydiumClmmTrade);
        },
        ("pump_fun", "pump_fun.create_v2_token") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::PumpFunCreateV2Token);
        },
        ("pump_fun", "pump_fun.buy") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::PumpFunTrade);
        },
        ("pump_fun", "pump_fun.sell") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::PumpFunTrade);
        },
        ("pump_swap", "pump_swap.buy") => {
            if crate::dex_detection_route::is_incomplete_pump_swap_decoded_event(decoded_event) {
                return Some(
                    crate::dex_detection_route::DexDetectionRoute::SkipIncompletePumpSwapTrade,
                );
            }
            return Some(crate::dex_detection_route::DexDetectionRoute::PumpSwapTrade);
        },
        ("pump_swap", "pump_swap.sell") => {
            if crate::dex_detection_route::is_incomplete_pump_swap_decoded_event(decoded_event) {
                return Some(
                    crate::dex_detection_route::DexDetectionRoute::SkipIncompletePumpSwapTrade,
                );
            }
            return Some(crate::dex_detection_route::DexDetectionRoute::PumpSwapTrade);
        },
        ("meteora_dbc", "meteora_dbc.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDbcPool);
        },
        ("meteora_dbc", "meteora_dbc.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDbcPool);
        },
        ("meteora_dlmm", "meteora_dlmm.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDlmmPool);
        },
        ("meteora_dlmm", "meteora_dlmm.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDlmmPool);
        },
        ("meteora_damm_v1", "meteora_damm_v1.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDammV1Pool);
        },
        ("meteora_damm_v1", "meteora_damm_v1.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDammV1Pool);
        },
        ("meteora_damm_v2", "meteora_damm_v2.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDammV2Pool);
        },
        ("meteora_damm_v2", "meteora_damm_v2.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::MeteoraDammV2Pool);
        },
        ("orca_whirlpools", "orca_whirlpools.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::OrcaWhirlpoolsPool);
        },
        ("orca_whirlpools", "orca_whirlpools.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::OrcaWhirlpoolsPool);
        },
        ("fluxbeam", "fluxbeam.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::FluxbeamPool);
        },
        ("fluxbeam", "fluxbeam.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::FluxbeamPool);
        },
        ("dexlab", "dexlab.create_pool") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::DexlabPool);
        },
        ("dexlab", "dexlab.swap") => {
            return Some(crate::dex_detection_route::DexDetectionRoute::DexlabPool);
        },
        _ => return None,
    }
}

fn is_incomplete_pump_swap_decoded_event(decoded_event: &crate::DexDecodedEventDto) -> bool {
    if decoded_event.pool_account.is_none() {
        return true;
    }
    if decoded_event.token_a_mint.is_none() {
        return true;
    }
    if decoded_event.token_b_mint.is_none() {
        return true;
    }
    return false;
}
