<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { useI18n } from 'vue-i18n'
import {
  fetchMinOpenStakingConfig,
  fetchStakingConfigList,
  fetchStakingTeamOverview,
  IDO_SUBSCRIPTION_PRICE_USDT,
  submitStakeByUsdt,
  type StakingConfig,
} from '@/api/staking'
import { loadFundCoinBalance, loadStakingWalletSnapshot, STAKING_COIN_UNIT } from '@/utils/stakingWallet'
import {
  estimatedUnlockDate,
  formatUnlockDate,
  lockMonthsFromConfig,
  releaseMonthsFromConfig,
} from '@/utils/stakingDisplay'
import { useToast } from '@/composables/useToast'
import { AUTH_ENABLED } from '@/utils/featureFlags'
import TransferModal from '@/components/common/TransferModal.vue'
import idoHero from '@/assets/finance/ido-hero.png'
import idoHero2x from '@/assets/finance/ido-hero@2x.png'

const { t } = useI18n()
const route = useRoute()
const router = useRouter()
const toast = useToast()
const config = ref<StakingConfig | null>(null)
const loading = ref(true)
const submitting = ref(false)
/** 用户输入的 USDT 金额 */
const subscribeUsdt = ref('')
const error = ref<string | null>(null)
const availableUsdtBal = ref('0')
const showTransfer = ref(false)
const teamCount = ref(0)
const lockedTotal = ref('0')
const configIdParam = computed(() => {
  const raw = route.params.configId
  if (raw === undefined || raw === '' || raw === 'ido') return null
  const id = Number(raw)
  return Number.isFinite(id) && id > 0 ? id : null
})

const lockMonths = computed(() => (config.value ? lockMonthsFromConfig(config.value) : 0))
const releaseMonths = computed(() => (config.value ? releaseMonthsFromConfig(config.value) : 0))

const rulesText = computed(() => {
  if (!config.value) return ''
  if (config.value.releaseType === 1 && releaseMonths.value > 0) {
    return t('finance.idoRuleBatch', {
      lock: lockMonths.value,
      release: releaseMonths.value,
    })
  }
  return t('finance.idoRuleOnce', { lock: lockMonths.value })
})

const displayCoinUnit = computed(() => {
  const u = config.value?.coinUnit?.trim()
  if (!u) return 'iBit'
  return u.toUpperCase() === 'IBIT' ? 'iBit' : u
})

function fmtAmount(n: string | number, maxFrac = 8) {
  const v = Number(n)
  if (!Number.isFinite(v)) return '0'
  return v.toLocaleString('en-US', {
    minimumFractionDigits: 0,
    maximumFractionDigits: maxFrac,
  })
}

/** IDO 固定认购价 0.6 USDT */
const unitPriceUsdt = computed(() => IDO_SUBSCRIPTION_PRICE_USDT)

/** USDT → iBit 折算（固定价） */
const subscribeIbit = computed(() => {
  const usdt = Number(subscribeUsdt.value)
  if (!Number.isFinite(usdt) || usdt <= 0) {
    return '0'
  }
  const ibit = usdt / IDO_SUBSCRIPTION_PRICE_USDT
  return ibit.toLocaleString('en-US', {
    minimumFractionDigits: 0,
    maximumFractionDigits: 8,
  })
})

const subscribeIbitNum = computed(() => {
  const s = subscribeIbit.value.replace(/,/g, '')
  const n = Number(s)
  return Number.isFinite(n) ? n : 0
})

function fillAllAvailable() {
  const avail = Number(availableUsdtBal.value)
  if (avail > 0) {
    subscribeUsdt.value = String(avail)
  }
}

function openUsdtTransfer() {
  if (!AUTH_ENABLED) {
    router.push({ name: 'login', query: { redirect: route.fullPath } })
    return
  }
  showTransfer.value = true
}

function stakingCoinUnit() {
  return config.value?.coinUnit?.trim() || STAKING_COIN_UNIT
}

