<script setup lang="ts">
import { ref, computed, onMounted, watch, watchEffect } from 'vue'
import { useI18n } from 'vue-i18n'
import { useRoute, useRouter } from 'vue-router'
import { get, post, put } from '@/utils/request'
import request from '@/utils/request'
import { useAuthStore } from '@/stores/auth'
import { useCopyTradingStore } from '@/stores/copyTrading'

const { t } = useI18n()
const route  = useRoute()
const router = useRouter()
const auth   = useAuthStore()
const copyTradingStore = useCopyTradingStore()
const traderId = computed(() => route.params.id as string)

/** 跟单设置「资金实力」与 trader-info 的 moneyStrength 档位对齐：&lt;5K / ≥5K 等 */
const COPY_FUND_STRENGTH_THRESHOLD = 5000

function fundStrengthTierLabels(): { high: string; low: string } {
  const fmt = COPY_FUND_STRENGTH_THRESHOLD.toLocaleString('en-US', {
    minimumFractionDigits: 2,
    maximumFractionDigits: 2,
  })
  return {
    high: `资金实力 ≥${fmt} USDT`,
    low: `资金实力 ＜${fmt} USDT`,
  }
}

/**
 * trader-info 中 moneyStrength 多为档位文案（如 "&lt;5K"），也可能为可解析数字或科学计数法。
 */
function levelLabel(level: number): string {
  if (!level) {
    return ''
  }
  if (level === 1) {
    return '初级'
  }
  return `L${level}`
}

function formatCopyFundStrengthDisplay(raw: string | undefined): string {
  if (raw == null || raw === '') {
    return '资金实力 --'
  }
  const trimmed = String(raw).trim()
  const compact = trimmed.replace(/\s/g, '')
  const { high, low } = fundStrengthTierLabels()

  if (compact === '<5K' || trimmed === '＜5K' || /^[<＜]5K$/u.test(compact)) {
    return low
  }
  if (compact === '>=5K' || compact === '>5K' || /^≥5K$/u.test(compact)) {
    return high
  }

  const n = parseFloat(trimmed.replace(/,/g, ''))
  if (Number.isFinite(n)) {
    if (n >= COPY_FUND_STRENGTH_THRESHOLD) {
      return high
    }
    return low
  }

  return `资金实力 ${trimmed}`
}

// ── Types ──────────────────────────────────────────────────────────────────
interface TraderDetail {
  id: string | number
  name: string
  avatar: string | null
  verified: boolean
  lossless: boolean
  /** 交易员等级（traderLevelId），用于 L1 / 初级 徽标 */
  level: number
  /** 近 14 天收益率（%） */
  profit14d: number
  /** 近 14 天收益（USDT），无数据时为 null */
  profit14Usdt: number | null
  /** 近 14 天胜率（%） */
  winRate14: number
  /** 分润比例 0–100 */
  profitSharePct: number
  followers: number
  maxFollowers: number
  /** 已入驻天数 */
  registerDays: number
  totalProfit: string
  /** 累计跟单盈利额（USDT），跟单户侧汇总口径 */
  totalFollowProfit: number
  /** 累计跟单人数（历史或总额度，依后端字段） */
  totalFollowCount: number
  /** 累计交易天数 */
  tradingDaysTotal: number
  /** 后端资金实力原始值（follow_setting_screen / trader map 的 moneyStrength） */
  moneyStrength: string
  minFollow: string
  /** 带单展示：天数与笔数 */
  days: number
  trades: number
  description: string
  /** 风格标签文案（trader-info 或 tag 接口） */
  styleTags: string[]
}

interface Position {
  id: string | number
  symbol: string
  direction: number  // 0=long 1=short
  positionType: string
  openPrice: number
  closePrice: number
  amount: number
  lever: number
  profit: number
  profitRate: number
  openTime: number
  closeTime?: number
}

// ── State ──────────────────────────────────────────────────────────────────
const trader        = ref<TraderDetail | null>(null)
const loading       = ref(true)
const loadError     = ref('')
const isFavorited   = ref(false)
const isFollowing   = ref(false)
const traderSymbols = ref<string[]>([])
const contractsOpen = ref(true)

/** 外链 OSS 头像需 no-referrer，否则易触发防盗链导致加载失败（与个人中心一致） */
const traderAvatarLoadError = ref(false)
watch(
  () => [trader.value?.id, trader.value?.avatar] as const,
  () => {
    traderAvatarLoadError.value = false
  },
)

const positions     = ref<Position[]>([])
const historyOrders = ref<Position[]>([])
const activeTab     = ref<'positions' | 'history'>('positions')
const posLoading    = ref(false)
const histLoading   = ref(false)

// Follow
const followLoading   = ref(false)
const followError     = ref('')
const showFollowModal = ref(false)

