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

// Local imports
import { BasketsProgram } from "../../idl/types";
import { fetchBasketState } from "../../state/basket";
import { getStateCreatorAccount } from "../../utils/programAccounts";
import { MAX_LUT_UPDATES_PER_TX } from "../../utils/constants";


export async function extendLookupTableIxs(params: {
    program: Program<BasketsProgram>;
    manager: PublicKey;
    basket: PublicKey;
}): Promise<{
    ixs: TransactionInstruction[],
    luts: PublicKey[],
}> {
    const { program, manager } = params;
    const basketState = await fetchBasketState(program, params.basket);
    const basketPda = basketState.basketPda;
    const lookupTable1 = basketState.lookupTable1;
    const lookupTable2 = basketState.lookupTable2;
    const otherLookupTable1 = basketState.otherLookupTable1;
    const otherLookupTable2 = basketState.otherLookupTable2;
    const stateCreator = getStateCreatorAccount();

    const ixs: TransactionInstruction[] = [];
    
    let remainingAccounts = [];
    for (let i = 0; i < basketState.numTokens; i++) {
        remainingAccounts.push({
            pubkey: basketState.compositionOracle1[i],
            isSigner: false,
            isWritable: false,
        });
        if (!basketState.compositionOracle2[i].equals(PublicKey.default)) {
            remainingAccounts.push({
                pubkey: basketState.compositionOracle2[i],
                isSigner: false,
                isWritable: false,
            });
        }
        if (remainingAccounts.length + 1 >= MAX_LUT_UPDATES_PER_TX) {
            ixs.push(
                await program.methods
                    .extendLookupTable()
                    .accountsStrict({
                        manager,
                        basket: params.basket,
                        basketPda,
                        otherLookupTable1,
                        otherLookupTable2,
                        stateCreator,
                        addressLookupTableProgram: AddressLookupTableProgram.programId,
                        systemProgram: SystemProgram.programId,
                    })
                    .remainingAccounts(remainingAccounts)
                    .instruction()
            );
            remainingAccounts = [];
        }
    }

    if (remainingAccounts.length > 0) {
        ixs.push(
            await program.methods
                .extendLookupTable()
                .accountsStrict({
                    manager,
                    basket: params.basket,
                    basketPda,
                    otherLookupTable1,
                    otherLookupTable2,
                    stateCreator,
                    addressLookupTableProgram: AddressLookupTableProgram.programId,
                    systemProgram: SystemProgram.programId,
                })
                .remainingAccounts(remainingAccounts)
                .instruction()
        );
    }

    return {
        ixs,
        luts: [lookupTable1, lookupTable2],
    };
}
