use solana_program::pubkey::Pubkey;

use crate::pyra::get_vault;
use crate::KAMINO_LEND_PROGRAM_ID;

pub fn get_kamino_lending_market_authority(market: &Pubkey) -> Pubkey {
    let (pubkey, _) =
        Pubkey::find_program_address(&[b"lma", market.as_ref()], &KAMINO_LEND_PROGRAM_ID);
    pubkey
}

/// Derive the default Kamino obligation PDA for a Pyra vault.
///
/// `owner` is the end user's wallet pubkey. The Pyra vault is derived
/// internally — do NOT pass the vault here, or you'll get a PDA derived
/// from a vault-of-vault which does not exist on-chain.
///
/// Seeds: `[tag, id, vault, market, seed1_account, seed2_account]`.
/// - `tag = 0`: default obligation type (Klend supports multiple via tag/id)
/// - `id = 0`: first obligation of this type
/// - `seed1_account` / `seed2_account` = `Pubkey::default()`: must be default when tag is 0
pub fn get_kamino_obligation(owner: &Pubkey, market: &Pubkey) -> Pubkey {
    let vault = get_vault(owner);
    let (pubkey, _) = Pubkey::find_program_address(
        &[
            &[0u8],
            &[0u8],
            vault.as_ref(),
            market.as_ref(),
            Pubkey::default().as_ref(),
            Pubkey::default().as_ref(),
        ],
        &KAMINO_LEND_PROGRAM_ID,
    );
    pubkey
}

/// Derive the Kamino `user_meta` PDA for a Pyra vault.
///
/// `owner` is the end user's wallet pubkey. The Pyra vault is derived
/// internally — do NOT pass the vault.
pub fn get_kamino_user_metadata(owner: &Pubkey) -> Pubkey {
    let vault = get_vault(owner);
    let (pubkey, _) =
        Pubkey::find_program_address(&[b"user_meta", vault.as_ref()], &KAMINO_LEND_PROGRAM_ID);
    pubkey
}

pub fn get_kamino_reserve_fee_vault(reserve: &Pubkey) -> Pubkey {
    let (pubkey, _) = Pubkey::find_program_address(
        &[b"fee_receiver", reserve.as_ref()],
        &KAMINO_LEND_PROGRAM_ID,
    );
    pubkey
}

/// Derive the Kamino owner-queued-collateral-vault PDA for a Pyra vault.
///
/// `owner` is the end user's wallet pubkey. The Pyra vault is derived
/// internally — do NOT pass the vault.
pub fn get_kamino_owner_queued_collateral_vault(owner: &Pubkey, reserve: &Pubkey) -> Pubkey {
    let vault = get_vault(owner);
    let (pda, _) = Pubkey::find_program_address(
        &[
            b"owner_queued_collateral_vault",
            reserve.as_ref(),
            vault.as_ref(),
        ],
        &KAMINO_LEND_PROGRAM_ID,
    );
    pda
}

pub fn get_kamino_withdraw_ticket(reserve: &Pubkey, sequence_number: u64) -> Pubkey {
    let (pda, _) = Pubkey::find_program_address(
        &[
            b"withdraw_ticket",
            reserve.as_ref(),
            &sequence_number.to_le_bytes(),
        ],
        &KAMINO_LEND_PROGRAM_ID,
    );
    pda
}