// ── Mappers ────────────────────────────────────────────────────────────────
// eslint-disable-next-line @typescript-eslint/no-explicit-any
function extractStyleTags(r: any): string[] {
  const raw = r.tagList ?? r.tags ?? r.traderTagList ?? r.traderTags
  if (!Array.isArray(raw)) {
    return []
  }
  return raw
    .map((t: any) => (t && typeof t === 'object' ? (t.tagName ?? t.name ?? '') : String(t)))
    .filter((s: string) => !!s && String(s).trim() !== '')
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function mapTrader(r: any): TraderDetail {
  const profit14d = parseFloat(r.dayYield14 ?? r.dayYield30 ?? r.roi30 ?? r.profit30d ?? '0') || 0
  const followers = parseInt(r.followCustomer ?? r.followCount ?? r.followers ?? '0', 10) || 0
  const maxFollowers = parseInt(r.maxFollow ?? r.maxFollowCount ?? '0', 10) || 0
  const registerDays = parseInt(r.settledDays ?? r.registerDays ?? '0', 10) || 0
  const tradingDaysTotal = parseInt(r.tradingDays ?? r.tradeDays ?? '0', 10) || 0
  const daysForLead = parseInt(r.tradingDays ?? r.registerDays ?? r.days ?? '0', 10) || 0
  const trades =
    parseInt(r.orderDealNum ?? r.totalOrders ?? r.tradeCount ?? r.orderDeal14 ?? r.trades ?? '0', 10) || 0
  const minFollow = String(r.minFollowAmount ?? r.minCopyAmount ?? '100')
  const v = parseFloat(r.profitAmount ?? r.totalProfit ?? '0') || 0
  const totalProfit =
    (v >= 0 ? '+' : '') + v.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
  const moneyStrength =
    r.moneyStrength != null && String(r.moneyStrength).trim() !== '' ? String(r.moneyStrength).trim() : ''

  const raw14Usdt =
    r.profitAmount14 ?? r.dayProfit14 ?? r.income14 ?? r.profit14Amount ?? r.yield14Profit ?? null
  let profit14Usdt: number | null = null
  if (raw14Usdt != null && raw14Usdt !== '') {
    const p = parseFloat(String(raw14Usdt))
    if (Number.isFinite(p)) {
      profit14Usdt = p
    }
  }

  const winRate14 = parseFloat(r.winRate14 ?? r.winRate ?? r.winningRate ?? '0') || 0
  const profitSharePct = parseFloat(r.dividendPercent ?? r.profitShare ?? r.shareRatio ?? '0') || 0

  const totalFollowProfit =
    parseFloat(r.totalFollowProfit ?? r.followTotalProfit ?? r.sumFollowProfit ?? r.profitAmount ?? '0') ||
    0
  const totalFollowCount =
    parseInt(
      r.historyFollowNum ??
        r.totalFollowCustomer ??
        r.totalFollowers ??
        r.hisFollowCustomer ??
        r.followCustomer ??
        '0',
      10,
    ) || 0

  return {
    id: r.id ?? r.traderId ?? r.memberId,
    name: r.nickname ?? r.nickName ?? r.name ?? '交易员',
    avatar: r.avatar ?? r.headImg ?? null,
    verified: !!(r.certFlag ?? r.verified ?? r.traderCert ?? r.traderLevelId),
    lossless: !!(r.specialTrader ?? r.lossless),
    level: parseInt(r.traderLevelId ?? r.level ?? '0', 10) || 0,
    profit14d,
    profit14Usdt,
    winRate14,
    profitSharePct,
    followers,
    maxFollowers,
    registerDays,
    totalProfit,
    totalFollowProfit,
    totalFollowCount,
    tradingDaysTotal,
    moneyStrength,
    minFollow,
    days: daysForLead,
    trades,
    description: r.description ?? r.intro ?? '',
    styleTags: extractStyleTags(r),
  }
}

// eslint-disable-next-line @typescript-eslint/no-explicit-any
function mapPosition(r: any): Position {
  return {
    id: r.id ?? r.positionId ?? Math.random(),
    symbol: normSym(r.symbol ?? r.coin ?? '') || '—',
    direction: parseInt(r.direction ?? r.side ?? '0', 10),
    positionType: r.positionType ?? r.marginMode ?? '全仓',
    openPrice: parseFloat(r.openPrice ?? r.openRealPrice ?? '0') || 0,
    closePrice: parseFloat(r.closePrice ?? r.currentPrice ?? r.nowPrice ?? '0') || 0,
    amount: parseFloat(r.amount ?? r.volume ?? r.openAmount ?? '0') || 0,
    lever: parseInt(r.lever ?? r.leverage ?? '1', 10) || 1,
    profit: parseFloat(r.profit ?? r.profitAmount ?? r.income ?? '0') || 0,
    profitRate: parseFloat(r.profitRate ?? r.yieldRate ?? r.returnRate ?? '0') || 0,
    openTime: parseInt(r.openTime ?? r.createTime ?? '0', 10) || 0,
    closeTime: r.closeTime ? parseInt(r.closeTime, 10) : undefined,
  }
}

// ── API ────────────────────────────────────────────────────────────────────
async function loadTrader() {
  loading.value   = true
  loadError.value = ''
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await put(`/follow/customer/trader-info/${traderId.value}`)
    const payload = Array.isArray(res) ? res[0] : res
    trader.value = mapTrader(payload ?? {})
    isFavorited.value = !!(payload?.isFavorite ?? payload?.isFavorited ?? payload?.favorite ?? false)

    try {
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      const symRes: any = await put(`/follow/trader-symbol/${traderId.value}`)
      const symList = Array.isArray(symRes) ? symRes : (symRes?.records ?? symRes?.list ?? [])
      // eslint-disable-next-line @typescript-eslint/no-explicit-any
      traderSymbols.value = symList.map((s: any) => s.symbol ?? s)
    } catch { /* symbols optional */ }

    if (trader.value && trader.value.styleTags.length === 0) {
      try {
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const tagRes: any = await get(`/follow/trader-tag/${traderId.value}`)
        const tagList = Array.isArray(tagRes) ? tagRes : (tagRes?.list ?? tagRes?.data ?? [])
        // eslint-disable-next-line @typescript-eslint/no-explicit-any
        const names = tagList.map((t: any) => t.tagName ?? t.name ?? t.tag).filter(Boolean)
        if (names.length) {
          trader.value = { ...trader.value, styleTags: names }
        }
      } catch { /* public tag list optional */ }
    }
  } catch (e: unknown) {
    loadError.value = (e as Error).message || '加载交易员信息失败'
  } finally {
    loading.value = false
  }
}

async function loadFollowStatus() {
  if (!auth.isLoggedIn) return
  try {
    const res = await put(`/follow/follow/info/${traderId.value}`)
    isFollowing.value = !!res
  } catch {
    isFollowing.value = false
  }
}

async function loadPositions() {
  posLoading.value = true
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await post('/follow/position/lead', {
      traderId: traderId.value,
      type: 'current',
      currentPage: 1,
      pageSize: 20,
    })
    const list = Array.isArray(res) ? res : (res?.records ?? res?.list ?? res?.data ?? [])
    positions.value = list.map(mapPosition)
  } catch { /* silent */ } finally {
    posLoading.value = false
  }
}

