// Core dependencies
import { Program } from "@coral-xyz/anchor";
import { ASSOCIATED_TOKEN_PROGRAM_ID, TOKEN_PROGRAM_ID } from "@solana/spl-token";
import { AddressLookupTableProgram, PublicKey, SystemProgram } from "@solana/web3.js";

// Local imports
import { PYTH_SPONSORED_FEEDS, REBALANCE_FEE_WALLET } from "../../utils/constants";
import { BasketsProgram } from "../../idl/types";
import { getAta } from "../../utils/programAccounts";
import { fetchBasketState } from "../../state/basket";


export async function addNewTokenIx(params: {
    program: Program<BasketsProgram>;
    basket: PublicKey;
    manager: PublicKey;
    token: PublicKey;
    tokenWeight: number;
    oracleType: number;
    oraclePool: PublicKey;
    oracle1: PublicKey;
    oracle2: PublicKey;
}) {
    // Destructure all params
    const { 
        program,
        basket,
        manager,
        token,
        tokenWeight,
        oracleType,
        oraclePool,
        oracle1,
        oracle2 
    } = params;

    // Get basket state and lookup tables
    const basketState = await fetchBasketState(program, basket);
    const {basketPda, lookupTable1, lookupTable2 } = basketState;

    // Get token accounts that need to be created
    const basketTokenAccount = getAta(basketPda, token);
    const rebalanceTokenAccount = getAta(REBALANCE_FEE_WALLET, token);

    // Build and return instruction
    return await program.methods
        .addNewToken(
            tokenWeight,
            oracleType,
            oracle1,
            oracle2
        )
        .accountsStrict({
            manager,
            basket,
            basketPda,
            lookupTable1,
            lookupTable2,
            rebalanceFeeWallet: REBALANCE_FEE_WALLET,
            newTokenMint: token,
            pythSponsoredFeeds: PYTH_SPONSORED_FEEDS,
            newTokenOraclePool: oraclePool,
            newTokenBasketTokenAccount: basketTokenAccount,
            newTokenRebalanceTokenAccount: rebalanceTokenAccount,
            addressLookupTableProgram: AddressLookupTableProgram.programId,
            systemProgram: SystemProgram.programId,
            tokenProgram: TOKEN_PROGRAM_ID,
            associatedTokenProgram: ASSOCIATED_TOKEN_PROGRAM_ID,
        })
        .instruction();
}
