// file: kb_lib/src/dex/raydium_launchpad.rs

//! Raydium Launchpad instruction and event helper metadata.
//!
//! The specialized `0.7.50` implementation still decodes Launchpad through
//! the shared persistence-oriented decoder. This module centralizes the stable
//! Launchpad account-layout hints so they do not remain hidden inside the
//! generic Raydium audit fallback.

/// Static account layout for a locally mapped Raydium Launchpad instruction.
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub(crate) struct RaydiumLaunchpadAccountLayout {
    /// IDL instruction name.
    pub(crate) instruction_name: &'static str,
    /// Local decoded event kind.
    pub(crate) event_kind: &'static str,
    /// Minimum projected account count required before applying account hints.
    pub(crate) minimum_account_count: usize,
    /// Candidate pool-state account index in the projected instruction account list.
    pub(crate) pool_account_index: std::option::Option<usize>,
    /// Candidate base mint account index in the projected instruction account list.
    pub(crate) base_mint_index: std::option::Option<usize>,
    /// Candidate quote mint account index in the projected instruction account list.
    pub(crate) quote_mint_index: std::option::Option<usize>,
    /// Whether this instruction creates a Launchpad pool/bonding curve.
    pub(crate) creates_pool: bool,
}

/// Returns local account-layout hints for one Raydium Launchpad instruction discriminator.
pub(crate) fn account_layout(
    discriminator_hex: &str,
    account_count: usize,
) -> std::option::Option<RaydiumLaunchpadAccountLayout> {
    let layout = match discriminator_hex {
        "faea0d7bd59c13ec" => RaydiumLaunchpadAccountLayout {
            instruction_name: "buy_exact_in",
            event_kind: "raydium_launchpad.buy_exact_in",
            minimum_account_count: 11,
            pool_account_index: Some(4),
            base_mint_index: Some(9),
            quote_mint_index: Some(10),
            creates_pool: false,
        },
        "18d3742869039938" => RaydiumLaunchpadAccountLayout {
            instruction_name: "buy_exact_out",
            event_kind: "raydium_launchpad.buy_exact_out",
            minimum_account_count: 11,
            pool_account_index: Some(4),
            base_mint_index: Some(9),
            quote_mint_index: Some(10),
            creates_pool: false,
        },
        "7bb4b8816fb9bb3b" => RaydiumLaunchpadAccountLayout {
            instruction_name: "close_platform_global_access",
            event_kind: "raydium_launchpad.close_platform_global_access",
            minimum_account_count: 4,
            pool_account_index: None,
            base_mint_index: None,
            quote_mint_index: None,
            creates_pool: false,
        },
        "a25b92c75d85eaed" => RaydiumLaunchpadAccountLayout {
            instruction_name: "create_platform_global_access",
            event_kind: "raydium_launchpad.create_platform_global_access",
            minimum_account_count: 5,
            pool_account_index: None,
            base_mint_index: None,
            quote_mint_index: None,
            creates_pool: false,
        },
        "9247ad4562130f6a" => RaydiumLaunchpadAccountLayout {
            instruction_name: "create_platform_vesting_account",
            event_kind: "raydium_launchpad.create_platform_vesting_account",
            minimum_account_count: 6,
            pool_account_index: Some(3),
            base_mint_index: None,
            quote_mint_index: None,
            creates_pool: false,
        },
        "e445a52e51cb9a1d" => no_account_layout("cpi_event", "raydium_launchpad.cpi_event"),
        "1a618acb84ab8dfc" => {
            no_account_layout("claim_creator_fee", "raydium_launchpad.claim_creator_fee")
        },
        "9c27d0874ced3d48" => RaydiumLaunchpadAccountLayout {
            instruction_name: "claim_platform_fee",
            event_kind: "raydium_launchpad.claim_platform_fee",
            minimum_account_count: 7,
            pool_account_index: Some(2),
            base_mint_index: None,
            quote_mint_index: Some(6),
            creates_pool: false,
        },
        "75f1c6a8f8da501d" => no_account_layout(
            "claim_platform_fee_from_vault",
            "raydium_launchpad.claim_platform_fee_from_vault",
        ),
        "3121681ebd9d4f23" => RaydiumLaunchpadAccountLayout {
            instruction_name: "claim_vested_token",
            event_kind: "raydium_launchpad.claim_vested_token",
            minimum_account_count: 7,
            pool_account_index: Some(2),
            base_mint_index: Some(6),
            quote_mint_index: None,
            creates_pool: false,
        },
        "3cadf767045d8230" => RaydiumLaunchpadAccountLayout {
            instruction_name: "collect_fee",
            event_kind: "raydium_launchpad.collect_fee",
            minimum_account_count: 6,
            pool_account_index: Some(2),
            base_mint_index: None,
            quote_mint_index: Some(5),
            creates_pool: false,
        },
        "ffba96dfeb76c9ba" => RaydiumLaunchpadAccountLayout {
            instruction_name: "collect_migrate_fee",
            event_kind: "raydium_launchpad.collect_migrate_fee",
            minimum_account_count: 6,
            pool_account_index: Some(2),
            base_mint_index: None,
            quote_mint_index: Some(5),
            creates_pool: false,
        },
        "c9cff3724b6f2fbd" => no_account_layout("create_config", "raydium_launchpad.create_config"),
        "b05ac4affd71dc14" => {
            no_account_layout("create_platform_config", "raydium_launchpad.create_platform_config")
        },
        "81b2020dd9ace6da" => RaydiumLaunchpadAccountLayout {
            instruction_name: "create_vesting_account",
            event_kind: "raydium_launchpad.create_vesting_account",
            minimum_account_count: 5,
            pool_account_index: Some(2),
            base_mint_index: None,
            quote_mint_index: None,
            creates_pool: false,
        },
        "afaf6d1f0d989bed" => initialize_layout("initialize", "raydium_launchpad.initialize"),
        "4399af27da102620" => initialize_layout("initialize_v2", "raydium_launchpad.initialize_v2"),
        "25be7ede2c9aab11" => initialize_layout(
            "initialize_with_token_2022",
            "raydium_launchpad.initialize_with_token_2022",
        ),
        "cf52c091fecf91df" => RaydiumLaunchpadAccountLayout {
            instruction_name: "migrate_to_amm",
            event_kind: "raydium_launchpad.migrate_to_amm",
            minimum_account_count: 28,
            pool_account_index: Some(23),
            base_mint_index: Some(1),
            quote_mint_index: Some(2),
            creates_pool: false,
        },
        "885cc8671cda908c" => RaydiumLaunchpadAccountLayout {
            instruction_name: "migrate_to_cpswap",
            event_kind: "raydium_launchpad.migrate_to_cpswap",
            minimum_account_count: 22,
            pool_account_index: Some(17),
            base_mint_index: Some(1),
            quote_mint_index: Some(2),
            creates_pool: false,
        },
        "1b1e3ea95de01891" => no_account_layout(
            "remove_platform_curve_param",
            "raydium_launchpad.remove_platform_curve_param",
        ),
        "9527de9bd37c981a" => RaydiumLaunchpadAccountLayout {
            instruction_name: "sell_exact_in",
            event_kind: "raydium_launchpad.sell_exact_in",
            minimum_account_count: 11,
            pool_account_index: Some(4),
            base_mint_index: Some(9),
            quote_mint_index: Some(10),
            creates_pool: false,
        },
        "5fc8472208090ba6" => RaydiumLaunchpadAccountLayout {
            instruction_name: "sell_exact_out",
            event_kind: "raydium_launchpad.sell_exact_out",
            minimum_account_count: 11,
            pool_account_index: Some(4),
            base_mint_index: Some(9),
            quote_mint_index: Some(10),
            creates_pool: false,
        },
        "1d9efcbf0a53db63" => no_account_layout("update_config", "raydium_launchpad.update_config"),
        "c33c4c81922d438f" => {
            no_account_layout("update_platform_config", "raydium_launchpad.update_platform_config")
        },
        "8a908afadc800439" => no_account_layout(
            "update_platform_curve_param",
            "raydium_launchpad.update_platform_curve_param",
        ),
        _ => return None,
    };
    return Some(sanitize_account_layout(layout, account_count));
}