async function loadHistory() {
  histLoading.value = true
  try {
    // eslint-disable-next-line @typescript-eslint/no-explicit-any
    const res: any = await post('/follow/position/lead', {
      traderId: traderId.value,
      type: 'history',
      currentPage: 1,
      pageSize: 20,
    })
    const list = Array.isArray(res) ? res : (res?.records ?? res?.list ?? res?.data ?? [])
    historyOrders.value = list.map(mapPosition)
  } catch { /* silent */ } finally {
    histLoading.value = false
  }
}

async function toggleFavorite() {
  if (!auth.isLoggedIn) { router.push('/login'); return }
  try {
    if (isFavorited.value) {
      await request.put(`/follow/favorite/unfavorite/${traderId.value}`)
      isFavorited.value = false
    } else {
      await request.put(`/follow/favorite/${traderId.value}`)
      isFavorited.value = true
    }
  } catch { /* silent */ }
}

async function submitFollow() {
  if (!auth.isLoggedIn) { router.push('/login'); return }
  followLoading.value = true
  followError.value   = ''
  try {
    await post('/follow/follow/', {
      traderId: traderId.value,
      tradingMode: '30',
      tradingAmount: '100',
      symbols: traderSymbols.value,
    })
    isFollowing.value = true
    showFollowModal.value = false
    if (trader.value) trader.value.followers++
  } catch (e: unknown) {
    followError.value = (e as Error).message || '跟单失败，请稍后重试'
  } finally {
    followLoading.value = false
  }
}

async function unfollow() {
  if (!confirm('确认取消对该交易员的跟单？')) return
  try {
    await request.put(`/follow/follow/unfollow/${traderId.value}`)
    isFollowing.value = false
    if (trader.value) trader.value.followers = Math.max(0, trader.value.followers - 1)
  } catch (e: unknown) {
    alert((e as Error).message || '取消跟单失败')
  }
}

// ── Helpers ────────────────────────────────────────────────────────────────
function initials(name: string) { return name.charAt(0).toUpperCase() }

function fmtTime(ts: number) {
  if (!ts) return '—'
  return new Date(ts).toLocaleString('zh-CN', { month: '2-digit', day: '2-digit', hour: '2-digit', minute: '2-digit' })
}

function fmtNum(v: number, digits = 2) {
  return v.toLocaleString('en-US', { minimumFractionDigits: digits, maximumFractionDigits: digits })
}

function fmtPnl(v: number) {
  return (v >= 0 ? '+' : '') + fmtNum(v)
}

function fmtSignedUsdt(v: number, digits = 2) {
  return (
    (v >= 0 ? '+' : '') +
    v.toLocaleString('en-US', { minimumFractionDigits: digits, maximumFractionDigits: digits })
  )
}

function fmtProfit14UsdtCell(v: number | null) {
  if (v === null) {
    return '--'
  }
  return fmtSignedUsdt(v)
}

function fmtProfit(v: number) {
  return (v >= 0 ? '+' : '') + v.toLocaleString('en-US', { minimumFractionDigits: 4, maximumFractionDigits: 4 })
}

function fmtPctShare(v: number) {
  if (!v) {
    return '--'
  }
  return `${v % 1 === 0 ? String(Math.round(v)) : v.toFixed(1)}%`
}

function fmtFundingStrengthCell(raw: string): string {
  if (raw == null || raw === '') {
    return '--'
  }
  return String(raw).trim()
}

function normSym(s: string) { return s.toUpperCase().replace(/[/\-_ ]/g, '') }

function fmtSymbol(sym: string) {
  if (sym.endsWith('USDT')) return sym.slice(0, -4) + '/USDT'
  if (sym.endsWith('BTC'))  return sym.slice(0, -3) + '/BTC'
  if (sym.endsWith('ETH'))  return sym.slice(0, -3) + '/ETH'
  return sym
}

function baseAsset(sym: string) {
  if (sym.endsWith('USDT')) return sym.slice(0, -4)
  if (sym.endsWith('BTC'))  return sym.slice(0, -3)
  if (sym.endsWith('ETH'))  return sym.slice(0, -3)
  return sym
}

function fmtQty(v: number) {
  if (v === 0) return '0'
  return parseFloat(v.toFixed(4)).toString()
}

// ── Init ───────────────────────────────────────────────────────────────────
onMounted(async () => {
  if (auth.isLoggedIn) {
    await copyTradingStore.fetchFollowerInfo()
  } else {
    copyTradingStore.reset()
  }
  await Promise.all([loadTrader(), loadFollowStatus(), loadPositions()])
})

watch(activeTab, (tab) => {
  if (tab === 'history') {
    void loadHistory()
  } else {
    void loadPositions()
  }
})

watch(traderId, () => {
  trader.value = null; positions.value = []; historyOrders.value = []
  void (async () => {
    if (auth.isLoggedIn) {
      await copyTradingStore.fetchFollowerInfo()
    } else {
      copyTradingStore.reset()
    }
    await Promise.all([loadTrader(), loadFollowStatus(), loadPositions()])
  })()
})

/** PC 弹窗：ESC 关闭 */
watchEffect((onCleanup) => {
  if (!showFollowModal.value) {
    return
  }
  const onKeydown = (e: KeyboardEvent) => {
    if (e.key === 'Escape') {
      showFollowModal.value = false
    }
  }
  window.addEventListener('keydown', onKeydown)
  onCleanup(() => {
    window.removeEventListener('keydown', onKeydown)
  })
})
</script>