async function refreshAvailableUsdt() {
  try {
    availableUsdtBal.value = await loadFundCoinBalance('USDT')
  } catch {
    availableUsdtBal.value = '0'
  }
}

async function refreshOverviewStats() {
  const unit = stakingCoinUnit()
  try {
    const team = await fetchStakingTeamOverview()
    teamCount.value = Number(team.teamNum) || 0
    const lock = Number(team.lockTotal)
    if (Number.isFinite(lock)) {
      lockedTotal.value = String(lock)
      return
    }
  } catch {
    // 回退质押钱包余额
  }
  try {
    const stakingSnap = await loadStakingWalletSnapshot(unit)
    const total = Number(stakingSnap.available) + Number(stakingSnap.locked)
    lockedTotal.value = Number.isFinite(total) ? String(total) : '0'
  } catch {
    lockedTotal.value = '0'
  }
}

function goToMyTeam() {
  router.push({ name: 'finance-team' })
}

function goToStakingAccount() {
  router.push({ name: 'assets', query: { tab: 'staking' } })
}

async function onTransferSuccess() {
  showTransfer.value = false
  await load({ silent: true })
}

const unlockDateText = computed(() => {
  if (!config.value) return '—'
  return formatUnlockDate(estimatedUnlockDate(config.value))
})

async function resolveConfig() {
  if (configIdParam.value != null) {
    const list = await fetchStakingConfigList()
    const arr = Array.isArray(list) ? list : []
    const found = arr.find(c => c.id === configIdParam.value)
    if (found) return found
  }
  return fetchMinOpenStakingConfig()
}

async function load(opts?: { silent?: boolean }) {
  if (!opts?.silent) {
    loading.value = true
  }
  error.value = null
  try {
    config.value = await resolveConfig()
    if (!config.value) {
      error.value = t('finance.configNotFound')
      return
    }
    await Promise.all([refreshAvailableUsdt(), refreshOverviewStats()])
  } catch (e) {
    error.value = e instanceof Error ? e.message : t('common.loadFailed')
    config.value = null
  } finally {
    if (!opts?.silent) {
      loading.value = false
    }
  }
}

async function onSubmit() {
  if (!AUTH_ENABLED) {
    router.push({ name: 'login', query: { redirect: route.fullPath } })
    return
  }
  if (!config.value) return

  const usdt = Number(subscribeUsdt.value)
  if (!usdt || usdt <= 0) {
    toast.error(t('finance.amountRequired'))
    return
  }

  const ibit = subscribeIbitNum.value
  if (!ibit || ibit <= 0) {
    toast.error(t('finance.amountRequired'))
    return
  }
  if (ibit < Number(config.value.minAmount)) {
    toast.error(t('finance.belowMin', { min: config.value.minAmount }))
    return
  }
  const max = Number(config.value.maxAmount)
  if (max > 0 && ibit > max) {
    toast.error(t('finance.aboveMax', { max: config.value.maxAmount }))
    return
  }
  if (usdt > Number(availableUsdtBal.value)) {
    toast.error(t('assets.insufficientBalance'))
    return
  }

  submitting.value = true
  try {
    await submitStakeByUsdt(config.value.id, subscribeUsdt.value)
    toast.success(t('finance.stakeSuccess'))
    subscribeUsdt.value = ''
    await load({ silent: true })
    await refreshOverviewStats()
  } catch (e) {
    toast.error(e instanceof Error ? e.message : t('finance.stakeFailed'))
  } finally {
    submitting.value = false
  }
}

onMounted(() => load())

watch(() => route.params.configId, () => load())
</script>