fn sanitize_account_layout(
    layout: RaydiumLaunchpadAccountLayout,
    account_count: usize,
) -> RaydiumLaunchpadAccountLayout {
    let pool_account_index = retain_existing_index(layout.pool_account_index, account_count);
    let base_mint_index = retain_existing_index(layout.base_mint_index, account_count);
    let quote_mint_index = retain_existing_index(layout.quote_mint_index, account_count);
    return RaydiumLaunchpadAccountLayout {
        instruction_name: layout.instruction_name,
        event_kind: layout.event_kind,
        minimum_account_count: layout.minimum_account_count,
        pool_account_index,
        base_mint_index,
        quote_mint_index,
        creates_pool: layout.creates_pool
            && pool_account_index.is_some()
            && base_mint_index.is_some()
            && quote_mint_index.is_some(),
    };
}

fn retain_existing_index(
    index: std::option::Option<usize>,
    account_count: usize,
) -> std::option::Option<usize> {
    let index = match index {
        Some(index) => index,
        None => return None,
    };
    if index < account_count {
        return Some(index);
    }
    return None;
}

fn no_account_layout(
    instruction_name: &'static str,
    event_kind: &'static str,
) -> RaydiumLaunchpadAccountLayout {
    return RaydiumLaunchpadAccountLayout {
        instruction_name,
        event_kind,
        minimum_account_count: 1,
        pool_account_index: None,
        base_mint_index: None,
        quote_mint_index: None,
        creates_pool: false,
    };
}

