import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import { get, post, postForm } from '@/utils/request'
import {
  extractUsdtAvailableFromSpotAssets,
  involvesSpotTradingBridge,
  loadSpotTransferAssetContext,
  type SpotTransferAssetContext,
} from '@/utils/spotAsset'
export type WalletType = 'SPOT' | 'SWAP' | 'FOLLOW' | 'SPOT_TRADING'

/** 与可提现账户在同侧可选的账户（不含 iBit 质押钱包） */
export type OtherWalletType = 'SWAP' | 'FOLLOW' | 'SPOT_TRADING'
export const OTHER_WALLET_TYPES: OtherWalletType[] = ['SWAP', 'FOLLOW', 'SPOT_TRADING']

/**
 * 有效组合：仅「资金↔合约/跟单」或「资金↔现货交易账户」，其余回退为默认
 */
export function normalizeTransferPair(a: WalletType, b: WalletType): [WalletType, WalletType] {
  if (a === b) {
    return ['SPOT', 'SWAP']
  }
  const isSpotTradingBridge =
    (a === 'SPOT' && b === 'SPOT_TRADING') || (a === 'SPOT_TRADING' && b === 'SPOT')
  if (isSpotTradingBridge) {
    return [a, b]
  }
  const isFundingBridge =
    (a === 'SPOT' && (b === 'SWAP' || b === 'FOLLOW')) ||
    (b === 'SPOT' && (a === 'SWAP' || a === 'FOLLOW'))
  if (isFundingBridge) {
    return [a, b]
  }
  return ['SPOT', 'SWAP']
}

export interface WalletOverview {
  walletType: WalletType
  name: string
  balance: string
}

export interface TransferRecord {
  id: string
  memberId: string
  unit: string
  amount: string
  source: string
  target: string
  createTime: string
}

/** Spring Data 风格分页：/uc/asset/transfer/list 返回 data.content + data.last */
interface TransferListPage {
  content?: unknown[]
  records?: unknown[]
  list?: unknown[]
  last?: boolean
}

function normalizeTransferRecord(raw: unknown): TransferRecord {
  const r = raw && typeof raw === 'object' ? (raw as Record<string, unknown>) : {}
  return {
    id: String(r.id ?? ''),
    memberId: String(r.memberId ?? ''),
    unit: String(r.unit ?? ''),
    amount: String(r.amount ?? ''),
    source: String(r.source ?? ''),
    target: String(r.target ?? ''),
    createTime: String(r.createTime ?? ''),
  }
}

function extractTransferListPayload(raw: unknown): { list: TransferRecord[]; hasMore: boolean } {
  const PAGE_SIZE = 15
  if (Array.isArray(raw)) {
    const list = raw.map(normalizeTransferRecord)
    return { list, hasMore: list.length >= PAGE_SIZE }
  }
  if (raw && typeof raw === 'object') {
    const p = raw as TransferListPage
    const arr = p.content ?? p.records ?? p.list
    const list = Array.isArray(arr) ? arr.map(normalizeTransferRecord) : []
    if (typeof p.last === 'boolean') {
      return { list, hasMore: !p.last }
    }
    return { list, hasMore: list.length >= PAGE_SIZE }
  }
  return { list: [], hasMore: false }
}