<template>
  <main class="ido-page page-main">
    <div v-if="loading" class="loading-state page-container">
      <div class="spinner" />
    </div>

    <template v-else-if="config">
      <section class="ido-hero">
        <div class="page-container hero-inner">
          <div class="hero-copy">
            <h1 class="hero-title">{{ t('finance.idoTitle') }}</h1>
            <p class="hero-rule">
              <span class="hero-rule-label">{{ t('finance.idoRuleLabel') }}</span>
              {{ rulesText }}
            </p>
          </div>
          <div class="hero-art">
            <img
              :src="idoHero"
              :srcset="`${idoHero} 1x, ${idoHero2x} 2x`"
              alt=""
              class="hero-img"
            />
          </div>
        </div>
      </section>

      <section class="ido-overview-section page-container">
        <div class="ido-overview-grid">
          <button type="button" class="ido-overview-card" @click="goToMyTeam">
            <span class="ido-overview-label">
              {{ t('finance.myTeam') }}
              <span class="ido-overview-chevron" aria-hidden="true">&gt;</span>
            </span>
            <span class="ido-overview-value num">{{ fmtAmount(teamCount, 0) }}</span>
          </button>
          <button type="button" class="ido-overview-card" @click="goToStakingAccount">
            <span class="ido-overview-label">
              {{ t('assets.stakingTotal') }}
              <span class="ido-overview-chevron" aria-hidden="true">&gt;</span>
            </span>
            <span class="ido-overview-value num">{{ fmtAmount(lockedTotal, 2) }}</span>
          </button>
        </div>
      </section>

      <section class="ido-form-section page-container">
        <h2 class="section-title">{{ t('finance.joinPresale') }}</h2>

        <div class="subscribe-grid">
          <div class="subscribe-col subscribe-col--label">
            <label class="field-label">{{ t('finance.correspondingPrice') }}</label>
          </div>
          <div class="subscribe-col subscribe-col--label">
            <label class="field-label">{{ t('finance.subscribeQty') }}</label>
          </div>

          <div class="subscribe-col subscribe-col--meta">
            <div class="meta-line-row">
              <p class="meta-line">
                {{ t('finance.availableUsdt') }}:
                <span class="meta-amount num">{{ fmtAmount(availableUsdtBal, 2) }}</span>
                USDT
              </p>
              <button
                type="button"
                class="link-action-btn"
                @click="fillAllAvailable"
              >
                {{ t('common.all') }}
              </button>
            </div>
          </div>
          <div class="subscribe-col subscribe-col--meta">
            <p class="meta-line">
              {{ t('finance.ibitUnitPriceLine', { price: unitPriceUsdt > 0 ? fmtAmount(unitPriceUsdt, 4) : '—' }) }}
            </p>
          </div>

          <div class="subscribe-col subscribe-col--input subscribe-col--price">
            <div class="price-transfer-row">
              <div class="field-input-wrap">
                <input
                  v-model="subscribeUsdt"
                  type="number"
                  class="field-input"
                  min="0"
                  placeholder="0.00"
                  step="any"
                />
                <span class="field-unit">USDT</span>
              </div>
              <button type="button" class="transfer-btn" @click="openUsdtTransfer">
                {{ t('finance.ibitTransfer') }}
              </button>
            </div>
          </div>
          <div class="subscribe-col subscribe-col--input">
            <div class="field-input-wrap field-input-wrap--readonly">
              <input
                :value="subscribeIbit"
                type="text"
                class="field-input field-input--readonly"
                readonly
                tabindex="-1"
                aria-readonly="true"
                placeholder="0"
              />
              <span class="field-unit">{{ displayCoinUnit }}</span>
            </div>
          </div>
        </div>

        <button
          type="button"
          class="confirm-btn"
          :disabled="submitting || !unitPriceUsdt"
          @click="onSubmit"
        >
          {{ submitting ? t('common.loading') : t('finance.confirmPresale') }}
        </button>

        <p class="unlock-tip">
          {{ t('finance.estimatedUnlockLine', { date: unlockDateText }) }}
        </p>

        <p v-if="!AUTH_ENABLED" class="avail-tip">
          {{ t('finance.loginToStake') }}
          <RouterLink to="/login" class="login-link">{{ t('header.login') }}</RouterLink>
        </p>
      </section>
    </template>

    <div v-else class="empty page-container">
      <p>{{ error || t('finance.configNotFound') }}</p>
      <RouterLink to="/" class="retry-link">{{ t('nav.home') }}</RouterLink>
    </div>

    <TransferModal
      v-if="showTransfer"
      prefer-default-symbol
      default-from="SWAP"
      default-to="SPOT"
      default-symbol="USDT"
      @close="showTransfer = false"
      @success="onTransferSuccess"
    />
  </main>