fn initialize_layout(
    instruction_name: &'static str,
    event_kind: &'static str,
) -> RaydiumLaunchpadAccountLayout {
    return RaydiumLaunchpadAccountLayout {
        instruction_name,
        event_kind,
        minimum_account_count: 18,
        pool_account_index: Some(5),
        base_mint_index: Some(6),
        quote_mint_index: Some(7),
        creates_pool: true,
    };
}

#[cfg(test)]
mod tests {
    #[test]
    fn initialize_layout_exposes_carbon_account_order() {
        let layout = super::account_layout("afaf6d1f0d989bed", 18);
        let layout = match layout {
            Some(layout) => layout,
            None => panic!("initialize layout must resolve"),
        };
        assert_eq!(layout.instruction_name, "initialize");
        assert_eq!(layout.pool_account_index, Some(5));
        assert_eq!(layout.base_mint_index, Some(6));
        assert_eq!(layout.quote_mint_index, Some(7));
        assert!(layout.creates_pool);
    }

    #[test]
    fn platform_vesting_layout_exposes_pool_state() {
        let layout = super::account_layout("9247ad4562130f6a", 6);
        let layout = match layout {
            Some(layout) => layout,
            None => panic!("create_platform_vesting_account layout must resolve"),
        };
        assert_eq!(layout.instruction_name, "create_platform_vesting_account");
        assert_eq!(layout.pool_account_index, Some(3));
    }

    #[test]
    fn buy_layout_keeps_audit_only_pool_hints() {
        let layout = super::account_layout("faea0d7bd59c13ec", 11);
        let layout = match layout {
            Some(layout) => layout,
            None => panic!("buy layout must resolve"),
        };
        assert_eq!(layout.event_kind, "raydium_launchpad.buy_exact_in");
        assert_eq!(layout.pool_account_index, Some(4));
        assert_eq!(layout.base_mint_index, Some(9));
        assert_eq!(layout.quote_mint_index, Some(10));
        assert!(!layout.creates_pool);
    }

    #[test]
    fn known_discriminator_still_maps_when_account_list_is_truncated() {
        let layout = super::account_layout("cf52c091fecf91df", 1);
        let layout = match layout {
            Some(layout) => layout,
            None => panic!("migrate_to_amm layout must resolve"),
        };
        assert_eq!(layout.instruction_name, "migrate_to_amm");
        assert_eq!(layout.event_kind, "raydium_launchpad.migrate_to_amm");
        assert_eq!(layout.pool_account_index, None);
        assert_eq!(layout.base_mint_index, None);
        assert_eq!(layout.quote_mint_index, None);
        assert!(!layout.creates_pool);
    }
}
