import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { post, get, postForm } from '@/utils/request'
import type { AccountAuth } from '@/types/account'

export interface WithdrawBalance {
  memberId: string
  balance: string
  frozenBalance: string
  withdrawableBalance: string
  transferableBalance: string
}

export interface WalletCoin {
  unit: string
  name: string
  nameCn: string
  canRecharge: string
  canWithdraw: string
  minRechargeAmount: number
  maxRechargeAmount: number
  minWithdrawAmount: string
  maxWithdrawAmount: string
  minTxFee: string
  maxTxFee: string
  withdrawFeeValue: string
}

export interface WalletAddress {
  id: number
  balance: number
  address: string
  coin: WalletCoin | null
}

export interface SupportCoinInfo {
  unit: string
  aliasName?: string
  nameCn?: string
  name?: string
  balance?: string | number
  minWithdrawAmount: string
  maxWithdrawAmount: string
  minTxFee: string
  maxTxFee: string
  fee: string
  minTransferAmount?: string
  minAmount?: string
  withdrawFeeValue?: string
}

/** coin 表顶级主币（parent_coin_name 为空且 can_recharge=1，内部转账用） */
export interface TransferParentCoin {
  name: string
  nameCn: string
  unit: string
  sort: number
  minWithdrawAmount?: string | number
  withdrawFeeValue?: string | number
}

/** coin_network 表一行（提币网络列表） */
export interface WithdrawNetworkItem {
  id: number
  name: string
  protocol: string
  sort: number
}

/** 可提/可转币种 */
export interface WithdrawCoinOption {
  unit: string
  displayName: string
  networkLabel: string
  networkId?: number
  balance: string
  minWithdraw: string
  minTransfer: string
  withdrawFee: string
  isUsdtFamily: boolean
  /** 主币（内部转账仅主币） */
  isMainCoin: boolean
}

export interface WithdrawRecordCoin {
  coinName: string
  aliasName: string
  fee: string
}

export interface WithdrawRecord {
  id: string
  status: string
  address: string
  amount: string
  transferAmount: string
  createTime: string
  dealTime: string
  transactionHashId: string
  coin: WithdrawRecordCoin | null
  memberId: string
  isTransfer: boolean
}

/** 取第一个非空字符串（提币接口金额字段在各端命名不一致） */
function firstNonEmptyStr(...vals: unknown[]): string {
  for (const v of vals) {
    if (v === undefined || v === null) {
      continue
    }
    const s = String(v).trim()
    if (s !== '') {
      return s
    }
  }
  return ''
}

/**
 * 从原始记录中解析提现/转账数量（兼容 amount、money、totalAmount 及 snake_case）
 */
function pickWithdrawAmountFields(r: Record<string, unknown>): string {
  return firstNonEmptyStr(
    r.amount,
    r.money,
    r.totalAmount,
    r.applyAmount,
    r.withdrawAmount,
    r.realAmount,
    r.arrivedAmount,
    r.transferAmount,
    r.total_amount,
    r.apply_amount,
    r.transfer_amount,
    r.transferMoney,
  )
}

function normalizeWithdrawCoin(raw: unknown): WithdrawRecordCoin | null {
  if (!raw || typeof raw !== 'object') {
    return null
  }
  const c = raw as Record<string, unknown>
  const coinName = firstNonEmptyStr(c.unit, c.coinName, c.coin_name, c.name)
  const aliasName = firstNonEmptyStr(c.nameCn, c.aliasName, c.alias_name, c.name)
  const fee = firstNonEmptyStr(c.fee, c.withdrawFeeValue, c.withdraw_fee_value, c.minTxFee)
  if (!coinName && !aliasName && !fee) {
    return null
  }
  return {
    coinName,
    aliasName,
    fee,
  }
}

/**
 * 将链上/内部转账列表或详情接口返回的行数据规范为 WithdrawRecord（统一 amount 与 transferAmount）
 */
