<script setup lang="ts">
import { useI18n } from 'vue-i18n'
import { ref, computed, onMounted, watch } from 'vue'
import { get, post, postForm } from '@/utils/request'
import { useToast } from '@/composables/useToast'
import { extractUsdtAvailableFromSpotAssets } from '@/utils/spotAsset'
import type { OtherWalletType, WalletType } from '@/stores/transfer'
import { OTHER_WALLET_TYPES, normalizeTransferPair } from '@/stores/transfer'
import { walletTypeLabel } from '@/utils/walletTypeLabel'
import { involvesSpotTradingBridge, useSpotTransferCoin } from '@/composables/useSpotTransferCoin'

const { t } = useI18n()
const props = withDefaults(defineProps<{
  defaultFrom?: WalletType
  defaultTo?: WalletType
  /** 可提现账户 ↔ 现货交易账户时默认选中的币种 */
  defaultSymbol?: string
  /** 为 true 时加载币种列表后保持 defaultSymbol（IDO 等场景默认 IBIT） */
  preferDefaultSymbol?: boolean
  /** 仅可提现账户 ↔ 现货交易账户 */
  spotTradingBridgeOnly?: boolean
}>(), {
  defaultFrom: 'SPOT',
  defaultTo: 'FOLLOW',
  defaultSymbol: 'USDT',
  preferDefaultSymbol: false,
  spotTradingBridgeOnly: false,
})

const emit = defineEmits<{ (e: 'close'): void; (e: 'success'): void }>()

const toast = useToast()

function wLabel(kind: WalletType | OtherWalletType) {
  return walletTypeLabel(t, kind)
}

const SWAP_IDX   = 0
const FOLLOW_IDX = 1
const SPOT_IDX   = 2

interface AccountInfo { balance: string }
interface WalletData  { accountInfoList?: AccountInfo[] }

const walletData = ref<WalletData | null>(null)
const spotTradingBal = ref('0')
const initPair = computed(() => {
  if (props.spotTradingBridgeOnly) {
    return ['SPOT', 'SPOT_TRADING'] as [WalletType, WalletType]
  }
  return normalizeTransferPair(props.defaultFrom, props.defaultTo)
})
const transferFrom = ref<WalletType>(initPair.value[0])
const transferTo = ref<WalletType>(initPair.value[1])

const transferOtherTypes = computed((): OtherWalletType[] => {
  if (props.spotTradingBridgeOnly) {
    return ['SPOT_TRADING']
  }
  return [...OTHER_WALLET_TYPES]
})
const transferAmount = ref('')
const transferLoading = ref(false)
const transferError  = ref('')

const {
  symbol: transferSymbol,
  assetsLoading: coinAssetsLoading,
  coinOptions,
  loadAssets: loadCoinAssets,
  availableFor,
} = useSpotTransferCoin(props.defaultSymbol, {
  preferInitialSymbol: props.preferDefaultSymbol,
})

const isSpotCoinTransfer = computed(() =>
  involvesSpotTradingBridge(transferFrom.value, transferTo.value),
)

const fromAvailable = computed(() => {
  if (isSpotCoinTransfer.value) {
    return availableFor(transferFrom.value, transferSymbol.value)
  }
  if (transferFrom.value === 'SPOT_TRADING') {
    return spotTradingBal.value
  }
  const idxMap: Record<'SWAP' | 'FOLLOW' | 'SPOT', number> = { SWAP: SWAP_IDX, FOLLOW: FOLLOW_IDX, SPOT: SPOT_IDX }
  const idx = idxMap[transferFrom.value as 'SWAP' | 'FOLLOW' | 'SPOT']
  return walletData.value?.accountInfoList?.[idx]?.balance ?? '0'
})

const displayCoinUnit = computed(() => {
  if (isSpotCoinTransfer.value) {
    return transferSymbol.value
  }
  return 'USDT'
})

function fmt(n: string | number, decimals = 2) {
  return Number(n).toLocaleString('en-US', { minimumFractionDigits: decimals, maximumFractionDigits: decimals })
}

async function swapTransfer() {
  if (props.spotTradingBridgeOnly) {
    transferFrom.value = transferFrom.value === 'SPOT' ? 'SPOT_TRADING' : 'SPOT'
    transferTo.value = transferFrom.value === 'SPOT' ? 'SPOT_TRADING' : 'SPOT'
    transferAmount.value = ''
    void loadCoinAssets()
    return
  }
  const [a, b] = normalizeTransferPair(transferTo.value, transferFrom.value)
  transferFrom.value = a
  transferTo.value = b
}