<template>
  <main class="td-main">
    <!-- Back bar -->
    <div class="td-topbar">
      <div class="page-container topbar-inner">
        <button class="back-btn" @click="router.back()">
          <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5m0 0l7 7m-7-7l7-7"/></svg>
          跟单广场
        </button>
        <div class="topbar-actions">
          <button class="icon-btn" :class="{ active: isFavorited }" :title="isFavorited ? '取消收藏' : '收藏'" @click="toggleFavorite">
            <svg width="18" height="18" viewBox="0 0 24 24" :fill="isFavorited ? 'currentColor' : 'none'" stroke="currentColor" stroke-width="2">
              <path d="M12 2l3.09 6.26L22 9.27l-5 4.87 1.18 6.88L12 17.77l-6.18 3.25L7 14.14 2 9.27l6.91-1.01L12 2z"/>
            </svg>
            {{ isFavorited ? '已收藏' : '收藏' }}
          </button>
        </div>
      </div>
    </div>

    <!-- Loading / Error -->
    <div v-if="loading" class="page-container td-skeleton">
      <div class="sk sk-header" />
      <div class="sk sk-stats" />
      <div class="sk sk-table" />
    </div>
    <div v-else-if="loadError" class="page-container empty-state">
      <div class="empty-icon">⚠️</div>
      <div class="empty-text">{{ loadError }}</div>
      <button class="retry-btn" @click="loadTrader">重试</button>
    </div>

    <template v-else-if="trader">
      <!-- Trader Header Card -->
      <div class="td-hero">
        <div class="page-container hero-inner">
          <div class="hero-left">
            <div class="hero-avatar-wrap">
              <img
                v-if="trader.avatar && !traderAvatarLoadError"
                :src="trader.avatar"
                alt=""
                class="hero-avatar-img"
                referrerpolicy="no-referrer"
                @error="traderAvatarLoadError = true"
              >
              <div v-else class="hero-avatar" :class="{ 'hero-avatar--lossless': trader.lossless }">
                {{ initials(trader.name) }}
              </div>
            </div>
            <div class="hero-info">
              <div class="hero-name-row">
                <h1 class="hero-name">{{ trader.name }}</h1>
                <span v-if="trader.level" class="badge-level">{{ levelLabel(trader.level) }}</span>
                <span v-if="trader.verified" class="badge-verified">✓</span>
                <span v-if="trader.lossless" class="badge-lossless">无损</span>
              </div>
              <p v-if="trader.description" class="hero-desc">{{ trader.description }}</p>
              <div v-if="trader.registerDays > 0 || (trader.maxFollowers > 0 && trader.followers >= 0)" class="hero-submeta">
                <span v-if="trader.registerDays > 0" class="hero-submeta-item">已入驻 {{ trader.registerDays }} 天</span>
                <span v-if="trader.maxFollowers > 0" class="hero-submeta-item">
                  当前跟随 {{ trader.followers }}/{{ trader.maxFollowers }}
                </span>
              </div>
              <div class="hero-meta">
                带单 {{ trader.days }} 天 · 共 {{ trader.trades }} 笔交易
              </div>
              <div v-if="trader.styleTags.length" class="hero-style-tags">
                <span v-for="tag in trader.styleTags" :key="tag" class="style-tag">{{ tag }}</span>
              </div>
            </div>
          </div>

          <div class="hero-right">
            <div class="hero-actions">
              <template v-if="isFollowing">
                <button class="btn-outline" @click="router.push('/copy-trade/my-following')">查看跟单</button>
                <button class="btn-danger" @click="unfollow">取消跟单</button>
              </template>
              <button v-else-if="!copyTradingStore.isTrader" class="btn-primary" @click="showFollowModal = true">
                开始跟单
              </button>
            </div>
            <p class="hero-min-follow">最低跟单 <strong>{{ trader.minFollow }}</strong> USDT</p>
            <div v-if="followError" class="follow-error-msg">{{ followError }}</div>
          </div>
        </div>
      </div>

      <!-- 与 App 对齐：账户信息 / 核心数据 / 带单合约 -->
      <div class="page-container td-detail-blocks">
        <section class="detail-card" aria-label="账户信息">
          <h2 class="detail-card-title">账户信息</h2>
          <div class="detail-grid">
            <div class="detail-cell">
              <div class="detail-label">累计跟单盈利额(USDT)</div>
              <div class="detail-val" :class="trader.totalFollowProfit >= 0 ? 'text-up' : 'text-down'">
                {{ fmtSignedUsdt(trader.totalFollowProfit) }}
              </div>
            </div>
            <div class="detail-cell">
              <div class="detail-label">资金实力(USDT)</div>
              <div class="detail-val">{{ fmtFundingStrengthCell(trader.moneyStrength) }}</div>
            </div>
            <div class="detail-cell">
              <div class="detail-label">累计跟单人数</div>
              <div class="detail-val">{{ (trader.totalFollowCount || trader.followers).toLocaleString() }}</div>
            </div>
            <div class="detail-cell">
              <div class="detail-label">累计交易天数</div>
              <div class="detail-val">{{ trader.tradingDaysTotal || trader.days || '—' }}</div>
            </div>
          </div>
        </section>

        <section class="detail-card" aria-label="核心数据">
          <h2 class="detail-card-title">核心数据</h2>
          <div class="detail-grid">
            <div class="detail-cell">
              <div class="detail-label">近14天收益率</div>
              <div class="detail-val" :class="trader.profit14d >= 0 ? 'text-up' : 'text-down'">
                {{ trader.profit14d >= 0 ? '+' : '' }}{{ trader.profit14d.toFixed(2) }}%
              </div>
            </div>
            <div class="detail-cell">
              <div class="detail-label">近14天收益(USDT)</div>
              <div
                class="detail-val"
                :class="
                  trader.profit14Usdt === null
                    ? ''
                    : trader.profit14Usdt >= 0
                      ? 'text-up'
                      : 'text-down'
                "
              >
                {{ fmtProfit14UsdtCell(trader.profit14Usdt) }}
              </div>
            </div>
            <div class="detail-cell">
              <div class="detail-label">近14天胜率</div>
              <div class="detail-val">{{ trader.winRate14.toFixed(1) }}%</div>
            </div>
            <div class="detail-cell">
              <div class="detail-label">分润比例</div>
              <div class="detail-val">{{ fmtPctShare(trader.profitSharePct) }}</div>
            </div>
          </div>
        </section>

        <section v-if="traderSymbols.length" class="contracts-panel">
          <button type="button" class="contracts-toggle" :aria-expanded="contractsOpen" @click="contractsOpen = !contractsOpen">
            <span class="contracts-toggle-title">带单合约</span>
            <svg
              class="contracts-chevron"
              :class="{ 'contracts-chevron--open': contractsOpen }"
              width="14"
              height="14"
              viewBox="0 0 10 6"
            ><path d="M1 1l4 4 4-4" stroke="currentColor" stroke-width="1.5" fill="none"/></svg>
          </button>
          <div v-show="contractsOpen" class="contracts-chips">
            <span v-for="sym in traderSymbols" :key="sym" class="sym-chip">{{ fmtSymbol(normSym(sym)) }}</span>
          </div>
        </section>
      </div>

      
      <!-- Tabs: positions / history -->
      <div class="td-tabs-wrap">
        <div class="page-container">
          <div class="td-tabs">
            <button class="td-tab" :class="{ active: activeTab === 'positions' }" @click="activeTab = 'positions'">
              当前持仓
            </button>
            <button class="td-tab" :class="{ active: activeTab === 'history' }" @click="activeTab = 'history'">
              历史带单
            </button>
          </div>
        </div>
      </div>

      <!-- Positions Table -->
      <div class="page-container td-content">
        <!-- Loading skeleton for positions -->
        <div v-if="(activeTab === 'positions' && posLoading) || (activeTab === 'history' && histLoading)" class="table-loading">
          <div v-for="i in 4" :key="i" class="sk sk-row" />
        </div>

        <!-- Current positions -->
        <template v-else-if="activeTab === 'positions'">
          <div v-if="positions.length === 0" class="empty-state">
            <div class="empty-icon">📭</div>
            <div class="empty-text">暂无当前持仓</div>
          </div>
          <div v-else class="pos-table-wrap">
            <table class="pos-table">
              <thead>
                <tr>
                  <th>合约</th>
                  <th>方向</th>
                  <th>开仓价</th>
                  <th>当前价</th>
                  <th>数量</th>
                  <th>杠杆</th>
                  <th>未实现盈亏</th>
                  <th>开仓时间</th>
                </tr>
              </thead>
              <tbody>
                <tr v-for="p in positions" :key="p.id">
                  <td class="td-symbol">{{ p.symbol }}</td>
                  <td>
                    <span class="dir-badge" :class="p.direction === 0 ? 'dir-long' : 'dir-short'">
                      {{ p.direction === 0 ? '做多' : '做空' }}
                    </span>
                  </td>
                  <td class="num">{{ fmtNum(p.openPrice, 4) }}</td>
                  <td class="num">{{ fmtNum(p.closePrice, 4) }}</td>
                  <td class="num">{{ fmtNum(p.amount) }}</td>
                  <td class="num">{{ p.lever }}x</td>
                  <td class="num" :class="p.profit >= 0 ? 'text-up' : 'text-down'">
                    {{ fmtPnl(p.profit) }}
                    <span class="pnl-rate">({{ fmtPnl(p.profitRate) }}%)</span>
                  </td>
                  <td class="td-time">{{ fmtTime(p.openTime) }}</td>
                </tr>
              </tbody>
            </table>
          </div>
        </template>

        <!-- History lead orders (card layout) -->
        <template v-else>
          <div v-if="historyOrders.length === 0" class="empty-state">
            <div class="empty-icon">📭</div>
            <div class="empty-text">暂无历史带单</div>
          </div>
          <div v-else class="order-cards">
            <div v-for="p in historyOrders" :key="p.id" class="order-card">
              <div class="oc-header">
                <span class="oc-symbol">{{ fmtSymbol(p.symbol) }}</span>
                <span class="oc-perp">{{ t('common.perpetual') }}</span>
                <span class="dir-badge" :class="p.direction === 0 ? 'dir-long' : 'dir-short'">{{ p.direction === 0 ? '开多' : '开空' }}</span>
                <span class="oc-pos-type">{{ p.positionType }}</span>
                <span class="oc-lever">{{ p.lever }}X</span>
              </div>
              <div class="oc-row">
                <div class="oc-col">
                  <div class="oc-label">平仓数量({{ baseAsset(p.symbol) }})</div>
                  <div class="oc-val num">{{ fmtQty(p.amount) }}</div>
                </div>
                <div class="oc-col oc-col-center">
                  <div class="oc-label">已实现盈亏(USDT)</div>
                  <div class="oc-val num" :class="p.profit >= 0 ? 'pnl-up' : 'pnl-down'">{{ fmtProfit(p.profit) }}</div>
                </div>
                <div class="oc-col oc-col-right">
                  <div class="oc-label">收益率</div>
                  <div class="oc-val num" :class="p.profitRate >= 0 ? 'pnl-up' : 'pnl-down'">{{ fmtPnl(p.profitRate) }}%</div>
                </div>
              </div>
              <div class="oc-row oc-row-2col">
                <div class="oc-col">
                  <div class="oc-label">开仓均价(USDT)</div>
                  <div class="oc-val num">{{ fmtNum(p.openPrice, 2) }}</div>
                </div>
                <div class="oc-col oc-col-right">
                  <div class="oc-label">平仓均价(USDT)</div>
                  <div class="oc-val num">{{ fmtNum(p.closePrice, 2) }}</div>
                </div>
              </div>
              <div class="oc-footer">
                <span class="oc-time">{{ fmtTime(p.openTime) }}</span>
                <span class="oc-time-sep">→</span>
                <span class="oc-time">{{ fmtTime(p.closeTime ?? 0) }}</span>
              </div>
            </div>
          </div>
        </template>
      </div>
    </template>
  </main>

  <!-- ── Follow settings modal ── -->
  <Teleport to="body">
    <div
      v-if="showFollowModal"
      class="fs-mask"
      role="presentation"
      @click.self="showFollowModal = false"
    >
      <div
        class="fs-box"
        role="dialog"
        aria-modal="true"
        aria-labelledby="fs-dialog-title"
      >
        <div class="fs-header">
          <button type="button" class="fs-back" aria-label="返回" @click="showFollowModal = false">
            <svg width="18" height="18" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2"><path d="M19 12H5m0 0l7 7m-7-7l7-7"/></svg>
          </button>
          <span id="fs-dialog-title" class="fs-title">跟单设置</span>
          <div style="width:36px" aria-hidden="true" />
        </div>
        <div class="fs-body">
          <!-- Trader info -->
          <div v-if="trader" class="fs-trader-card">
            <div class="fs-trader-row">
              <div v-if="trader.avatar && !traderAvatarLoadError" class="fs-trader-avatar-wrap">
                <img
                  :src="trader.avatar"
                  alt=""
                  class="fs-trader-avatar-img"
                  referrerpolicy="no-referrer"
                  @error="traderAvatarLoadError = true"
                >
              </div>
              <div v-else class="fs-trader-avatar">
                {{ initials(trader.name) }}
              </div>
              <div class="fs-trader-info">
                <div class="fs-trader-name">{{ trader.name }}</div>
                <div class="fs-trader-meta">
                  {{ formatCopyFundStrengthDisplay(trader.moneyStrength) }}
                </div>
              </div>
            </div>
          </div>

          <!-- Symbols section -->
          <div class="fs-symbols-section">
            <div class="fs-symbols-label">跟单合约</div>
            <div v-if="traderSymbols.length === 0" class="fs-symbols-empty">暂无跟单合约</div>
            <div v-else class="fs-symbols-wrap">
              <span v-for="sym in traderSymbols" :key="sym" class="fs-sym-chip">{{ sym }}</span>
            </div>
          </div>
        </div>

        <!-- Bottom button -->
        <div class="fs-footer">
          <div v-if="followError" class="fs-error">{{ followError }}</div>
          <button class="fs-submit-btn" :disabled="followLoading" @click="submitFollow">
            {{ followLoading ? '提交中…' : '开始跟单' }}
          </button>
        </div>
      </div>
    </div>
  </Teleport>
