import { createModuleLogger, setDefaultLogLevel } from '@layerzerolabs/io-devtools'
import inquirer from 'inquirer'

import { getHyperliquidSigner } from '@/signer'
import {
    setTradingFeeShare,
    setUserGenesis,
    setGenesis,
    setNoHyperliquidity,
    registerSpot,
    enableFreezePrivilege,
    freezeUser,
    revokeFreezePrivilege,
    enableQuoteToken,
    enableAlignedQuoteToken,
} from '@/operations'
import { LOGGER_MODULES } from '@/types/cli-constants'
import {
    TradingFeeArgs,
    UserGenesisArgs,
    GenesisArgs,
    CreateSpotDeploymentArgs,
    RegisterTradingSpotArgs,
    EnableTokenFreezePrivilegeArgs,
    RevokeTokenFreezePrivilegeArgs,
    EnableTokenQuoteAssetArgs,
    EnableTokenAlignedQuoteAssetArgs,
    FreezeUserArgs,
} from '@/types'

export async function tradingFee(args: TradingFeeArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.TRADING_FEE, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'

    logger.info(`Setting trading fee share for token ${args.tokenIndex} to ${args.share}`)

    const { executeTx } = await inquirer.prompt([
        {
            type: 'confirm',
            name: 'executeTx',
            message: `Trading fee can ONLY be decreased. Do you want to execute the transaction?`,
            default: false,
        },
    ])

    if (!executeTx) {
        logger.info('Transaction cancelled - quitting.')
        process.exit(1)
    }

    const tokenIndex: number = parseInt(args.tokenIndex)
    const share: string = args.share

    logger.info(`Setting trading fee share for token ${tokenIndex} to ${share}`)

    await setTradingFeeShare(signer, isTestnet, tokenIndex, share, args.logLevel)
}

export async function userGenesis(args: UserGenesisArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.USER_GENESIS, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const action = args.action

    logger.info(`Setting user genesis for token ${args.tokenIndex}`)

    const tokenIndex: number = parseInt(args.tokenIndex)

    await setUserGenesis(signer, isTestnet, tokenIndex, action, args.logLevel)
}

export async function genesis(args: GenesisArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.GENESIS, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'

    logger.info(`Setting genesis for token ${args.tokenIndex}`)

    const tokenIndex: number = parseInt(args.tokenIndex)

    await setGenesis(signer, isTestnet, tokenIndex, args.logLevel)
}

export async function createSpotDeployment(args: CreateSpotDeploymentArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.CREATE_SPOT_DEPLOYMENT, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const tokenIndex: number = parseInt(args.tokenIndex)
    const spotIndex: number | undefined = args.spotIndex ? parseInt(args.spotIndex) : undefined

    if (spotIndex !== undefined) {
        logger.info(`Finalizing spot ${spotIndex} for token ${tokenIndex}`)
    } else {
        logger.info(`Setting no hyperliquidity for token ${tokenIndex}`)
    }

    await setNoHyperliquidity(signer, isTestnet, tokenIndex, args.logLevel, spotIndex)
}

export async function registerTradingSpot(args: RegisterTradingSpotArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.REGISTER_TRADING_SPOT, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'

    logger.info(`Registering core spot ${args.tokenIndex} for trading`)

    const tokenIndex: number = parseInt(args.tokenIndex)

    await registerSpot(signer, isTestnet, tokenIndex, args.logLevel)
}

// === Post-Launch Management Functions ===

export async function enableTokenFreezePrivilege(args: EnableTokenFreezePrivilegeArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.ENABLE_FREEZE_PRIVILEGE, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const tokenIndex: number = parseInt(args.tokenIndex)

    logger.info(`Enabling freeze privilege for token ${tokenIndex}`)

    await enableFreezePrivilege(signer, isTestnet, tokenIndex, args.logLevel)
}

export async function freezeTokenUser(args: FreezeUserArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.FREEZE_USER, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const tokenIndex: number = parseInt(args.tokenIndex)
    const userAddress: string = args.userAddress
    const freeze: boolean = args.freeze === 'true'

    logger.info(`${freeze ? 'Freezing' : 'Unfreezing'} user ${userAddress} for token ${tokenIndex}`)

    await freezeUser(signer, isTestnet, tokenIndex, userAddress, freeze, args.logLevel)
}

export async function revokeTokenFreezePrivilege(args: RevokeTokenFreezePrivilegeArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.REVOKE_FREEZE_PRIVILEGE, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const tokenIndex: number = parseInt(args.tokenIndex)

    logger.info(`Revoking freeze privilege for token ${tokenIndex}`)

    await revokeFreezePrivilege(signer, isTestnet, tokenIndex, args.logLevel)
}

export async function enableTokenQuoteAsset(args: EnableTokenQuoteAssetArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.ENABLE_QUOTE_TOKEN, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const tokenIndex: number = parseInt(args.tokenIndex)

    logger.info(`Enabling quote token capability for token ${tokenIndex}`)

    await enableQuoteToken(signer, isTestnet, tokenIndex, args.logLevel)
}

export async function enableTokenAlignedQuoteAsset(args: EnableTokenAlignedQuoteAssetArgs): Promise<void> {
    setDefaultLogLevel(args.logLevel)
    const logger = createModuleLogger(LOGGER_MODULES.ENABLE_ALIGNED_QUOTE_TOKEN, args.logLevel)

    const signer = await getHyperliquidSigner(args.privateKey)
    const isTestnet = args.network === 'testnet'
    const tokenIndex: number = parseInt(args.tokenIndex)

    logger.info(`Enabling aligned quote token capability for token ${tokenIndex}`)

    await enableAlignedQuoteToken(signer, isTestnet, tokenIndex, args.logLevel)
}