async function doTransfer() {
  transferError.value = ''
  const [fromWallet, toWallet] = normalizeTransferPair(transferFrom.value, transferTo.value)
  transferFrom.value = fromWallet
  transferTo.value = toWallet
  if (transferFrom.value === transferTo.value) { transferError.value = t('assets.sameAccountError'); return }
  const amt = Number(transferAmount.value)
  if (!amt || amt <= 0) { transferError.value = t('assets.amountError'); return }
  if (amt > Number(fromAvailable.value)) { transferError.value = t('assets.insufficientBalance'); return }
  transferLoading.value = true
  try {
    if (props.spotTradingBridgeOnly || fromWallet === 'SPOT_TRADING' || toWallet === 'SPOT_TRADING') {
      const direction = fromWallet === 'SPOT' ? 1 : 2
      await post('/spot/v1/account/transfer', {
        symbol: transferSymbol.value,
        amount: amt,
        direction,
      })
    } else {
      await postForm('/uc/asset/transfer', { amount: transferAmount.value, from: fromWallet, to: toWallet })
    }
    toast.success(t('assets.transferSuccess'))
    if (props.spotTradingBridgeOnly) {
      await loadCoinAssets()
    }
    emit('success')
    emit('close')
  } catch (e) {
    transferError.value = e instanceof Error ? e.message : t('assets.transferFailed')
  } finally {
    transferLoading.value = false
  }
}

async function refreshLegacyBalances() {
  try {
    walletData.value = await get<WalletData>('/swap/wallet-new/get')
  } catch { /* silent */ }
  try {
    const raw = await get<unknown>('spot/v1/account/asset/list')
    spotTradingBal.value = extractUsdtAvailableFromSpotAssets(raw)
  } catch {
    spotTradingBal.value = '0'
  }
}

watch(isSpotCoinTransfer, (v) => {
  if (v) {
    void loadCoinAssets()
  }
}, { immediate: true })

watch([transferFrom, transferTo], async ([f, toW]) => {
  transferAmount.value = ''
  if (involvesSpotTradingBridge(f, toW)) {
    void loadCoinAssets()
  }
})

watch(transferSymbol, () => {
  transferAmount.value = ''
})

onMounted(() => {
  if (props.spotTradingBridgeOnly) {
    const [from, to] = normalizeTransferPair(props.defaultFrom, props.defaultTo)
    transferFrom.value = from
    transferTo.value = to
    void loadCoinAssets()
    return
  }
  void refreshLegacyBalances()
  if (isSpotCoinTransfer.value) {
    void loadCoinAssets()
  }
})
</script>

<template>
  <div class="tm-overlay" @click.self="emit('close')">
    <div class="tm-modal">
      <div class="tm-header">
        <h3 class="tm-title">{{ t('assets.accountTransfer') }}</h3>
        <button class="tm-close" @click="emit('close')">✕</button>
      </div>

      <div v-if="isSpotCoinTransfer" class="tm-coin-row">
        <p class="tm-lbl">{{ t('spot.transferModal.selectCoin') }}</p>
        <select v-model="transferSymbol" class="tm-select" :disabled="coinAssetsLoading">
          <option v-for="c in coinOptions" :key="c" :value="c">{{ c }}</option>
        </select>
      </div>

      <div class="tm-accounts">
        <div class="tm-side">
          <p class="tm-lbl">{{ t('assets.transferFrom') }}</p>
          <div v-if="transferFrom === 'SPOT'" class="tm-select tm-select--readonly">{{ wLabel('SPOT') }}</div>
          <select v-else v-model="transferFrom" class="tm-select">
            <option v-for="wt in transferOtherTypes" :key="wt" :value="wt">{{ wLabel(wt) }}</option>
          </select>
          <p class="tm-bal">
            {{ t('assets.availableCoin', { available: fmt(fromAvailable), coin: displayCoinUnit }) }}
          </p>
        </div>
        <button class="tm-swap-btn" @click="swapTransfer">⇄</button>
        <div class="tm-side">
          <p class="tm-lbl">{{ t('assets.transferTo') }}</p>
          <div
            v-if="transferFrom === 'SWAP' || transferFrom === 'FOLLOW' || transferFrom === 'SPOT_TRADING'"
            class="tm-select tm-select--readonly"
          >
            {{ wLabel('SPOT') }}
          </div>
          <select v-else v-model="transferTo" class="tm-select">
            <option v-for="wt in transferOtherTypes" :key="wt" :value="wt">{{ wLabel(wt) }}</option>
          </select>
        </div>
      </div>

      <div class="tm-amount-hd">
        <label class="tm-label">
          {{ isSpotCoinTransfer ? t('assets.amountCoin', { coin: displayCoinUnit }) : t('assets.amountUsdt') }}
        </label>
        <button class="tm-all-btn" type="button" @click="transferAmount = fromAvailable">{{ t('common.all') }}</button>
      </div>
      <input v-model="transferAmount" type="number" class="tm-input" placeholder="0.00" min="0" />

      <p class="tm-hint">{{ t('assets.freeTransfer') }}</p>
      <p v-if="transferError" class="tm-error">{{ transferError }}</p>

      <div class="tm-actions">
        <button class="tm-btn-cancel" type="button" @click="emit('close')">{{ t('common.cancel') }}</button>
        <button
          class="tm-btn-confirm"
          type="button"
          :disabled="transferLoading || coinAssetsLoading"
          @click="doTransfer"
        >
          {{ transferLoading ? t('assets.transferring') : t('assets.confirmTransferBtn') }}
        </button>
      </div>
    </div>
  </div>