</template>

<style scoped>
.td-main { padding-top: var(--header-height); background: var(--color-bg-primary); min-height: 100vh; }

/* ── Top bar ── */
.td-topbar {
  background: var(--color-bg-secondary);
  border-bottom: 1px solid var(--color-border);
  padding: 12px 0;
}
.topbar-inner { display: flex; align-items: center; justify-content: space-between; }
.back-btn {
  display: flex; align-items: center; gap: 6px;
  color: var(--color-text-secondary); background: none; border: none; cursor: pointer;
  font-size: 14px; padding: 6px 0; transition: color 0.2s;
}
.back-btn:hover { color: var(--color-text-primary); }
.icon-btn {
  display: flex; align-items: center; gap: 5px;
  padding: 7px 14px; border-radius: 8px;
  background: transparent; border: 1px solid var(--color-border);
  color: var(--color-text-secondary); font-size: 13px; cursor: pointer;
  transition: all 0.2s;
}
.icon-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }
.icon-btn.active { color: #f0b90b; border-color: rgba(240,185,11,0.4); }

/* ── Skeleton ── */
.td-skeleton { padding: 32px 0; }
.sk { background: rgba(255,255,255,0.06); border-radius: 8px; animation: sk-pulse 1.4s ease infinite; }
.sk-header { height: 140px; margin-bottom: 16px; }
.sk-stats  { height: 80px; margin-bottom: 16px; }
.sk-table  { height: 200px; }
.sk-row    { height: 44px; margin-bottom: 8px; }
@keyframes sk-pulse { 0%,100% { opacity:1 } 50% { opacity:.35 } }

/* ── Hero ── */
.td-hero {
  background: linear-gradient(135deg, #0f0f0f 0%, #1a1400 60%, #0f0f0f 100%);
  border-bottom: 1px solid var(--color-border);
  padding: 36px 0;
}
.hero-inner {
  display: grid;
  grid-template-columns: 1fr auto;
  gap: 40px;
  align-items: start;
}
.hero-left { display: flex; gap: 20px; align-items: flex-start; }
.hero-avatar-wrap { flex-shrink: 0; }
.hero-avatar-img { width: 72px; height: 72px; border-radius: 50%; object-fit: cover; }
.hero-avatar {
  width: 72px; height: 72px; border-radius: 50%;
  background: var(--color-primary); color: #000;
  font-size: 26px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.hero-avatar--lossless { background: #0ecb81; }
.hero-name-row { display: flex; align-items: center; gap: 8px; flex-wrap: wrap; margin-bottom: 8px; }
.hero-name { font-size: 22px; font-weight: 700; color: var(--color-text-primary); }
.badge-verified {
  width: 18px; height: 18px; border-radius: 50%;
  background: #1677ff; color: #fff; font-size: 10px; font-weight: 700;
  display: flex; align-items: center; justify-content: center;
}
.badge-lossless {
  font-size: 11px; font-weight: 600;
  background: rgba(14,203,129,0.15); color: #0ecb81;
  border: 1px solid rgba(14,203,129,0.3); border-radius: 4px; padding: 2px 7px;
}
.hero-desc { font-size: 13px; color: var(--color-text-secondary); margin-bottom: 8px; max-width: 360px; line-height: 1.5; }
.hero-meta { font-size: 12px; color: var(--color-text-muted); margin-bottom: 10px; }
.hero-symbols { display: flex; flex-wrap: wrap; gap: 5px; }
.sym-tag {
  font-size: 11px; color: var(--color-text-muted);
  background: rgba(255,255,255,0.06); border: 1px solid var(--color-border);
  border-radius: 4px; padding: 2px 7px;
}
.sym-more { font-size: 11px; color: var(--color-text-muted); align-self: center; }

.hero-right { min-width: 220px; }
.hero-actions { display: flex; gap: 10px; flex-wrap: wrap; }

.follow-error-msg {
  font-size: 12px; color: #f6465d;
  margin-top: 8px;
  padding: 8px 12px;
  background: rgba(246,70,93,0.08);
  border-radius: 6px;
}

.badge-level {
  font-size: 11px; font-weight: 700;
  padding: 2px 8px; border-radius: 4px;
  background: rgba(240, 185, 11, 0.2);
  color: var(--color-primary);
  border: 1px solid rgba(240, 185, 11, 0.45);
}

.hero-submeta {
  display: flex; flex-wrap: wrap; gap: 12px 18px;
  font-size: 12px; color: var(--color-text-muted);
  margin-bottom: 8px;
}
.hero-submeta-item { color: var(--color-text-secondary); }

.hero-style-tags { display: flex; flex-wrap: wrap; gap: 6px; margin-top: 10px; }
.style-tag {
  font-size: 11px; font-weight: 500;
  padding: 3px 10px; border-radius: 999px;
  background: rgba(22, 119, 255, 0.12);
  color: #69b1ff;
  border: 1px solid rgba(22, 119, 255, 0.28);
}

.hero-min-follow {
  font-size: 12px; color: var(--color-text-muted);
  margin-top: 12px;
}
.hero-min-follow strong { color: var(--color-text-secondary); font-family: var(--font-family-num); }

.td-detail-blocks { padding-bottom: 8px; display: flex; flex-direction: column; gap: 14px; }

.detail-card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 16px 18px;
}
.detail-card-title {
  font-size: 15px; font-weight: 600;
  color: var(--color-text-primary);
  margin: 0 0 14px;
}
.detail-grid {
  display: grid;
  grid-template-columns: repeat(2, 1fr);
  gap: 14px 20px;
}
.detail-cell { min-width: 0; }
.detail-label {
  font-size: 11px; color: var(--color-text-muted);
  margin-bottom: 6px; line-height: 1.3;
}
.detail-val {
  font-size: 16px; font-weight: 700;
  font-family: var(--font-family-num);
  color: var(--color-text-primary);
  word-break: break-all;
}

.contracts-panel {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  overflow: hidden;
}
.contracts-toggle {
  width: 100%; display: flex; align-items: center; justify-content: space-between;
  padding: 14px 18px;
  background: transparent;
  border: none;
  cursor: pointer;
  color: var(--color-text-primary);
  font-size: 15px; font-weight: 600;
}
.contracts-toggle:hover { background: rgba(255,255,255,0.03); }
.contracts-toggle-title { text-align: left; }
.contracts-chevron { flex-shrink: 0; color: var(--color-text-muted); transition: transform 0.2s; }
.contracts-chevron--open { transform: rotate(180deg); }
.contracts-chips {
  display: flex; flex-wrap: wrap; gap: 8px;
  padding: 0 18px 16px;
}
.sym-chip {
  font-size: 12px; font-weight: 600;
  color: var(--color-primary);
  padding: 6px 12px;
  border-radius: 8px;
  background: rgba(240, 185, 11, 0.1);
  border: 1px solid rgba(240, 185, 11, 0.45);
}

@media (max-width: 600px) {
  .detail-grid { gap: 12px 14px; }
  .detail-val { font-size: 15px; }
}

/* ── Tabs ── */
.td-tabs-wrap {
  background: var(--color-bg-secondary);
  border-bottom: 1px solid var(--color-border);
  position: sticky; top: var(--header-height); z-index: 10;
}
.td-tabs { display: flex; }
.td-tab {
  padding: 14px 28px; font-size: 14px; font-weight: 500;
  color: var(--color-text-muted); background: transparent;
  border: none; cursor: pointer;
  border-bottom: 2px solid transparent; transition: all 0.2s;
}
.td-tab:hover { color: var(--color-text-primary); }
.td-tab.active { color: var(--color-primary); border-bottom-color: var(--color-primary); }

/* ── Content ── */
.td-content { padding: 24px 0 48px; }
.table-loading { display: flex; flex-direction: column; gap: 8px; }

/* ── Position table ── */
.pos-table-wrap { overflow-x: auto; }
.pos-table {
  width: 100%; border-collapse: collapse;
  font-size: 13px;
}
.pos-table th {
  padding: 10px 14px; text-align: left;
  font-size: 11px; font-weight: 500;
  color: var(--color-text-muted);
  border-bottom: 1px solid var(--color-border);
  white-space: nowrap;
}
.pos-table td {
  padding: 13px 14px;
  color: var(--color-text-secondary);
  border-bottom: 1px solid rgba(255,255,255,0.04);
  white-space: nowrap;
}
.pos-table tr:hover td { background: rgba(255,255,255,0.02); }
.td-symbol { color: var(--color-text-primary) !important; font-weight: 600; }
.td-time { color: var(--color-text-muted) !important; font-size: 12px; }
.pnl-rate { font-size: 11px; color: inherit; opacity: 0.75; }

.dir-badge {
  display: inline-block;
  font-size: 11px; font-weight: 600;
  padding: 2px 8px; border-radius: 4px;
}
.dir-long  { background: rgba(14,203,129,0.12); color: #0ecb81; }
.dir-short { background: rgba(246,70,93,0.12);  color: #f6465d; }

/* ── Order cards ── */
.order-cards { display: grid; grid-template-columns: repeat(2, 1fr); gap: 12px; }
.order-card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 12px; padding: 16px;
  display: flex; flex-direction: column; gap: 10px;
}
.oc-header { display: flex; align-items: center; gap: 6px; flex-wrap: wrap; }
.oc-symbol  { font-size: 14px; font-weight: 700; color: var(--color-text-primary); }
.oc-perp    { font-size: 11px; color: var(--color-text-muted); }
.oc-pos-type { font-size: 11px; color: var(--color-text-muted); padding: 1px 6px; border: 1px solid var(--color-border); border-radius: 3px; }
.oc-lever    { font-size: 11px; color: var(--color-text-muted); padding: 1px 6px; border: 1px solid var(--color-border); border-radius: 3px; margin-left: auto; }

.oc-row { display: grid; grid-template-columns: 1fr 1fr 1fr; gap: 4px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.05); }
.oc-row-2col { grid-template-columns: 1fr 1fr; }
.oc-col { display: flex; flex-direction: column; gap: 4px; }
.oc-col-center { text-align: center; }
.oc-col-right  { text-align: right; }
.oc-label { font-size: 11px; color: var(--color-text-muted); white-space: nowrap; }
.oc-val   { font-size: 13px; font-weight: 600; color: var(--color-text-primary); font-family: var(--font-family-num); }

.oc-footer { display: flex; align-items: center; gap: 6px; padding-top: 6px; border-top: 1px solid rgba(255,255,255,0.05); }
.oc-time   { font-size: 11px; color: var(--color-text-muted); }
.oc-time-sep { font-size: 11px; color: var(--color-text-muted); }

.pnl-up   { color: #0ecb81; }
.pnl-down { color: #f6465d; }

@media (max-width: 900px) { .order-cards { grid-template-columns: 1fr; } }

/* ── Empty ── */
.empty-state { text-align: center; padding: 60px 20px; }
.empty-icon { font-size: 36px; margin-bottom: 12px; }
.empty-text { color: var(--color-text-muted); font-size: 14px; margin-bottom: 16px; }
.retry-btn {
  padding: 8px 24px; border: 1px solid var(--color-border);
  border-radius: 8px; cursor: pointer; color: var(--color-text-secondary);
  background: transparent; font-size: 13px; transition: border-color 0.2s;
}
.retry-btn:hover { border-color: var(--color-primary); color: var(--color-primary); }

/* ── Buttons ── */
.btn-primary {
  padding: 10px 28px; background: var(--color-primary); color: #000;
  font-size: 14px; font-weight: 600; border-radius: 8px; border: none;
  cursor: pointer; transition: opacity 0.2s;
}
.btn-primary:hover { opacity: 0.85; }
.btn-outline {
  padding: 10px 20px; background: transparent; color: var(--color-text-secondary);
  font-size: 14px; font-weight: 500; border-radius: 8px;
  border: 1px solid var(--color-border); cursor: pointer; transition: all 0.2s;
}
.btn-outline:hover { border-color: var(--color-primary); color: var(--color-primary); }
.btn-danger {
  padding: 10px 20px; background: transparent; color: #f6465d;
  font-size: 14px; font-weight: 500; border-radius: 8px;
  border: 1px solid rgba(246,70,93,0.4); cursor: pointer; transition: all 0.2s;
}
.btn-danger:hover { background: rgba(246,70,93,0.1); }

/* ── Responsive ── */
@media (max-width: 900px) {
  .hero-inner { grid-template-columns: 1fr; }
  .hero-right { min-width: unset; }
}
@media (max-width: 600px) {
  .hero-left { flex-direction: column; }
}

/* ── Follow Settings Modal（大屏为居中弹窗，小屏全屏） ── */
.fs-mask {
  position: fixed;
  inset: 0;
  background: rgba(0, 0, 0, 0.58);
  display: flex;
  align-items: center;
  justify-content: center;
  z-index: 2000;
  padding: 20px;
  box-sizing: border-box;
}
.fs-box {
  background: var(--color-bg-secondary);
  width: 100%;
  max-width: 440px;
  height: auto;
  max-height: min(90vh, 680px);
  display: flex;
  flex-direction: column;
  overflow: hidden;
  border-radius: 16px;
  border: 1px solid var(--color-border);
  box-shadow: 0 24px 64px rgba(0, 0, 0, 0.5);
}
.fs-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 16px 20px;
  border-bottom: 1px solid rgba(255, 255, 255, 0.08);
  flex-shrink: 0;
}
.fs-back {
  display: flex;
  align-items: center;
  justify-content: center;
  width: 36px;
  height: 36px;
  border-radius: 8px;
  background: none;
  border: none;
  cursor: pointer;
  color: var(--color-text-secondary);
  transition: background 0.2s;
}
.fs-back:hover { background: rgba(255,255,255,0.06); color: var(--color-text-primary); }
.fs-title { font-size: 17px; font-weight: 600; color: var(--color-text-primary); }
.fs-body { flex: 1; overflow-y: auto; padding: 20px; min-height: 0; }

.fs-trader-card {
  background: var(--color-bg-card);
  border: 1px solid var(--color-border);
  border-radius: 12px;
  padding: 14px;
  margin-bottom: 20px;
}
.fs-trader-row { display: flex; align-items: center; gap: 12px; }
.fs-trader-avatar-wrap { flex-shrink: 0; }
.fs-trader-avatar-img { width: 48px; height: 48px; border-radius: 50%; object-fit: cover; }
.fs-trader-avatar {
  width: 48px;
  height: 48px;
  border-radius: 50%;
  background: var(--color-primary);
  color: #000;
  font-size: 18px;
  font-weight: 700;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
}
.fs-trader-name { font-size: 15px; font-weight: 700; color: var(--color-text-primary); }
.fs-trader-meta { font-size: 12px; color: var(--color-text-muted); margin-top: 4px; line-height: 1.4; }

.fs-symbols-section { margin-bottom: 8px; }
.fs-symbols-label { font-size: 13px; color: var(--color-text-muted); margin-bottom: 10px; }
.fs-symbols-empty { font-size: 13px; color: var(--color-text-muted); }
.fs-symbols-wrap { display: flex; flex-wrap: wrap; gap: 8px; }
.fs-sym-chip {
  padding: 7px 14px;
  font-size: 13px;
  font-weight: 600;
  color: var(--color-primary);
  background: rgba(240,185,11,0.12);
  border: 1.5px solid rgba(240,185,11,0.6);
  border-radius: 8px;
}

.fs-footer {
  flex-shrink: 0;
  padding: 16px 20px 20px;
  background: var(--color-bg-secondary);
  border-top: 1px solid var(--color-border);
}
.fs-error {
  font-size: 12px;
  color: #f6465d;
  margin-bottom: 10px;
  padding: 8px 12px;
  background: rgba(246,70,93,0.08);
  border-radius: 6px;
}
.fs-submit-btn {
  width: 100%;
  height: 48px;
  border-radius: 24px;
  background: var(--color-primary);
  color: #000;
  font-size: 15px;
  font-weight: 600;
  border: none;
  cursor: pointer;
  transition: opacity 0.2s;
}
.fs-submit-btn:hover:not(:disabled) { opacity: 0.85; }
.fs-submit-btn:disabled { opacity: 0.5; cursor: not-allowed; }

@media (max-width: 520px) {
  .fs-mask {
    padding: 0;
    align-items: stretch;
    background: var(--color-bg-primary);
  }
  .fs-box {
    max-width: none;
    width: 100%;
    height: 100%;
    max-height: none;
    border-radius: 0;
    border: none;
    box-shadow: none;
  }
  .fs-footer {
    padding: 12px 16px calc(12px + env(safe-area-inset-bottom, 0));
  }
}
</style>