export function normalizeWithdrawRecord(raw: unknown, isTransfer: boolean): WithdrawRecord {
  const r = raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : {}
  const resolved = pickWithdrawAmountFields(r)
  const amountOut = firstNonEmptyStr(r.amount, resolved)
  const transferOut = firstNonEmptyStr(r.transferAmount, r.amount, resolved)
  const coinRaw = r.coin ?? r.coinDto ?? r.coinInfo
  let coin = normalizeWithdrawCoin(coinRaw)
  if (!coin && (r.coinName != null || r.aliasName != null)) {
    coin = normalizeWithdrawCoin({
      coinName: r.coinName,
      aliasName: r.aliasName,
      fee: r.fee ?? r.withdrawFeeValue,
    })
  }

  return {
    id: r.id != null ? String(r.id) : '',
    status: r.status != null ? String(r.status) : '',
    address: firstNonEmptyStr(r.address, r.toAddress, r.to_address, r.account, r.walletAddress),
    amount: amountOut,
    transferAmount: transferOut,
    createTime: firstNonEmptyStr(r.createTime, r.create_time, r.addTime, r.add_time),
    dealTime: firstNonEmptyStr(r.dealTime, r.deal_time, r.finishTime, r.finish_time),
    transactionHashId: firstNonEmptyStr(
      r.transactionNumber,
      r.transaction_number,
      r.transactionHashId,
      r.transactionHash,
      r.transaction_hash_id,
      r.hash,
      r.txId,
      r.txid,
    ),
    coin,
    memberId: firstNonEmptyStr(r.memberId, r.member_id),
    isTransfer,
  }
}

const COUNTDOWN_SEC = 60

/** 安全开关：兼容后端 0/1、布尔、字符串 */
function isSecurityFlagOn(v: unknown): boolean {
  if (v === true || v === 'true') {
    return true
  }
  if (v === false || v === 'false' || v === '' || v == null) {
    return false
  }
  if (typeof v === 'string' && v.trim() === '1') {
    return true
  }
  const n = Number(v)
  if (!Number.isNaN(n)) {
    return n === 1
  }
  return false
}

/**
 * 将钱包 / 支持币种里的 unit 解析为提币网络 Tab（与充值页 deposit 逻辑一致，且 USDT 归入 TRC20）
 */
function walletUnitToNetworkLabel(unit: string | undefined): string {
  if (!unit) {
    return ''
  }
  const code = unit.toUpperCase()
  if (code === 'USDT') {
    return 'TRC20'
  }
  if (code.startsWith('T')) {
    return 'TRC20'
  }
  if (code.startsWith('E')) {
    return 'ERC20'
  }
  if (code.includes('BEP20')) {
    return 'BEP20'
  }
  return ''
}

/** 网络 Tab 排序：与 App 一致 */
const NETWORK_TAB_ORDER: Record<string, number> = { TRC20: 0, ERC20: 1, BEP20: 2 }

function isUsdtFamilyUnit(unit: string): boolean {
  const u = unit.toUpperCase()
  return u === 'USDT' || u === 'EUSDT' || u === 'TUSDT' || u.includes('BEP20')
}

function mapTransferParent(
  row: Record<string, unknown>,
  supportMap: Map<string, SupportCoinInfo>,
): WithdrawCoinOption {
  const unit = String(row.unit ?? '').trim().toLowerCase()
  const name = String(row.name ?? '')
  const support = supportMap.get(unit) ?? supportMap.get(name.toLowerCase())
  const minFromCoin = firstNonEmptyStr(row.minWithdrawAmount)
  const minFromSupport = firstNonEmptyStr(support?.minAmount, support?.minWithdrawAmount, support?.minTransferAmount)
  return {
    unit,
    displayName: firstNonEmptyStr(row.nameCn, support?.nameCn, support?.aliasName, name) || unit.toUpperCase(),
    networkLabel: '',
    balance: firstNonEmptyStr(support?.balance, '0') || '0',
    minWithdraw: minFromSupport || minFromCoin || '0',
    minTransfer: firstNonEmptyStr(support?.minTransferAmount, support?.minAmount, minFromSupport, minFromCoin) || '0',
    withdrawFee: firstNonEmptyStr(support?.withdrawFeeValue, support?.fee, row.withdrawFeeValue) || '0',
    isUsdtFamily: isUsdtFamilyUnit(unit),
    isMainCoin: true,
  }
}