</template>

<style scoped>
.tm-overlay {
  position: fixed; inset: 0;
  background: rgba(0,0,0,.6);
  display: flex; align-items: center; justify-content: center;
  z-index: 1000;
}
.tm-modal {
  width: 460px;
  max-width: calc(100vw - 32px);
  padding: 24px;
  background: #1a1a1a;
  border: 1px solid rgba(255,255,255,0.08);
  border-radius: 12px;
  box-shadow: 0 16px 48px rgba(0,0,0,0.6);
}
.tm-header {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 24px;
}
.tm-title { font-size: 18px; font-weight: 600; color: var(--color-text-primary); }
.tm-close {
  background: none; border: none;
  color: var(--color-text-muted); font-size: 18px; cursor: pointer;
}
.tm-close:hover { color: var(--color-text-primary); }

.tm-coin-row { margin-bottom: 16px; }

.tm-accounts {
  display: flex; align-items: flex-start; gap: 12px;
  margin-bottom: 20px;
}
.tm-side { flex: 1; }
.tm-lbl  { font-size: 12px; color: var(--color-text-muted); margin-bottom: 6px; }
.tm-bal  { font-size: 12px; color: var(--color-text-muted); margin-top: 6px; }
.tm-select {
  width: 100%; padding: 10px 12px;
  background: #111;
  border: 1px solid rgba(255,255,255,0.12);
  border-radius: var(--radius-md);
  color: #fff;
  font-size: 14px; cursor: pointer;
  appearance: auto;
}
.tm-select option {
  background: #1a1a1a;
  color: #fff;
}
.tm-select--readonly {
  cursor: default;
  color: var(--color-text-secondary);
}
.tm-swap-btn {
  margin-top: 24px;
  width: 36px; height: 36px;
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 50%;
  color: var(--color-text-secondary);
  font-size: 16px; cursor: pointer; flex-shrink: 0;
  display: flex; align-items: center; justify-content: center;
}
.tm-swap-btn:hover { color: var(--color-primary); border-color: var(--color-primary); }

.tm-amount-hd {
  display: flex; align-items: center; justify-content: space-between;
  margin-bottom: 8px;
}
.tm-label { font-size: 13px; color: var(--color-text-muted); }
.tm-all-btn {
  background: none; border: none;
  color: var(--color-primary); font-size: 13px; cursor: pointer;
}
.tm-input {
  width: 100%; padding: 10px 12px;
  background: var(--color-bg-input, #111);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text-primary); font-size: 14px;
  box-sizing: border-box;
}
.tm-input:focus { outline: none; border-color: var(--color-primary); }

.tm-hint  { font-size: 12px; color: var(--color-text-muted); margin: 8px 0 16px; }
.tm-error { font-size: 12px; color: var(--color-down); margin-bottom: 12px; }

.tm-actions { display: flex; gap: 12px; margin-top: 8px; }
.tm-btn-cancel {
  flex: 1; padding: 10px;
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: var(--radius-md);
  color: var(--color-text-secondary); cursor: pointer;
}
.tm-btn-confirm {
  flex: 2; padding: 10px;
  background: var(--color-primary); border: none;
  border-radius: var(--radius-md);
  color: #000; font-weight: 600; cursor: pointer;
}
.tm-btn-confirm:disabled { opacity: 0.6; cursor: not-allowed; }
</style>