</template>

<style scoped>
.ido-page {
  padding-bottom: var(--space-16);
}

.loading-state,
.empty {
  padding-top: calc(var(--header-height) + var(--space-16));
  text-align: center;
  color: var(--color-text-secondary);
}

.spinner {
  width: 36px;
  height: 36px;
  margin: 0 auto;
  border-radius: 50%;
  border: 2px solid var(--color-border);
  border-top-color: var(--color-primary);
  animation: spin 0.8s linear infinite;
}

@keyframes spin {
  to { transform: rotate(360deg); }
}

.retry-link {
  color: var(--color-primary);
  margin-top: var(--space-4);
  display: inline-block;
}

.ido-hero {
  padding-top: calc(var(--header-height) + var(--space-10));
  padding-bottom: var(--space-8);
  background: linear-gradient(180deg, rgba(240, 185, 11, 0.04) 0%, transparent 70%);
}

.hero-inner {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-8);
  min-height: 280px;
  max-width: 960px;
}

.hero-copy {
  flex: 1;
  min-width: 0;
  max-width: 560px;
}

.hero-title {
  font-size: clamp(40px, 6vw, 64px);
  font-weight: 700;
  color: #fff;
  line-height: 1.1;
  margin: 0 0 var(--space-6);
  letter-spacing: 0.02em;
}

.hero-rule {
  font-size: 15px;
  line-height: 1.75;
  color: rgba(255, 255, 255, 0.75);
  margin: 0;
}

.hero-rule-label {
  color: rgba(255, 255, 255, 0.55);
  margin-right: 4px;
}

.hero-art {
  flex-shrink: 0;
  width: min(420px, 42vw);
  display: flex;
  justify-content: flex-end;
}

.hero-img {
  width: 100%;
  height: auto;
  max-height: 320px;
  object-fit: contain;
  display: block;
}

.ido-overview-section {
  max-width: 960px;
  padding-bottom: var(--space-6);
}

.ido-overview-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  gap: var(--space-4);
}

.ido-overview-card {
  display: flex;
  flex-direction: column;
  align-items: flex-start;
  gap: var(--space-4);
  padding: var(--space-5) var(--space-6);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.1);
  border-radius: 16px;
  cursor: pointer;
  text-align: left;
  transition: border-color 0.2s, background 0.2s;
}

.ido-overview-card:hover {
  border-color: rgba(240, 185, 11, 0.35);
  background: rgba(240, 185, 11, 0.06);
}

.ido-overview-label {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 14px;
  color: rgba(255, 255, 255, 0.55);
}

.ido-overview-chevron {
  color: rgba(255, 255, 255, 0.35);
  font-size: 13px;
}

.ido-overview-value {
  font-size: clamp(28px, 4vw, 36px);
  font-weight: 600;
  color: #fff;
  line-height: 1.1;
  font-variant-numeric: tabular-nums;
}

.ido-form-section {
  max-width: 960px;
  padding-bottom: var(--space-8);
}

.section-title {
  font-size: 22px;
  font-weight: 600;
  color: #fff;
  text-align: left;
  margin: 0 0 var(--space-8);
}

.subscribe-grid {
  display: grid;
  grid-template-columns: 1fr 1fr;
  column-gap: var(--space-6);
  row-gap: var(--space-3);
  margin-bottom: var(--space-8);
  align-items: center;
}

.subscribe-col--label {
  align-self: end;
}

