use anyhow::Result;
use riptide_amm::{fetch_market, MarketClose, 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) -> Result<()> {
    let rpc = config.rpc_client();

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

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

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

    let ixs = [
        MarketWithdraw {
            authority,
            market: market.address,
            mint_a: market.data.mint_a,
            mint_b: market.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: u64::MAX,
            amount_b: u64::MAX,
        }),
        MarketClose {
            authority,
            market: market.address,
            mint_a: market.data.mint_a,
            mint_b: market.data.mint_b,
            market_a,
            market_b,
            system_program: solana_system_interface::program::ID,
            ata_program: spl_associated_token_account_interface::program::ID,
            token_program_a: mint_a_account.owner,
            token_program_b: mint_b_account.owner,
            authority_a,
            authority_b,
        }
        .instruction(),
    ];

    log_context!(
        market => market.address,
        authority => authority,
    );

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