function mapNetworkItem(row: Record<string, unknown>): WithdrawNetworkItem {
  return {
    id: Number(row.id ?? 0),
    name: String(row.name ?? ''),
    protocol: String(row.protocol ?? ''),
    sort: Number(row.sort ?? 0),
  }
}

function supportInfoByUnit(list: SupportCoinInfo[]): Map<string, SupportCoinInfo> {
  const map = new Map<string, SupportCoinInfo>()
  for (const c of list) {
    const u = String(c.unit ?? '').toLowerCase()
    if (u) {
      map.set(u, c)
    }
  }
  return map
}

function mapWithdrawConfigFromDb(
  row: Record<string, unknown>,
  supportMap: Map<string, SupportCoinInfo>,
): WithdrawCoinOption {
  const unit = String(row.unit ?? '').trim().toLowerCase()
  const coinName = String(row.coinName ?? '')
  const support = supportMap.get(unit) ?? supportMap.get(coinName.toLowerCase())
  const networkName = String(row.networkName ?? '')
  const minFromDb = firstNonEmptyStr(row.minWithdrawAmount, row.minAmount)
  const minFromSupport = firstNonEmptyStr(support?.minAmount, support?.minWithdrawAmount)
  return {
    unit,
    displayName: firstNonEmptyStr(row.coinNameCn, support?.nameCn, support?.aliasName, coinName) || unit.toUpperCase(),
    networkLabel: networkName,
    networkId: Number(row.networkId ?? 0) || undefined,
    balance: firstNonEmptyStr(support?.balance, '0') || '0',
    minWithdraw: minFromSupport || minFromDb || '0',
    minTransfer: firstNonEmptyStr(support?.minTransferAmount, support?.minAmount, minFromSupport) || '0',
    withdrawFee: firstNonEmptyStr(support?.withdrawFeeValue, support?.fee, row.withdrawFeeValue) || '0',
    isUsdtFamily: isUsdtFamilyUnit(unit),
    isMainCoin: false,
  }
}

/**
 * 各链默认手续费 / 最小提币（仅当钱包与支持币种接口均未返回有效值时使用，与 App 展示对齐）
 */
const NETWORK_WITHDRAW_DEFAULTS: Record<string, { fee: string; min: string }> = {
  TRC20: { fee: '1', min: '10' },
  ERC20: { fee: '5', min: '20' },
  BEP20: { fee: '2', min: '10' },
}

