use anyhow::Result;
use riptide_amm::{fetch_market, MarketWithdraw, MarketWithdrawInstructionArgs};
use solana_pubkey::Pubkey;
use spl_associated_token_account_interface::address::get_associated_token_address_with_program_id;

use crate::{config::Config, log_context, transaction::process_instructions};

pub fn handle(config: &Config, market: &Pubkey, amount_a: &u64, amount_b: &u64) -> Result<()> {
    let rpc = config.rpc_client();

    let market_account = fetch_market(&rpc, market)?;
    let mint_a_account = rpc.get_account(&market_account.data.mint_a)?;
    let mint_b_account = rpc.get_account(&market_account.data.mint_b)?;

    let authority = market_account.data.authority;
    let signer = config
        .authority(&market_account.data.authority)
        .ok_or(anyhow::anyhow!("Authority not found"))?;

    let authority_a = get_associated_token_address_with_program_id(
        &authority,
        &market_account.data.mint_a,
        &mint_a_account.owner,
    );
    let authority_b = get_associated_token_address_with_program_id(
        &authority,
        &market_account.data.mint_b,
        &mint_b_account.owner,
    );
    let market_a = get_associated_token_address_with_program_id(
        &market_account.address,
        &market_account.data.mint_a,
        &mint_a_account.owner,
    );
    let market_b = get_associated_token_address_with_program_id(
        &market_account.address,
        &market_account.data.mint_b,
        &mint_b_account.owner,
    );

    let ixs = [MarketWithdraw {
        authority,
        market: *market,
        mint_a: market_account.data.mint_a,
        mint_b: market_account.data.mint_b,
        authority_a,
        authority_b,
        market_a,
        market_b,
        token_program_a: mint_a_account.owner,
        token_program_b: mint_b_account.owner,
        memo_program: spl_memo_interface::v3::ID,
    }
    .instruction(MarketWithdrawInstructionArgs {
        amount_a: *amount_a,
        amount_b: *amount_b,
    })];

    log_context!(
        market => market,
        authority => authority,
        amount_a => amount_a,
        amount_b => amount_b,
    );

    process_instructions(&rpc, &[signer], &ixs)
}
