import type { WalletChain } from '@/components/wallet/AddToMetaMask'
import { toWalletAddEthereumChainParams } from '@/utils/walletAddEthereumChain'
import {
  buildWatchAssetRpcRequest,
  type WatchAssetToken,
} from '@/utils/walletWatchAsset'
import {
  isMobileWalletContext,
  type EthereumProvider,
} from '@/utils/walletProviderEnv'

export async function switchOrAddChain(
  ethereum: EthereumProvider,
  chain: WalletChain,
): Promise<boolean> {
  try {
    await ethereum.request({
      method: 'wallet_switchEthereumChain',
      params: [{ chainId: chain.chainId }],
    })
    return true
  } catch (e) {
    const err = e as { code?: number }
    if (err.code !== 4902) return false
  }

  try {
    await ethereum.request({
      method: 'wallet_addEthereumChain',
      params: [
        toWalletAddEthereumChainParams(chain, {
          preferSingleRpc: isMobileWalletContext(),
        }),
      ],
    })
    return true
  } catch {
    return false
  }
}

export async function watchTokenInWallet(
  ethereum: EthereumProvider,
  token: WatchAssetToken,
  chain: WalletChain,
): Promise<{ ok: boolean; added?: boolean; error?: string }> {
  const switched = await switchOrAddChain(ethereum, chain)
  if (!switched) {
    return { ok: false, error: `Failed to switch to ${chain.chainName}. Add the network first, then retry.` }
  }

  try {
    const added = await ethereum.request(
      buildWatchAssetRpcRequest(token, isMobileWalletContext()),
    )
    return { ok: true, added: Boolean(added) }
  } catch (e) {
    const err = e as { code?: number; message?: string }
    if (err.code === 4001 || /rejected|denied|not been authorized/i.test(err.message || '')) {
      return { ok: false, error: 'Wallet request was rejected. Approve the popup to add the token.' }
    }
    return { ok: false, error: err.message || 'Could not add token to wallet.' }
  }
}