export const useWithdrawStore = defineStore('withdraw', () => {
  const walletBalance = ref<WithdrawBalance | null>(null)
  const security = ref<AccountAuth | null>(null)
  const coinInfoList = ref<SupportCoinInfo[]>([])
  const walletAddresses = ref<WalletAddress[]>([])
  /** 链上：coin_network 表 */
  const networkList = ref<WithdrawNetworkItem[]>([])
  const selectedNetworkId = ref(0)
  const onchainSubCoins = ref<WithdrawCoinOption[]>([])
  const onchainSubCoinsLoading = ref(false)
  const selectedSubCoinIndex = ref(0)
  /** 内部转账：仅主币 */
  const transferMainCoins = ref<WithdrawCoinOption[]>([])
  const selectedTransferCoinIndex = ref(0)
  const initLoading = ref(false)
  const initError = ref<string | null>(null)

  const sendingCode = ref(false)
  const codeCountdown = ref(0)
  const submitting = ref(false)
  const formError = ref<string | null>(null)

  const records = ref<WithdrawRecord[]>([])
  const recordLoading = ref(false)
  const recordHasMore = ref(true)
  const onchainPage = ref(0)
  const transferPage = ref(0)

  let countdownTimer: ReturnType<typeof setInterval> | null = null

  function startCountdown() {
    if (countdownTimer) clearInterval(countdownTimer)
    codeCountdown.value = COUNTDOWN_SEC
    countdownTimer = setInterval(() => {
      codeCountdown.value--
      if (codeCountdown.value <= 0) {
        clearInterval(countdownTimer!)
        countdownTimer = null
      }
    }, 1000)
  }

  function stopCountdown() {
    if (countdownTimer) { clearInterval(countdownTimer); countdownTimer = null }
    codeCountdown.value = 0
  }

  async function init() {
    initLoading.value = true
    initError.value = null
    try {
      const [balRes, secRes, coinRes, netRes, parentRes] = await Promise.all([
        post<WithdrawBalance>('/uc/asset/wallet/usdt', {}),
        postForm<AccountAuth>('/uc/approve/security/setting', {}),
        post<SupportCoinInfo[]>('/uc/withdraw/support/coin/info', {}),
        get<Record<string, unknown>[]>('/uc/coin-network/withdraw-networks'),
        get<Record<string, unknown>[]>('/uc/coin-network/transfer-parents'),
      ])
      walletBalance.value = balRes
      security.value = secRes
      coinInfoList.value = Array.isArray(coinRes) ? coinRes : []
      const nets = Array.isArray(netRes) ? netRes : []
      networkList.value = nets.map(r => mapNetworkItem(r)).filter(n => n.id > 0)
      const parents = Array.isArray(parentRes) ? parentRes : []
      const supportMap = supportInfoByUnit(coinInfoList.value)
      transferMainCoins.value = parents
        .map(r => mapTransferParent(r, supportMap))
        .filter(c => c.unit)
        .sort((a, b) => a.displayName.localeCompare(b.displayName))
      await resetSelection()
    } catch (e) {
      initError.value = e instanceof Error ? e.message : 'i18n:withdraw.initFailed'
      throw e
    } finally {
      initLoading.value = false
    }
  }

  /** All USDT wallet addresses (filtered to those with a recognizable coin unit) */
  const usdtWallets = computed(() =>
    walletAddresses.value.filter(w => {
      const unit = w.coin?.unit?.toUpperCase() ?? ''
      return unit === 'USDT' || unit === 'TUSDT' || unit === 'EUSDT' || unit.includes('BEP20')
    }),
  )

  /** Networks available from the user's wallet addresses */
  const availableNetworks = computed(() => {
    const nets: string[] = []
    for (const w of usdtWallets.value) {
      const label = walletUnitToNetworkLabel(w.coin?.unit)
      if (label) {
        nets.push(label)
      }
    }
    const unique = [...new Set(nets)]
    return unique.sort((a, b) => (NETWORK_TAB_ORDER[a] ?? 99) - (NETWORK_TAB_ORDER[b] ?? 99))
  })

  /** 按当前选择的网络匹配 support/coin/info 中的币种配置 */
  function findSupportCoinForNetwork(network: string): SupportCoinInfo | undefined {
    return coinInfoList.value.find(c => walletUnitToNetworkLabel(c.unit) === network)
  }

  /** Find wallet by network label */
  function getWalletByNetwork(network: string): WalletAddress | undefined {
    return usdtWallets.value.find(w => walletUnitToNetworkLabel(w.coin?.unit) === network)
  }

  /** Fee for the selected network（钱包币种 → 支持币种接口 → 默认表） */
  function getFee(network: string): string {
    const w = getWalletByNetwork(network)?.coin
    if (w?.withdrawFeeValue != null && String(w.withdrawFeeValue).trim() !== '') {
      return String(w.withdrawFeeValue)
    }
    const info = findSupportCoinForNetwork(network)
    const fromInfo = info?.withdrawFeeValue ?? info?.fee
    if (fromInfo != null && String(fromInfo).trim() !== '') {
      return String(fromInfo)
    }
    return NETWORK_WITHDRAW_DEFAULTS[network]?.fee ?? '0'
  }

  /** Min withdraw amount for the selected network */
  function getMinWithdrawAmount(network: string): string {
    const w = getWalletByNetwork(network)?.coin
    const wMin = w?.minWithdrawAmount
    if (wMin != null && String(wMin).trim() !== '' && Number(wMin) > 0) {
      return String(wMin)
    }
    const info = findSupportCoinForNetwork(network)
    const iMin = info?.minWithdrawAmount
    if (iMin != null && String(iMin).trim() !== '' && Number(iMin) > 0) {
      return String(iMin)
    }
    return NETWORK_WITHDRAW_DEFAULTS[network]?.min ?? '0'
  }

  const onchainSelectedCoin = computed(
    () => onchainSubCoins.value[selectedSubCoinIndex.value] ?? null,
  )

  const transferSelectedCoin = computed(
    () => transferMainCoins.value[selectedTransferCoinIndex.value] ?? null,
  )

  const minTransferAmount = computed(() => transferSelectedCoin.value?.minTransfer ?? '0')

  async function loadOnchainSubCoins(networkId: number) {
    if (!networkId) {
      onchainSubCoins.value = []
      return
    }
    onchainSubCoinsLoading.value = true
    try {
      const raw = await get<Record<string, unknown>[]>('/uc/coin-network/withdraw-configs', {
        networkId,
      })
      const list = Array.isArray(raw) ? raw : []
      const supportMap = supportInfoByUnit(coinInfoList.value)
      onchainSubCoins.value = list
        .map(r => mapWithdrawConfigFromDb(r, supportMap))
        .filter(c => c.unit)
      if (selectedSubCoinIndex.value >= onchainSubCoins.value.length) {
        selectedSubCoinIndex.value = 0
      }
    } finally {
      onchainSubCoinsLoading.value = false
    }
  }

  async function resetSelection() {
    const nets = networkList.value
    if (nets.length > 0) {
      const stillValid = nets.some(n => n.id === selectedNetworkId.value)
      if (!stillValid) {
        selectedNetworkId.value = nets[0].id
      }
      await loadOnchainSubCoins(selectedNetworkId.value)
    } else {
      selectedNetworkId.value = 0
      onchainSubCoins.value = []
    }
    selectedSubCoinIndex.value = 0
    if (selectedTransferCoinIndex.value >= transferMainCoins.value.length) {
      selectedTransferCoinIndex.value = 0
    }
  }

  async function selectNetwork(networkId: number) {
    if (!networkId || !networkList.value.some(n => n.id === networkId)) {
      return
    }
    selectedNetworkId.value = networkId
    selectedSubCoinIndex.value = 0
    await loadOnchainSubCoins(networkId)
  }

  function selectSubCoin(index: number) {
    if (index < 0 || index >= onchainSubCoins.value.length) {
      return
    }
    selectedSubCoinIndex.value = index
  }

  function selectTransferCoin(index: number) {
    if (index < 0 || index >= transferMainCoins.value.length) {
      return
    }
    selectedTransferCoinIndex.value = index
  }

  function balanceForCoin(coin: WithdrawCoinOption | null, mode: 'withdraw' | 'transfer'): string {
    if (!coin) {
      return '0'
    }
    if (mode === 'transfer' && coin.unit.toUpperCase() === 'USDT') {
      const bal = walletBalance.value
      return bal?.transferableBalance ?? bal?.balance ?? '0'
    }
    if (mode === 'withdraw' && coin.isUsdtFamily) {
      const bal = walletBalance.value
      return bal?.withdrawableBalance ?? bal?.balance ?? '0'
    }
    return coin.balance
  }

  /** 链上可提余额 */
  const onchainAvailableBalance = computed(() =>
    balanceForCoin(onchainSelectedCoin.value, 'withdraw'),
  )

  /** 内部转账可转余额 */
  const transferAvailableBalance = computed(() =>
    balanceForCoin(transferSelectedCoin.value, 'transfer'),
  )

  function getOnchainFee(): string {
    return onchainSelectedCoin.value?.withdrawFee ?? '0'
  }

  function getOnchainMinWithdraw(): string {
    const coin = onchainSelectedCoin.value
    if (!coin) {
      return '0'
    }
    const min = coin.minWithdraw
    if (min && Number(min) > 0) {
      return min
    }
    return NETWORK_WITHDRAW_DEFAULTS[coin.networkLabel]?.min ?? '0'
  }

  function getOnchainSubmitUnit(): string {
    return onchainSelectedCoin.value?.unit ?? 'usdt'
  }

  function getTransferSubmitUnit(): string {
    return transferSelectedCoin.value?.unit ?? 'usdt'
  }

  function symbolForCoin(coin: WithdrawCoinOption | null): string {
    if (!coin) {
      return 'USDT'
    }
    if (coin.isMainCoin && coin.unit.toUpperCase() === 'USDT') {
      return 'USDT'
    }
    if (coin.isUsdtFamily && coin.networkLabel && coin.unit.toUpperCase() !== 'USDT') {
      return `${coin.displayName || 'USDT'} (${coin.unit.toUpperCase()})`
    }
    return coin.displayName || coin.unit.toUpperCase()
  }

  function getOnchainCoinSymbol(): string {
    return symbolForCoin(onchainSelectedCoin.value)
  }

  function getTransferCoinSymbol(): string {
    return symbolForCoin(transferSelectedCoin.value)
  }

  /** @deprecated 链上请用 getOnchainSubmitUnit / 转账请用 getTransferSubmitUnit */
  function getSubmitUnit(): string {
    return getOnchainSubmitUnit()
  }

  /** @deprecated */
  function getCoinSymbol(): string {
    return getOnchainCoinSymbol()
  }

  function getSelectedFee(): string {
    return getOnchainFee()
  }

  function getSelectedMinWithdraw(): string {
    return getOnchainMinWithdraw()
  }

  async function sendEmailCode(unit: string, address: string, amount: string) {
    sendingCode.value = true
    formError.value = null
    try {
      await postForm('/uc/withdraw/email/code', { unit, address, amount })
      startCountdown()
    } catch (e) {
      formError.value = e instanceof Error ? e.message : 'i18n:error.sendFailed'
      throw e
    } finally {
      sendingCode.value = false
    }
  }

  async function submitOnchain(params: {
    unit: string; amount: string; address: string; fee: string
    vcode: string; jyPassword: string; vcode2?: string; remark?: string
  }) {
    submitting.value = true
    formError.value = null
    try {
      await postForm('/uc/withdraw/apply/code', {
        unit: params.unit,
        amount: params.amount,
        address: params.address,
        fee: params.fee,
        vcode: params.vcode,
        vtype: '2',
        jyPassword: params.jyPassword,
        vcode2: params.vcode2 ?? '',
        remark: params.remark ?? '',
      })
      await refreshBalance()
    } catch (e) {
      formError.value = e instanceof Error ? e.message : 'i18n:withdraw.submitOnChainFailed'
      throw e
    } finally {
      submitting.value = false
    }
  }

  async function submitTransfer(params: {
    unit: string; amount: string; address: string
    vcode: string; jyPassword: string; vcode2?: string; remark?: string
  }) {
    submitting.value = true
    formError.value = null
    try {
      await postForm('/uc/withdraw/transfer', {
        unit: params.unit,
        amount: params.amount,
        address: params.address,
        vcode: params.vcode,
        vtype: '2',
        jyPassword: params.jyPassword,
        vcode2: params.vcode2 ?? '',
        remark: params.remark ?? '',
      })
      await refreshBalance()
    } catch (e) {
      formError.value = e instanceof Error ? e.message : 'i18n:withdraw.transferSubmitFailed'
      throw e
    } finally {
      submitting.value = false
    }
  }

  async function refreshBalance() {
    try {
      walletBalance.value = await post<WithdrawBalance>('/uc/asset/wallet/usdt', {})
    } catch { /* ignore */ }
  }

  async function loadRecords(refresh = false) {
    if (refresh) {
      records.value = []
      recordHasMore.value = true
      onchainPage.value = 0
      transferPage.value = 0
    }
    if (!recordHasMore.value || recordLoading.value) return
    recordLoading.value = true
    try {
      const PAGE_SIZE = 15
      const [onchain, transfer] = await Promise.all([
        get<WithdrawRecord[]>('/uc/withdraw/record', { page: onchainPage.value, pageSize: PAGE_SIZE }),
        get<WithdrawRecord[]>('/uc/withdraw/transfer/record', { pageNo: transferPage.value, pageSize: PAGE_SIZE }),
      ])
      // Spring Page 响应：{ content: [], last, totalElements, ... } 或直接数组
      const toList = (raw: any): any[] =>
        Array.isArray(raw) ? raw : (raw?.content ?? [])
      const onchainList = toList(onchain)
      const transferList = toList(transfer)
      const merged = [
        ...onchainList.map(r => normalizeWithdrawRecord(r, false)),
        ...transferList.map(r => normalizeWithdrawRecord(r, true)),
      ].sort((a, b) => (b.createTime > a.createTime ? 1 : -1))
      records.value = refresh ? merged : [...records.value, ...merged]
      const onchainDone = (onchain as any)?.last ?? (onchainList.length < PAGE_SIZE)
      const transferDone = (transfer as any)?.last ?? (transferList.length < PAGE_SIZE)
      const exhausted = onchainDone && transferDone
      if (exhausted) { recordHasMore.value = false }
      else { onchainPage.value++; transferPage.value++ }
    } catch (e) {
      throw e
    } finally {
      recordLoading.value = false
    }
  }

  async function cancelRecord(id: string, isTransfer: boolean) {
    const url = isTransfer ? '/uc/withdraw/transfer/cancel' : '/uc/withdraw/cancel'
    await post(`${url}?id=${id}`, {})
    records.value = records.value.filter(r => r.id !== id || r.isTransfer !== isTransfer)
  }

  async function fetchDetail(id: string, isTransfer: boolean): Promise<WithdrawRecord> {
    const url = isTransfer ? `/uc/withdraw/transfer/record/${id}` : `/uc/withdraw/record/${id}`
    const raw = await get<unknown>(url)
    return normalizeWithdrawRecord(raw, isTransfer)
  }

  const availableBalance = onchainAvailableBalance
  const transferableBalance = transferAvailableBalance
  const googleBound = computed(() => {
    const s = security.value as (AccountAuth & Record<string, unknown>) | null
    if (!s) {
      return false
    }
    const raw = s.googleStatus ?? s.google_status
    return isSecurityFlagOn(raw)
  })
  const fundPasswordSet = computed(() => isSecurityFlagOn(security.value?.fundsVerified))

  return {
    walletBalance, security, coinInfoList, walletAddresses,
    networkList, selectedNetworkId, onchainSubCoins, onchainSubCoinsLoading,
    selectedSubCoinIndex, transferMainCoins, selectedTransferCoinIndex,
    initLoading, initError,
    sendingCode, codeCountdown, submitting, formError,
    records, recordLoading, recordHasMore,
    availableBalance, transferableBalance, googleBound, fundPasswordSet,
    onchainSelectedCoin, transferSelectedCoin, minTransferAmount,
    usdtWallets, availableNetworks,
    getFee, getMinWithdrawAmount, getWalletByNetwork,
    getOnchainFee, getOnchainMinWithdraw, getOnchainSubmitUnit, getTransferSubmitUnit,
    getOnchainCoinSymbol, getTransferCoinSymbol,
    getSelectedFee, getSelectedMinWithdraw, getSubmitUnit, getCoinSymbol,
    selectNetwork, selectSubCoin, selectTransferCoin, resetSelection, loadOnchainSubCoins,
    init, sendEmailCode, submitOnchain, submitTransfer,
    loadRecords, cancelRecord, fetchDetail, stopCountdown,
  }
})
