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

import { ModuleManager } from '../../module-manager'
import { asAddress, asAddressVector, asBytesVector, asObject, asU16, asU32, asU64 } from '../../utils'

const MODULE_NAME = 'dvn_layerzero'

export const DVNLayerzeroErrorCode = {
    // DVNLayerzero related errors (matching dvn_layerzero.move)
    DVNLayerzero_EWorkerCapNotFromPackage: 1,
} as const

export class DvnLayerZero {
    public packageId: string
    public readonly client: SuiClient

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

    // === Set Functions ===

    /**
     * Initialize DVN LayerZero instance
     * Creates and shares a new DVN with the specified configuration
     * @param tx - The transaction to add the move call to
     * @param workerCap - Worker capability object ID or transaction argument
     * @param vid - Verifier ID for the DVN or transaction argument
     * @param depositAddress - Address for fee deposits or transaction argument
     * @param supportedMessageLibs - Array of supported message library addresses or transaction argument
     * @param priceFeed - Price feed object address or transaction argument
     * @param workerFeeLib - Worker fee library address or transaction argument
     * @param defaultMultiplierBps - Default multiplier in basis points or transaction argument
     * @param admins - Array of admin addresses or transaction argument
     * @param signers - Array of signer public keys as bytes or transaction argument
     * @param quorum - Required signature threshold or transaction argument
     */
    initDvnMoveCall(
        tx: Transaction,
        workerCap: string | TransactionArgument,
        vid: number | TransactionArgument,
        depositAddress: string | TransactionArgument,
        supportedMessageLibs: string[] | TransactionArgument,
        priceFeed: string | TransactionArgument,
        workerFeeLib: string | TransactionArgument,
        defaultMultiplierBps: number | TransactionArgument,
        admins: string[] | TransactionArgument,
        signers: Uint8Array[] | TransactionArgument,
        quorum: bigint | number | string | TransactionArgument
    ): void {
        tx.moveCall({
            target: this.#target('init_dvn'),
            arguments: [
                asObject(tx, workerCap),
                asU32(tx, vid),
                asAddress(tx, depositAddress),
                asAddressVector(tx, supportedMessageLibs),
                asAddress(tx, priceFeed),
                asAddress(tx, workerFeeLib),
                asU16(tx, defaultMultiplierBps),
                asAddressVector(tx, admins),
                asBytesVector(tx, signers),
                asU64(tx, quorum),
                tx.object(this.moduleManager.objects.workerRegistry),
            ],
        })
    }

    /**
     * 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: string = MODULE_NAME): string {
        return `${this.packageId}::${module_name}::${name}`
    }
}
