import { SuiClient } from '@mysten/sui/client'
import { Transaction, TransactionArgument, TransactionResult } from '@mysten/sui/transactions'

import { ModuleManager } from '../../module-manager'
import { ObjectOptions } from '../../types'

const MODULE_NAME = 'executor_fee_lib'

export const ExecutorFeeLibErrorCode = {
    // Executor Fee Lib related errors (matching executor_fee_lib.move)
    ExecutorFeeLib_EEidNotSupported: 1,

    // ExecutorOption related errors (matching executor_option.move)
    ExecutorOption_ENoOptions: 1,
    ExecutorOption_EUnsupportedOptionType: 2,
    ExecutorOption_EZeroLzReceiveGasProvided: 3,
    ExecutorOption_EZeroLzComposeGasProvided: 4,
    ExecutorOption_ENativeAmountExceedsCap: 5,
    ExecutorOption_EInvalidLzReceiveOption: 6,
    ExecutorOption_EInvalidNativeDropOption: 7,
    ExecutorOption_EInvalidLzComposeOption: 8,
} as const

export class ExecutorFeeLib {
    public packageId: string
    public readonly client: SuiClient
    private readonly objects: ObjectOptions

    constructor(
        packageId: string,
        client: SuiClient,
        objects: ObjectOptions,
        private readonly moduleManager: ModuleManager
    ) {
        this.packageId = packageId
        this.client = client
        this.objects = objects
    }

    // === Witness Functions ===

    /**
     * Create a LayerZero witness for Executor Fee Lib package whitelist registration
     * @param tx - The transaction to add the move call to
     * @returns Transaction result containing the LayerZero witness
     */
    createLayerZeroWitnessMoveCall(tx: Transaction): TransactionResult {
        return tx.moveCall({
            target: `${this.packageId}::executor_fee_lib_witness::new`,
            arguments: [],
        })
    }

    // === Set Functions ===

    /**
     * Create get fee move call for executor fee calculation
     * Note: This is typically called by the Executor, not directly by users
     * @param tx - The transaction to add the move call to
     * @param call - The call transaction result containing fee parameters
     * @returns Transaction result containing the fee calculation call
     */
    getFeeMoveCall(tx: Transaction, call: TransactionArgument): TransactionResult {
        return tx.moveCall({
            target: this.#target('get_fee'),
            arguments: [tx.object(this.objects.executorFeeLib), call],
        })
    }

    /**
     * Confirm get fee move call with price feed integration
     * Note: This is typically called by the Executor, not directly by users
     * @param tx - The transaction to add the move call to
     * @param feelibCall - The fee library call transaction result
     * @param priceFeedCall - The price feed call transaction result
     */
    confirmGetFeeMoveCall(tx: Transaction, feelibCall: TransactionArgument, priceFeedCall: TransactionArgument): void {
        tx.moveCall({
            target: this.#target('confirm_get_fee'),
            arguments: [tx.object(this.objects.executorFeeLib), feelibCall, priceFeedCall],
        })
    }

    /**
     * Generate the full target path for move calls
     * @param name - The function name to call
     * @param module_name - The module name (defaults to MODULE_NAME)
     * @returns The full module path for the move call
     * @private
     */
    #target(name: string, module_name = MODULE_NAME): string {
        return `${this.packageId}::${module_name}::${name}`
    }
}