.subscribe-col--meta {
  min-height: 20px;
}

.meta-line-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: var(--space-3);
}

.meta-line {
  margin: 0;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.45);
  line-height: 1.4;
  min-width: 0;
}

.meta-amount {
  color: var(--color-primary);
  font-weight: 600;
  margin: 0 4px;
}

.subscribe-col--input .field-input-wrap {
  width: 100%;
}

.price-transfer-row {
  display: flex;
  align-items: center;
  gap: var(--space-3);
  width: 100%;
}

.price-transfer-row .field-input-wrap {
  flex: 1;
  min-width: 0;
}

.transfer-btn {
  flex-shrink: 0;
  height: 52px;
  padding: 0 var(--space-5);
  background: transparent;
  border: 1px solid var(--color-primary);
  border-radius: 12px;
  color: var(--color-primary);
  font-size: 14px;
  font-weight: 500;
  cursor: pointer;
  white-space: nowrap;
  transition: background 0.2s, color 0.2s;
}

.transfer-btn:hover {
  background: rgba(240, 185, 11, 0.1);
}

.field-label {
  font-size: 14px;
  color: rgba(255, 255, 255, 0.55);
}

.link-action-btn {
  padding: 0;
  border: none;
  background: transparent;
  font-size: 13px;
  color: var(--color-primary);
  cursor: pointer;
  white-space: nowrap;
}

.link-action-btn:hover {
  opacity: 0.85;
}

.field-input-wrap {
  display: flex;
  align-items: center;
  height: 52px;
  padding: 0 var(--space-4);
  background: rgba(255, 255, 255, 0.04);
  border: 1px solid rgba(255, 255, 255, 0.12);
  border-radius: 12px;
}

.field-input-wrap--readonly {
  background: rgba(255, 255, 255, 0.02);
}

.field-input {
  flex: 1;
  min-width: 0;
  background: transparent;
  border: none;
  outline: none;
  color: #fff;
  font-size: 16px;
  font-variant-numeric: tabular-nums;
}

.field-input::placeholder {
  color: rgba(255, 255, 255, 0.25);
}

.field-input--readonly {
  cursor: default;
  pointer-events: none;
}

.field-unit {
  flex-shrink: 0;
  margin-left: var(--space-3);
  font-size: 14px;
  color: rgba(255, 255, 255, 0.45);
}

.confirm-btn {
  display: block;
  width: 100%;
  max-width: 360px;
  margin: 0 auto var(--space-5);
  padding: 14px var(--space-8);
  background: var(--color-primary);
  color: #000;
  font-size: 16px;
  font-weight: 600;
  border: none;
  border-radius: 999px;
  cursor: pointer;
  transition: opacity 0.2s;
}

.confirm-btn:hover:not(:disabled) {
  opacity: 0.9;
}

.confirm-btn:disabled {
  opacity: 0.5;
  cursor: not-allowed;
}

.unlock-tip {
  text-align: center;
  font-size: 13px;
  color: rgba(255, 255, 255, 0.4);
  margin: 0 0 var(--space-3);
}

.avail-tip {
  text-align: center;
  font-size: 12px;
  color: rgba(255, 255, 255, 0.35);
  margin: 0;
}

.login-link {
  color: var(--color-primary);
  margin-left: 6px;
  text-decoration: none;
}

@media (max-width: 900px) {
  .hero-inner {
    flex-direction: column;
    align-items: flex-start;
    min-height: auto;
  }

  .hero-art {
    width: 100%;
    max-width: 360px;
    margin: 0 auto;
  }
}

@media (max-width: 640px) {
  .ido-overview-grid {
    gap: var(--space-3);
  }

  .ido-overview-card {
    padding: var(--space-4) var(--space-5);
  }

  .subscribe-grid {
    grid-template-columns: 1fr;
  }

  .ido-hero {
    padding-top: calc(var(--header-height) + var(--space-6));
  }
}
</style>
