import {
  getWatchAssetBatchSize,
  getWatchAssetInterPromptDelayMs,
  isMobileWalletContext,
  sleep,
  type EthereumProvider,
} from '@/utils/walletProviderEnv'

export type WatchAssetToken = {
  chainId: number
  address: string
  symbol: string
  decimals: number
  logoURI?: string
}

export function buildWatchAssetRpcRequest(token: WatchAssetToken, mobile = isMobileWalletContext()) {
  const options: {
    address: string
    symbol: string
    decimals: number
    image?: string
    chainId?: number | string
  } = {
    address: token.address,
    symbol: token.symbol,
    decimals: token.decimals,
  }

  if (token.logoURI) {
    options.image = token.logoURI
  }

  // Custom networks (Chain 138, ALL Mainnet, …) need explicit hex chainId or MetaMask may
  // attach the token to the wrong network and balances disappear after refresh.
  options.chainId =
    token.chainId === 1 && !mobile ? token.chainId : `0x${token.chainId.toString(16)}`

  return {
    method: 'wallet_watchAsset' as const,
    params: {
      type: 'ERC20' as const,
      options,
    },
  }
}

export type WatchAssetBatchResult = {
  addedCount: number
  nextIndex: number
  stoppedEarly: boolean
  errorMessage?: string
}

/**
 * Process up to `batchSize` wallet_watchAsset prompts starting at `startIndex`.
 * Call again from a fresh button click when `nextIndex < tokens.length` on mobile.
 */
export async function runWatchAssetBatch(
  provider: EthereumProvider,
  tokens: WatchAssetToken[],
  startIndex: number,
  options?: {
    batchSize?: number
    mobile?: boolean
    onProgress?: (current: number, total: number) => void
  },
): Promise<WatchAssetBatchResult> {
  const mobile = options?.mobile ?? isMobileWalletContext()
  const batchSize = options?.batchSize ?? getWatchAssetBatchSize(mobile)
  const delayMs = getWatchAssetInterPromptDelayMs(mobile)
  const endIndex = Math.min(tokens.length, startIndex + batchSize)
  let addedCount = 0

  for (let index = startIndex; index < endIndex; index += 1) {
    const token = tokens[index]
    options?.onProgress?.(index + 1, tokens.length)

    if (index > startIndex && delayMs > 0) {
      await sleep(delayMs)
    }

    try {
      const added = await provider.request(buildWatchAssetRpcRequest(token, mobile))
      if (added) addedCount += 1
    } catch (e) {
      const err = e as { message?: string }
      return {
        addedCount,
        nextIndex: index,
        stoppedEarly: true,
        errorMessage: err.message || `Stopped while adding ${token.symbol}.`,
      }
    }
  }

  return {
    addedCount,
    nextIndex: endIndex,
    stoppedEarly: false,
  }
}