export const useTransferStore = defineStore('transfer', () => {
  const wallets = ref<WalletOverview[]>([])
  const from = ref<WalletType>('SPOT')
  const to = ref<WalletType>('SWAP')
  const amount = ref('')
  const transferSymbol = ref('USDT')
  const spotTransferCtx = ref<SpotTransferAssetContext | null>(null)
  const loading = ref(false)
  const submitting = ref(false)
  const error = ref<string | null>(null)

  const records = ref<TransferRecord[]>([])
  const recordLoading = ref(false)
  const recordPage = ref(1)
  const recordHasMore = ref(true)

  const isSpotCoinTransfer = computed(() =>
    involvesSpotTradingBridge(from.value, to.value),
  )

  const fromBalance = computed(() => {
    if (isSpotCoinTransfer.value && spotTransferCtx.value) {
      const sym = transferSymbol.value.toUpperCase()
      if (from.value === 'SPOT_TRADING') {
        return spotTransferCtx.value.spotAvailable[sym] ?? '0'
      }
      if (from.value === 'SPOT') {
        return spotTransferCtx.value.fundAvailable[sym] ?? '0'
      }
    }
    return wallets.value.find(w => w.walletType === from.value)?.balance ?? '0'
  })

  const coinOptions = computed(() => spotTransferCtx.value?.openCoins ?? ['USDT'])

  async function loadSpotTransferAssets() {
    spotTransferCtx.value = await loadSpotTransferAssetContext()
    const coins = spotTransferCtx.value.openCoins
    if (!coins.includes(transferSymbol.value)) {
      transferSymbol.value = coins.includes('USDT') ? 'USDT' : coins[0]
    }
  }

  async function loadWallets() {
    loading.value = true
    error.value = null
    try {
      const list = await get<WalletOverview[]>('/uc/asset/wallets') ?? []
      let spotBal = '0'
      try {
        const assetRaw = await get<unknown>('spot/v1/account/asset/list')
        spotBal = extractUsdtAvailableFromSpotAssets(assetRaw)
      } catch {
        spotBal = '0'
      }
      wallets.value = [
        ...list,
        { walletType: 'SPOT_TRADING', name: '', balance: spotBal },
      ]
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'i18n:common.loadFailed'
      throw e
    } finally {
      loading.value = false
    }
  }

  function swap() {
    const [a, b] = normalizeTransferPair(to.value, from.value)
    from.value = a
    to.value = b
  }

  function setFromTo(f: WalletType, toWallet: WalletType) {
    const [a, b] = normalizeTransferPair(f, toWallet)
    from.value = a
    to.value = b
  }

  async function submit() {
    const [fromWallet, toWallet] = normalizeTransferPair(from.value, to.value)
    from.value = fromWallet
    to.value = toWallet
    if (!amount.value || Number(amount.value) <= 0) {
      error.value = 'i18n:transfer.enterAmount'
      return
    }
    if (from.value === to.value) {
      error.value = 'i18n:assets.sameAccountError'
      return
    }
    const avail = Number(fromBalance.value)
    if (Number(amount.value) > avail) {
      error.value = 'i18n:assets.insufficientBalance'
      return
    }
    submitting.value = true
    error.value = null
    try {
      if (fromWallet === 'SPOT_TRADING' || toWallet === 'SPOT_TRADING') {
        const direction = fromWallet === 'SPOT' ? 1 : 2
        await post('/spot/v1/account/transfer', {
          symbol: transferSymbol.value,
          amount: Number(amount.value),
          direction,
        })
      } else {
        await postForm('/uc/asset/transfer', {
          amount: amount.value,
          from: fromWallet,
          to: toWallet,
        })
      }
      amount.value = ''
      await loadWallets()
    } catch (e) {
      error.value = e instanceof Error ? e.message : 'i18n:assets.transferFailed'
      throw e
    } finally {
      submitting.value = false
    }
  }

  async function loadRecords(refresh = false) {
    if (refresh) {
      recordPage.value = 1
      records.value = []
      recordHasMore.value = true
    }
    if (!recordHasMore.value || recordLoading.value) return
    recordLoading.value = true
    try {
      const raw = await postForm<unknown>('/uc/asset/transfer/list', {
        pageNo: String(recordPage.value),
        pageSize: '15',
      })
      const { list, hasMore } = extractTransferListPayload(raw ?? null)
      records.value = refresh ? list : [...records.value, ...list]
      recordHasMore.value = hasMore
      if (recordHasMore.value) {
        recordPage.value++
      }
    } catch (e) {
      throw e
    } finally {
      recordLoading.value = false
    }
  }

  return {
    wallets, from, to, amount, transferSymbol, loading, submitting, error,
    records, recordLoading, recordHasMore,
    fromBalance, isSpotCoinTransfer, coinOptions,
    loadWallets, loadSpotTransferAssets, swap, setFromTo, submit, loadRecords,
  }
})
