<template>
  <v-container class="wallet-container">
    <!-- 顶部：Portfolio + Profit/Loss 卡片 -->
    <v-row class="wallet-cards">
      <v-col cols="12" md="6">
        <v-card class="wallet-card portfolio-card" elevation="0" rounded="lg">
          <div class="card-header">
            <span class="card-title">
              Portfolio
              <v-icon size="16" class="title-icon">mdi-eye-off-outline</v-icon>
            </span>
            <div class="balance-badge">
              <v-icon size="14">mdi-sack</v-icon>
              <span>${{ portfolioBalance }}</span>
            </div>
          </div>
          <div class="card-value">${{ portfolioBalance }}</div>
          <div class="card-timeframe">Today</div>
          <div class="card-actions">
            <v-btn
              color="primary"
              variant="flat"
              class="action-btn"
              prepend-icon="mdi-arrow-down"
              @click="depositDialogOpen = true"
            >
              Deposit
            </v-btn>
            <v-btn
              variant="outlined"
              color="grey"
              class="action-btn"
              prepend-icon="mdi-arrow-up"
              @click="withdrawDialogOpen = true"
            >
              Withdraw
            </v-btn>
          </div>
        </v-card>
      </v-col>
      <v-col cols="12" md="6">
        <v-card class="wallet-card pl-card" elevation="0" rounded="lg">
          <div class="card-header">
            <span class="card-title">
              <v-icon size="16" color="success">mdi-triangle-small-up</v-icon>
              Profit/Loss
            </span>
            <div class="pl-tabs">
              <v-btn
                v-for="t in plTimeRanges"
                :key="t"
                :variant="plRange === t ? 'flat' : 'text'"
                :color="plRange === t ? 'primary' : undefined"
                size="small"
                class="pl-tab"
                @click="plRange = t"
              >
                {{ t }}
              </v-btn>
            </div>
          </div>
          <div class="card-value-row">
            <span class="card-value">${{ profitLoss }}</span>
            <v-icon size="18" class="info-icon">mdi-information-outline</v-icon>
          </div>
          <div class="card-timeframe">All-Time</div>
          <div ref="plChartRef" class="pl-chart"></div>
        </v-card>
      </v-col>
    </v-row>

    <!-- 下方：Positions / Open orders / History -->
    <div class="wallet-section">
      <v-tabs v-model="activeTab" class="wallet-tabs" density="comfortable">
        <v-tab value="positions">Positions</v-tab>
        <v-tab value="orders">Open orders</v-tab>
        <v-tab value="history">History</v-tab>
      </v-tabs>
      <div class="toolbar">
        <v-text-field
          v-model="search"
          placeholder="Search"
          density="compact"
          hide-details
          variant="outlined"
          rounded
          class="search-field"
          prepend-inner-icon="mdi-magnify"
        />
        <template v-if="activeTab === 'history'">
          <v-btn v-if="mobile" variant="outlined" size="small" class="filter-btn filter-btn-close-losses" @click="closeLosses">
            <v-icon size="18">mdi-delete-outline</v-icon>
            Close Losses
          </v-btn>
          <v-btn variant="outlined" size="small" class="filter-btn">
            <v-icon size="18">mdi-filter</v-icon>
            All
          </v-btn>
          <v-btn variant="outlined" size="small" class="filter-btn">
            <v-icon size="18">mdi-sort</v-icon>
            Newest
          </v-btn>
          <v-btn variant="outlined" size="small" class="filter-btn" icon>
            <v-icon size="18">mdi-calendar</v-icon>
          </v-btn>
          <v-btn variant="outlined" size="small" class="filter-btn">
            <v-icon size="18">mdi-download</v-icon>
            Export
          </v-btn>
        </template>
        <template v-else-if="activeTab === 'positions'">
          <v-btn variant="outlined" size="small" class="filter-btn">
            <v-icon size="18">mdi-filter</v-icon>
            Current value
          </v-btn>
        </template>
        <template v-else-if="activeTab === 'orders'">
          <v-btn variant="outlined" size="small" class="filter-btn">
            <v-icon size="18">mdi-filter</v-icon>
            Market
          </v-btn>
          <v-btn variant="outlined" size="small" class="filter-btn filter-btn-cancel" @click="cancelAllOrders">
            <v-icon size="18">mdi-close</v-icon>
            Cancel all
          </v-btn>
        </template>
        <v-btn v-else variant="outlined" size="small" class="filter-btn">
          <v-icon size="18">mdi-filter</v-icon>
          Market
        </v-btn>
      </div>
      <v-card class="table-card" elevation="0" rounded="lg">
        <!-- 持仓：桌面端表格 / 移动端可折叠列表 -->
        <template v-if="activeTab === 'positions'">
          <!-- 移动端：可折叠列表 -->
          <div v-if="mobile" class="positions-mobile-list">
            <template v-if="filteredPositions.length === 0">
              <div class="empty-cell">No positions found.</div>
            </template>
            <div
              v-for="pos in paginatedPositions"
              :key="pos.id"
              class="position-mobile-card"
              :class="{ expanded: expandedPositionId === pos.id }"
              @click="togglePositionExpanded(pos.id)"
            >
              <div class="position-mobile-row">
                <div class="position-icon" :class="pos.iconClass">
                  <span class="position-icon-char">{{ pos.iconChar }}</span>
                </div>
                <div class="position-mobile-main">
                  <div class="position-mobile-title">{{ pos.market }}</div>
                  <div class="position-mobile-sub">
                    {{ pos.bet }} on {{ pos.outcomeWord || pos.sellOutcome || 'Position' }} to win {{ pos.toWin }}
                  </div>
                </div>
                <div class="position-mobile-right">
                  <div class="position-value">{{ pos.value }}</div>
                  <div v-if="pos.valueChange != null" :class="['position-value-change', pos.valueChangeLoss ? 'value-loss' : 'value-gain']">
                    {{ pos.valueChange }}{{ pos.valueChangePct != null ? ` (${pos.valueChangePct})` : '' }}
                  </div>
                </div>
              </div>
              <!-- 展开内容：AVG • NOW + 操作按钮 -->
              <div v-show="expandedPositionId === pos.id" class="position-mobile-expanded" @click.stop>
                <div class="position-mobile-avg-row">
                  <span class="avg-now-label">AVG • NOW</span>
                  <span class="avg-now-values">
                    <template v-if="parseAvgNow(pos.avgNow)[1]">
                      {{ parseAvgNow(pos.avgNow)[0] }}
                      <v-icon v-if="pos.valueChangeLoss" size="14" color="error" class="avg-now-arrow">mdi-chevron-down</v-icon>
                      <v-icon v-else size="14" color="success" class="avg-now-arrow">mdi-chevron-up</v-icon>
                      {{ parseAvgNow(pos.avgNow)[1] }}
                    </template>
                    <template v-else>{{ pos.avgNow }}</template>
                  </span>
                </div>
                <div class="position-mobile-actions">
                  <v-btn color="primary" variant="flat" size="small" class="position-sell-btn" @click="sellPosition(pos.id)">Sell</v-btn>
                  <v-btn icon variant="text" size="small" class="position-share-btn" @click="sharePosition(pos.id)">
                    <v-icon size="18">mdi-share-variant</v-icon>
                  </v-btn>
                </div>
              </div>
            </div>
          </div>
          <!-- 桌面端：表格 -->
          <v-table v-else class="wallet-table positions-table-full">
            <thead>
              <tr>
                <th class="text-left">MARKET</th>
                <th class="text-left">
                  AVG → NOW
                  <v-icon size="14" class="th-icon">mdi-information-outline</v-icon>
                </th>
                <th class="text-left">BET</th>
                <th class="text-left">TO WIN</th>
                <th class="text-left">
                  VALUE
                  <v-icon size="14" class="th-icon">mdi-chevron-down</v-icon>
                </th>
                <th class="text-right">ACTION</th>
              </tr>
            </thead>
            <tbody>
              <tr v-if="filteredPositions.length === 0">
                <td colspan="6" class="empty-cell">No positions found.</td>
              </tr>
              <tr v-for="pos in paginatedPositions" :key="pos.id" class="position-row">
                <td class="cell-market">
                  <div class="position-market-cell">
                    <div class="position-icon" :class="pos.iconClass">
                      <v-icon v-if="pos.icon" size="20" class="position-icon-svg">{{ pos.icon }}</v-icon>
                      <span v-else class="position-icon-char">{{ pos.iconChar }}</span>
                    </div>
                    <div class="position-market-info">
                      <span class="position-market-title">{{ pos.market }}</span>
                      <div class="position-meta">
                        <span v-if="pos.outcomeTag" class="position-outcome-pill" :class="pos.outcomePillClass">{{ pos.outcomeTag }}</span>
                        <span class="position-shares">{{ pos.shares }}</span>
                      </div>
                    </div>
                  </div>
                </td>
                <td class="cell-avg-now">{{ pos.avgNow }}</td>
                <td>{{ pos.bet }}</td>
                <td>{{ pos.toWin }}</td>
                <td class="cell-value">
                  <div class="position-value">{{ pos.value }}</div>
                  <div v-if="pos.valueChange != null" :class="['position-value-change', pos.valueChangeLoss ? 'value-loss' : 'value-gain']">
                    {{ pos.valueChange }}{{ pos.valueChangePct != null ? ` (${pos.valueChangePct})` : '' }}
                  </div>
                </td>
                <td class="text-right cell-actions">
                  <v-btn color="primary" variant="flat" size="small" class="position-sell-btn" @click="sellPosition(pos.id)">Sell</v-btn>
                  <v-btn icon variant="text" size="small" class="position-share-btn" @click="sharePosition(pos.id)">
                    <v-icon size="18">mdi-share-variant</v-icon>
                  </v-btn>
                </td>
              </tr>
            </tbody>
          </v-table>
        </template>
        <!-- 未成交：移动端卡片列表 / 桌面端表格 -->
        <template v-else-if="activeTab === 'orders'">
          <!-- 移动端：挂单卡片列表 -->
          <div v-if="mobile" class="orders-mobile-list">
            <template v-if="filteredOpenOrders.length === 0">
              <div class="empty-cell">No open orders found.</div>
            </template>
            <div v-for="ord in paginatedOpenOrders" :key="ord.id" class="order-mobile-card">
              <div class="order-mobile-icon" :class="ord.iconClass">
                <span class="position-icon-char">{{ ord.iconChar }}</span>
              </div>
              <div class="order-mobile-main">
                <div class="order-mobile-title">{{ ord.market }}</div>
                <div class="order-mobile-action" :class="ord.side === 'Yes' ? 'side-yes' : 'side-no'">
                  {{ ord.actionLabel || `Buy ${ord.outcome}` }}
                </div>
                <div class="order-mobile-price">{{ ord.price }} • {{ ord.total }}</div>
              </div>
              <div class="order-mobile-right">
                <v-btn icon variant="text" size="small" class="order-cancel-icon" color="error" :disabled="cancelOrderLoading" @click.stop="cancelOrder(ord)">
                  <v-icon size="20">mdi-close</v-icon>
                </v-btn>
                <div class="order-mobile-filled">{{ ord.filledDisplay || ord.filled }}</div>
                <div class="order-mobile-expiry">Expiration: {{ ord.expiration }}</div>
              </div>
            </div>
          </div>
          <!-- 桌面端：表格 -->
          <v-table v-else class="wallet-table">
            <thead>
              <tr>
                <th class="text-left">MARKET</th>
                <th class="text-left">SIDE</th>
                <th class="text-left">OUTCOME</th>
                <th class="text-left">PRICE</th>
                <th class="text-left">FILLED</th>
                <th class="text-left">TOTAL</th>
                <th class="text-left">EXPIRATION</th>
                <th class="text-right">ACTION</th>
              </tr>
            </thead>
            <tbody>
              <tr v-if="filteredOpenOrders.length === 0">
                <td colspan="8" class="empty-cell">No open orders found.</td>
              </tr>
              <tr v-for="ord in paginatedOpenOrders" :key="ord.id">
                <td class="cell-market">{{ ord.market }}</td>
                <td>
                  <span :class="ord.side === 'Yes' ? 'side-yes' : 'side-no'">{{ ord.side }}</span>
                </td>
                <td>{{ ord.outcome }}</td>
                <td>{{ ord.price }}</td>
                <td>{{ ord.filled }}</td>
                <td>{{ ord.total }}</td>
                <td>{{ ord.expiration }}</td>
                <td class="text-right">
                  <v-btn variant="text" size="small" color="error" :disabled="cancelOrderLoading" @click="cancelOrder(ord)">Cancel</v-btn>
                </td>
              </tr>
            </tbody>
          </v-table>
        </template>
        <!-- 历史记录：移动端可展开列表 / 桌面端表格 -->
        <template v-else-if="activeTab === 'history'">
          <!-- 移动端：历史卡片列表 -->
          <div v-if="mobile" class="history-mobile-list">
            <template v-if="filteredHistory.length === 0">
              <div class="empty-cell">You haven't traded any polymarkets yet</div>
            </template>
            <div
              v-for="h in paginatedHistory"
              :key="h.id"
              class="history-mobile-card"
              :class="{ expanded: expandedHistoryId === h.id }"
              @click="toggleHistoryExpanded(h.id)"
            >
              <div class="history-mobile-row">
                <div class="history-mobile-icon" :class="h.iconClass">
                  <span class="position-icon-char">{{ h.iconChar }}</span>
                </div>
                <div class="history-mobile-main">
                  <div class="history-mobile-title">{{ h.market }}</div>
                  <div class="history-mobile-activity">{{ h.activityDetail || h.activity }}</div>
                </div>
                <div class="history-mobile-right">
                  <span :class="['history-mobile-pl', h.profitLossNegative ? 'pl-loss' : 'pl-gain']">
                    {{ h.profitLoss ?? h.value }}
                  </span>
                  <div class="history-mobile-time">{{ h.timeAgo || '' }}</div>
                </div>
                <v-icon size="20" class="history-chevron">
                  {{ expandedHistoryId === h.id ? 'mdi-chevron-up' : 'mdi-chevron-down' }}
                </v-icon>
              </div>
              <div v-show="expandedHistoryId === h.id" class="history-mobile-expanded" @click.stop>
                <div class="history-mobile-detail-row">
                  <span v-if="h.avgPrice" class="history-detail-label">AVG {{ h.avgPrice }}</span>
                  <span v-if="h.shares" class="history-detail-label">SHARES {{ h.shares }}</span>
                </div>
                <div class="history-mobile-actions">
                  <v-btn variant="outlined" size="small" class="history-view-btn" @click="viewHistory(h.id)">View</v-btn>
                  <v-btn icon variant="text" size="small" class="position-share-btn" @click="shareHistory(h.id)">
                    <v-icon size="18">mdi-open-in-new</v-icon>
                  </v-btn>
                </div>
              </div>
            </div>
          </div>
          <!-- 桌面端：表格 -->
          <v-table v-else class="wallet-table">
            <thead>
              <tr>
                <th class="text-left">ACTIVITY</th>
                <th class="text-left">MARKET</th>
                <th class="text-left">VALUE</th>
              </tr>
            </thead>
            <tbody>
              <tr v-if="filteredHistory.length === 0">
                <td colspan="3" class="empty-cell">You haven't traded any polymarkets yet</td>
              </tr>
              <tr v-for="h in paginatedHistory" :key="h.id">
                <td>
                  <span :class="h.side === 'Yes' ? 'side-yes' : 'side-no'">{{ h.activity }}</span>
                </td>
                <td class="cell-market">{{ h.market }}</td>
                <td>{{ h.value }}</td>
              </tr>
            </tbody>
          </v-table>
        </template>
        <!-- 分页 -->
        <div v-if="currentListTotal > 0" class="pagination-bar">
          <span class="pagination-info">
            {{ currentPageStart }}–{{ currentPageEnd }} of {{ currentListTotal }}
          </span>
          <div class="pagination-controls">
            <v-select
              v-model="itemsPerPage"
              :items="pageSizeOptions"
              density="compact"
              hide-details
              variant="outlined"
              class="page-size-select"
              @update:model-value="page = 1"
            />
            <v-pagination
              v-model="page"
              :length="currentTotalPages"
              :total-visible="5"
              density="comfortable"
              class="pagination"
              @update:model-value="onPageChange"
            />
          </div>
        </div>
      </v-card>
    </div>

    <DepositDialog
      v-model="depositDialogOpen"
      :balance="portfolioBalance"
    />
    <WithdrawDialog
      v-model="withdrawDialogOpen"
      :balance="portfolioBalance"
      @success="onWithdrawSuccess"
    />

    <!-- Sell position dialog -->
    <v-dialog v-model="sellDialogOpen" max-width="440" persistent content-class="sell-dialog" transition="dialog-transition">
      <v-card v-if="sellPositionItem" class="sell-dialog-card" rounded="lg">
        <div class="sell-dialog-header">
          <v-btn icon variant="text" size="small" class="sell-dialog-close" @click="closeSellDialog">
            <v-icon>mdi-close</v-icon>
          </v-btn>
        </div>
        <v-card-text class="sell-dialog-body">
          <div class="sell-dialog-icon-wrap">
            <div class="position-icon" :class="sellPositionItem.iconClass">
              <span class="position-icon-char">{{ sellPositionItem.iconChar }}</span>
            </div>
          </div>
          <h3 class="sell-dialog-title">Sell {{ sellPositionItem.sellOutcome || 'Position' }}</h3>
          <p class="sell-dialog-market">{{ sellPositionItem.market }}</p>
          <div class="sell-receive-box">
            <div class="sell-receive-label">
              <v-icon size="20" color="success">mdi-sack</v-icon>
              <span>Receive</span>
            </div>
            <div class="sell-receive-value">{{ sellReceiveAmount }}</div>
          </div>
        </v-card-text>
        <v-card-actions class="sell-dialog-actions">
          <v-btn color="success" variant="flat" block class="sell-redeem-btn" @click="redeemSell">
            Redeem
          </v-btn>
          <a href="#" class="sell-edit-link" @click.prevent="editSellOrder">Edit order</a>
        </v-card-actions>
      </v-card>
    </v-dialog>

    <v-snackbar v-model="showCancelError" color="error" :timeout="4000">
      {{ cancelOrderError }}
    </v-snackbar>
  </v-container>
</template>

<script setup lang="ts">
import { ref, computed, watch, onMounted, onUnmounted, nextTick } from 'vue'
import { useDisplay } from 'vuetify'
import * as echarts from 'echarts'
import type { ECharts } from 'echarts'
import DepositDialog from '../components/DepositDialog.vue'
import WithdrawDialog from '../components/WithdrawDialog.vue'
import { useUserStore } from '../stores/user'
import { pmCancelOrder } from '../api/market'

const { mobile } = useDisplay()
const userStore = useUserStore()
const portfolioBalance = computed(() => userStore.balance)
const profitLoss = ref('0.00')
const plRange = ref('ALL')
const plTimeRanges = ['1D', '1W', '1M', 'ALL']
const activeTab = ref<'positions' | 'orders' | 'history'>('positions')
const search = ref('')
const depositDialogOpen = ref(false)
const withdrawDialogOpen = ref(false)
const sellDialogOpen = ref(false)
const sellPositionItem = ref<Position | null>(null)
/** 移动端展开的持仓 id，null 表示全部折叠 */
const expandedPositionId = ref<string | null>(null)
/** 移动端展开的历史记录 id */
const expandedHistoryId = ref<string | null>(null)

function togglePositionExpanded(id: string) {
  expandedPositionId.value = expandedPositionId.value === id ? null : id
}

function toggleHistoryExpanded(id: string) {
  expandedHistoryId.value = expandedHistoryId.value === id ? null : id
}

interface Position {
  id: string
  market: string
  icon?: string
  iconChar?: string
  iconClass?: string
  outcomeTag?: string
  outcomePillClass?: string
  shares: string
  avgNow: string
  bet: string
  toWin: string
  value: string
  valueChange?: string
  valueChangePct?: string
  valueChangeLoss?: boolean
  /** 用于 Sell 弹窗标题，如 "Down" | "Yes" | "No" */
  sellOutcome?: string
  /** 移动端副标题 "on Up/Down to win" 中的词 */
  outcomeWord?: string
}

/** 从 avgNow "72¢ → 0.5¢" 解析出 [avg, now] */
function parseAvgNow(avgNow: string): [string, string] {
  const parts = avgNow.split(' → ')
  return parts.length >= 2 ? [parts[0]!.trim(), parts[1]!.trim()] : [avgNow, '']
}
interface OpenOrder {
  id: string
  market: string
  side: 'Yes' | 'No'
  outcome: string
  price: string
  filled: string
  total: string
  expiration: string
  /** 移动端展示：如 "Buy Up" */
  actionLabel?: string
  /** 移动端展示：如 "0/5" */
  filledDisplay?: string
  iconChar?: string
  iconClass?: string
  /** 取消订单 API 用 */
  orderID?: number
  tokenID?: string
}
interface HistoryItem {
  id: string
  market: string
  side: 'Yes' | 'No'
  activity: string
  value: string
  /** 移动端：如 "Sold 1 Down at 50¢" */
  activityDetail?: string
  /** 移动端：盈亏展示如 "+$0.50" */
  profitLoss?: string
  profitLossNegative?: boolean
  /** 移动端：如 "3 minutes ago" */
  timeAgo?: string
  avgPrice?: string
  shares?: string
  iconChar?: string
  iconClass?: string
}

const positions = ref<Position[]>([
  {
    id: 'p1',
    market: 'Bitcoin Up or Down - February 9, 2:00AM-2:15AM ET',
    iconChar: '₿',
    iconClass: 'position-icon-btc',
    outcomeTag: 'Down 72¢',
    outcomePillClass: 'pill-down',
    shares: '6.9 shares',
    avgNow: '72¢ → 0.5¢',
    bet: '$4.95',
    toWin: '$6.87',
    value: '$0.03',
    valueChange: '-$4.91',
    valueChangePct: '99.31%',
    valueChangeLoss: true,
    sellOutcome: 'Down',
    outcomeWord: 'Down',
  },
  {
    id: 'p2',
    market: 'Bitcoin Up or Down - February 9, 2:15AM-2:30AM ET',
    iconChar: '₿',
    iconClass: 'position-icon-btc',
    outcomeTag: 'Up 26¢',
    outcomePillClass: 'pill-yes',
    shares: '3.8 shares',
    avgNow: '28¢ → 26¢',
    bet: '$0.99',
    toWin: '$3.54',
    value: '$0.90',
    valueChange: '-$0.09',
    valueChangePct: '8.9%',
    valueChangeLoss: true,
    sellOutcome: 'Up',
    outcomeWord: 'Up',
  },
  {
    id: 'p3',
    market: 'Will ETH merge complete by Q3?',
    iconChar: 'Ξ',
    iconClass: 'position-icon-eth',
    outcomeTag: 'Yes 48¢',
    outcomePillClass: 'pill-yes',
    shares: '30 shares',
    avgNow: '45¢ → 48¢',
    bet: '$30',
    toWin: '$36',
    value: '$32',
    valueChange: '+$2',
    valueChangePct: '6.67%',
    valueChangeLoss: false,
    sellOutcome: 'Yes',
    outcomeWord: 'Yes',
  },
])
const MOCK_TOKEN_ID = '59966088656508531737144108943848781534186324373509174641856486864137458635937'
const openOrders = ref<OpenOrder[]>([
  {
    id: 'o1',
    market: 'Bitcoin Up or Down - February 9, 2:45AM-3:00AM ET',
    side: 'Yes',
    outcome: 'Up',
    price: '1¢',
    filled: '0',
    total: '$0.05',
    expiration: 'Until Cancelled',
    actionLabel: 'Buy Up',
    filledDisplay: '0/5',
    iconChar: '₿',
    iconClass: 'position-icon-btc',
    orderID: 5,
    tokenID: MOCK_TOKEN_ID,
  },
  {
    id: 'o2',
    market: 'Will Bitcoin hit $100k by end of 2025?',
    side: 'Yes',
    outcome: 'Yes',
    price: '70¢',
    filled: '0',
    total: '$70',
    expiration: 'Dec 31, 2025',
    orderID: 5,
    tokenID: MOCK_TOKEN_ID,
  },
  {
    id: 'o3',
    market: 'Will ETH merge complete by Q3?',
    side: 'No',
    outcome: 'No',
    price: '52¢',
    filled: '25',
    total: '$26',
    expiration: 'Sep 30, 2025',
    orderID: 5,
    tokenID: MOCK_TOKEN_ID,
  },
])
const history = ref<HistoryItem[]>([
  {
    id: 'h1',
    market: 'Bitcoin Up or Down - February 9, 3:00AM-3:15AM ET',
    side: 'No',
    activity: 'Sell No',
    activityDetail: 'Sold 1 Down at 50¢',
    value: '$0.50',
    profitLoss: '+$0.50',
    profitLossNegative: false,
    timeAgo: '3 minutes ago',
    avgPrice: '50¢',
    shares: '1',
    iconChar: '₿',
    iconClass: 'position-icon-btc',
  },
  {
    id: 'h2',
    market: 'Bitcoin Up or Down - February 9, 3:00AM-3:15AM ET',
    side: 'Yes',
    activity: 'Sell Yes',
    activityDetail: 'Sold 1 Up at 63¢',
    value: '$0.63',
    profitLoss: '+$0.63',
    profitLossNegative: false,
    timeAgo: '6 minutes ago',
    iconChar: '₿',
    iconClass: 'position-icon-btc',
  },
  {
    id: 'h3',
    market: 'Bitcoin Up or Down - February 9, 3:00AM-3:15AM ET',
    side: 'Yes',
    activity: 'Split',
    activityDetail: 'Split',
    value: '-$1.00',
    profitLoss: '-$1.00',
    profitLossNegative: true,
    timeAgo: '7 minutes ago',
    iconChar: '₿',
    iconClass: 'position-icon-btc',
  },
  { id: 'h4', market: 'Will ETH merge complete by Q3?', side: 'No', activity: 'Sell No', value: '$35.20' },
])

function matchSearch(text: string): boolean {
  const q = search.value.trim().toLowerCase()
  return !q || text.toLowerCase().includes(q)
}
const filteredPositions = computed(() => positions.value.filter((p) => matchSearch(p.market)))
const filteredOpenOrders = computed(() => openOrders.value.filter((o) => matchSearch(o.market)))
const filteredHistory = computed(() => history.value.filter((h) => matchSearch(h.market)))

const page = ref(1)
const itemsPerPage = ref(10)
const pageSizeOptions = [5, 10, 25, 50]

function paginate<T>(list: T[]) {
  const start = (page.value - 1) * itemsPerPage.value
  return list.slice(start, start + itemsPerPage.value)
}
const paginatedPositions = computed(() => paginate(filteredPositions.value))
const paginatedOpenOrders = computed(() => paginate(filteredOpenOrders.value))
const paginatedHistory = computed(() => paginate(filteredHistory.value))

const totalPagesPositions = computed(() => Math.max(1, Math.ceil(filteredPositions.value.length / itemsPerPage.value)))
const totalPagesOrders = computed(() => Math.max(1, Math.ceil(filteredOpenOrders.value.length / itemsPerPage.value)))
const totalPagesHistory = computed(() => Math.max(1, Math.ceil(filteredHistory.value.length / itemsPerPage.value)))

const currentListTotal = computed(() => {
  if (activeTab.value === 'positions') return filteredPositions.value.length
  if (activeTab.value === 'orders') return filteredOpenOrders.value.length
  return filteredHistory.value.length
})
const currentTotalPages = computed(() => {
  if (activeTab.value === 'positions') return totalPagesPositions.value
  if (activeTab.value === 'orders') return totalPagesOrders.value
  return totalPagesHistory.value
})
const currentPageStart = computed(() => currentListTotal.value === 0 ? 0 : (page.value - 1) * itemsPerPage.value + 1)
const currentPageEnd = computed(() => Math.min(page.value * itemsPerPage.value, currentListTotal.value))

watch(activeTab, () => { page.value = 1 })
watch([currentListTotal, itemsPerPage], () => {
  const maxPage = currentTotalPages.value
  if (page.value > maxPage) page.value = Math.max(1, maxPage)
})

function onPageChange() {
  // 可选：翻页后滚动到表格顶部
}

const cancelOrderLoading = ref(false)
const cancelOrderError = ref('')
const showCancelError = ref(false)
async function cancelOrder(ord: OpenOrder) {
  const orderID = ord.orderID ?? 5
  const tokenID = ord.tokenID ?? MOCK_TOKEN_ID
  const uid = userStore.user?.id ?? userStore.user?.ID
  const userID = uid != null ? Number(uid) : 0
  if (!Number.isFinite(userID) || userID <= 0) {
    cancelOrderError.value = '请先登录'
    showCancelError.value = true
    return
  }
  const headers = userStore.getAuthHeaders()
  if (!headers) {
    cancelOrderError.value = '请先登录'
    showCancelError.value = true
    return
  }
  cancelOrderLoading.value = true
  cancelOrderError.value = ''
  try {
    const res = await pmCancelOrder({ orderID, tokenID, userID }, { headers })
    if (res.code === 0 || res.code === 200) {
      openOrders.value = openOrders.value.filter((o) => o.id !== ord.id)
      userStore.fetchUsdcBalance()
    } else {
      cancelOrderError.value = res.msg || '取消失败'
      showCancelError.value = true
    }
  } catch (e) {
    cancelOrderError.value = e instanceof Error ? e.message : 'Request failed'
    showCancelError.value = true
  } finally {
    cancelOrderLoading.value = false
  }
}

function cancelAllOrders() {
  openOrders.value = []
}

const sellReceiveAmount = computed(() => {
  const pos = sellPositionItem.value
  return pos ? pos.value : '$0.00'
})

function openSellDialog(pos: Position) {
  sellPositionItem.value = pos
  sellDialogOpen.value = true
}

function closeSellDialog() {
  sellDialogOpen.value = false
  sellPositionItem.value = null
}

function sellPosition(id: string) {
  const pos = positions.value.find((p) => p.id === id)
  if (pos) openSellDialog(pos)
}

function redeemSell() {
  if (sellPositionItem.value) {
    // TODO: 调用赎回接口，成功后从持仓移除
    positions.value = positions.value.filter((p) => p.id !== sellPositionItem.value!.id)
    closeSellDialog()
  }
}

function editSellOrder() {
  // TODO: 跳转交易页或打开限价单
  closeSellDialog()
}

function sharePosition(id: string) {
  // TODO: 分享或复制链接
}

function closeLosses() {
  // TODO: 关闭亏损仓位或筛选
}

function viewHistory(id: string) {
  // TODO: 跳转交易详情或订单详情
}

function shareHistory(id: string) {
  // TODO: 分享或复制链接
}

const plChartRef = ref<HTMLElement | null>(null)
let plChartInstance: ECharts | null = null

/** 根据时间范围生成盈亏折线数据 [timestamp, pnl] */
function generatePlData(range: string): [number, number][] {
  const now = Date.now()
  let stepMs: number
  let count: number
  switch (range) {
    case '1D':
      stepMs = 60 * 60 * 1000
      count = 24
      break
    case '1W':
      stepMs = 24 * 60 * 60 * 1000
      count = 7
      break
    case '1M':
      stepMs = 24 * 60 * 60 * 1000
      count = 30
      break
    case 'ALL':
    default:
      stepMs = 24 * 60 * 60 * 1000
      count = 30
      break
  }
  const data: [number, number][] = []
  let pnl = 0
  for (let i = count; i >= 0; i--) {
    const t = now - i * stepMs
    pnl += (Math.random() - 0.48) * 20
    data.push([t, Math.round(pnl * 100) / 100])
  }
  return data
}

function buildPlChartOption(chartData: [number, number][]) {
  const lastPoint = chartData[chartData.length - 1]
  const lastVal = lastPoint != null ? lastPoint[1] : 0
  const lineColor = lastVal >= 0 ? '#059669' : '#dc2626'
  return {
    animation: false,
    tooltip: {
      trigger: 'axis',
      formatter: (params: unknown) => {
        const p = (Array.isArray(params) ? params[0] : params) as { name: string | number; value: unknown }
        const date = new Date(p.name as number)
        const val = Array.isArray(p.value) ? (p.value as number[])[1] : p.value
        const sign = Number(val) >= 0 ? '+' : ''
        return `${date.getMonth() + 1}/${date.getDate()} ${date.getHours()}:${date.getMinutes().toString().padStart(2, '0')}<br/>${sign}$${Number(val).toFixed(2)}`
      },
      axisPointer: { animation: false },
    },
    grid: { left: 8, right: 8, top: 8, bottom: 24, containLabel: false },
    xAxis: {
      type: 'time',
      axisLine: { show: false },
      axisTick: { show: false },
      axisLabel: { color: '#9ca3af', fontSize: 10 },
      splitLine: { show: false },
    },
    yAxis: {
      type: 'value',
      position: 'right',
      axisLine: { show: false },
      axisTick: { show: false },
      axisLabel: { color: '#9ca3af', fontSize: 10, formatter: (v: number) => `$${v}` },
      splitLine: { lineStyle: { type: 'dashed', color: '#e5e7eb' } },
    },
    series: [
      {
        type: 'line',
        data: chartData,
        smooth: true,
        showSymbol: false,
        lineStyle: { width: 2, color: lineColor },
        areaStyle: { color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [{ offset: 0, color: lineColor + '40' }, { offset: 1, color: lineColor + '08' }]) },
      },
    ],
  }
}

const plChartData = ref<[number, number][]>([])

function updatePlChart() {
  plChartData.value = generatePlData(plRange.value)
  const last = plChartData.value[plChartData.value.length - 1]
  if (last) profitLoss.value = last[1].toFixed(2)
  if (plChartInstance) plChartInstance.setOption(buildPlChartOption(plChartData.value), { replaceMerge: ['series'] })
}

function initPlChart() {
  if (!plChartRef.value) return
  plChartData.value = generatePlData(plRange.value)
  const last = plChartData.value[plChartData.value.length - 1]
  if (last) profitLoss.value = last[1].toFixed(2)
  plChartInstance = echarts.init(plChartRef.value)
  plChartInstance.setOption(buildPlChartOption(plChartData.value))
}

const handleResize = () => plChartInstance?.resize()

watch(plRange, () => updatePlChart())

onMounted(() => {
  nextTick(() => {
    initPlChart()
  })
  window.addEventListener('resize', handleResize)
})

onUnmounted(() => {
  window.removeEventListener('resize', handleResize)
  plChartInstance?.dispose()
  plChartInstance = null
})

function onWithdrawSuccess() {
  withdrawDialogOpen.value = false
}
</script>

<style scoped>
.wallet-container {
  max-width: 1200px;
  margin: 0 auto;
  padding: 24px 16px;
}

.wallet-cards {
  margin-bottom: 32px;
}

.wallet-card {
  padding: 20px;
  border: 1px solid #e5e7eb;
  height: 100%;
}

.card-header {
  display: flex;
  align-items: center;
  justify-content: space-between;
  margin-bottom: 12px;
}

.card-title {
  font-size: 14px;
  font-weight: 500;
  color: #374151;
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.title-icon {
  color: #9ca3af;
}

.balance-badge {
  display: inline-flex;
  align-items: center;
  gap: 4px;
  font-size: 12px;
  color: #059669;
  background-color: #d1fae5;
  padding: 4px 8px;
  border-radius: 6px;
}

.card-value {
  font-size: 28px;
  font-weight: 600;
  color: #111827;
  margin-bottom: 4px;
}

.card-value-row {
  display: flex;
  align-items: center;
  gap: 6px;
  margin-bottom: 4px;
}

.card-value-row .card-value {
  margin-bottom: 0;
}

.info-icon {
  color: #9ca3af;
}

.card-timeframe {
  font-size: 12px;
  color: #6b7280;
  margin-bottom: 16px;
}

.card-actions {
  display: flex;
  gap: 12px;
  flex-wrap: wrap;
}

.action-btn {
  text-transform: none;
}

.pl-tabs {
  display: flex;
  gap: 4px;
}

.pl-tab {
  min-width: 40px;
  text-transform: none;
  font-size: 12px;
}

.pl-chart {
  height: 120px;
  width: 100%;
  margin-top: 4px;
}

.wallet-section {
  margin-top: 8px;
}

.wallet-tabs {
  margin-bottom: 16px;
}

.toolbar {
  display: flex;
  gap: 12px;
  align-items: center;
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.search-field {
  max-width: 280px;
}

.search-field :deep(.v-field) {
  font-size: 14px;
}

.filter-btn {
  text-transform: none;
  font-size: 13px;
}

.table-card {
  border: 1px solid #e5e7eb;
  overflow: hidden;
}

.positions-table,
.wallet-table {
  font-size: 14px;
}

.wallet-table th,
.positions-table th {
  font-size: 11px;
  font-weight: 600;
  color: #6b7280;
  text-transform: uppercase;
  letter-spacing: 0.02em;
  padding: 12px 16px;
}

.th-icon {
  vertical-align: middle;
  margin-left: 2px;
  color: #9ca3af;
}

.positions-table td,
.wallet-table td {
  padding: 12px 16px;
  color: #374151;
}

.cell-market {
  max-width: 320px;
  word-break: break-word;
}

/* 持仓行：市场图标 + 标题 + 标签 + 份额 */
.position-market-cell {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.position-icon {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
  font-weight: 700;
  font-size: 18px;
}

.position-icon-btc {
  background: linear-gradient(135deg, #f97316 0%, #ea580c 100%);
}

.position-icon-eth {
  background: linear-gradient(135deg, #6366f1 0%, #4f46e5 100%);
}

.position-icon-svg {
  color: inherit;
}

.position-market-info {
  min-width: 0;
}

.position-market-title {
  display: block;
  font-weight: 500;
  color: #111827;
  margin-bottom: 6px;
  line-height: 1.3;
}

.position-meta {
  display: flex;
  align-items: center;
  gap: 8px;
  flex-wrap: wrap;
}

.position-outcome-pill {
  font-size: 12px;
  padding: 2px 8px;
  border-radius: 999px;
  font-weight: 500;
}

.pill-down {
  background-color: #fee2e2;
  color: #dc2626;
}

.pill-yes {
  background-color: #dcfce7;
  color: #059669;
}

.position-shares {
  font-size: 12px;
  color: #6b7280;
}

.cell-avg-now {
  white-space: nowrap;
}

.cell-value {
  vertical-align: top;
}

.position-value {
  font-weight: 500;
  color: #111827;
}

.position-value-change {
  font-size: 12px;
  margin-top: 2px;
}

.value-loss {
  color: #dc2626;
}

.value-gain {
  color: #059669;
}

.cell-actions {
  white-space: nowrap;
}

.position-row .cell-actions {
  display: flex;
  align-items: center;
  justify-content: flex-end;
  gap: 4px;
}

.position-sell-btn {
  text-transform: none;
  font-weight: 600;
}

.position-share-btn {
  color: #6b7280;
}

/* 移动端持仓可折叠列表 */
.positions-mobile-list {
  padding: 0;
}

.positions-mobile-list .empty-cell {
  padding: 48px 16px;
  text-align: center;
  color: #6b7280;
  font-size: 14px;
}

.position-mobile-card {
  border-bottom: 1px solid #f3f4f6;
  padding: 14px 16px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.position-mobile-card:last-child {
  border-bottom: none;
}

.position-mobile-card:hover {
  background-color: #fafafa;
}

.position-mobile-card.expanded {
  background-color: #f9fafb;
}

.position-mobile-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.position-mobile-card .position-icon {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  flex-shrink: 0;
}

.position-mobile-main {
  flex: 1;
  min-width: 0;
}

.position-mobile-title {
  font-size: 14px;
  font-weight: 500;
  color: #111827;
  line-height: 1.35;
  margin-bottom: 4px;
}

.position-mobile-sub {
  font-size: 12px;
  color: #6b7280;
}

.position-mobile-right {
  text-align: right;
  flex-shrink: 0;
}

.position-mobile-right .position-value {
  font-size: 15px;
  font-weight: 600;
  color: #111827;
}

.position-mobile-right .position-value-change {
  font-size: 12px;
  margin-top: 2px;
}

.position-mobile-expanded {
  margin-top: 14px;
  padding-top: 14px;
  border-top: 1px solid #e5e7eb;
}

.position-mobile-avg-row {
  display: flex;
  align-items: center;
  justify-content: space-between;
  font-size: 13px;
  color: #6b7280;
  margin-bottom: 12px;
}

.avg-now-label {
  font-weight: 500;
}

.avg-now-values {
  display: inline-flex;
  align-items: center;
  gap: 4px;
}

.avg-now-arrow {
  vertical-align: middle;
}

.position-mobile-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-end;
}

.position-mobile-actions .position-sell-btn {
  text-transform: none;
  font-weight: 600;
}

/* 移动端挂单列表 */
.orders-mobile-list {
  padding: 0;
}

.orders-mobile-list .empty-cell {
  padding: 48px 16px;
  text-align: center;
  color: #6b7280;
  font-size: 14px;
}

.order-mobile-card {
  display: flex;
  align-items: flex-start;
  gap: 12px;
  padding: 14px 16px;
  border-bottom: 1px solid #f3f4f6;
}

.order-mobile-card:last-child {
  border-bottom: none;
}

.order-mobile-icon {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
  font-weight: 700;
  font-size: 18px;
}

.order-mobile-main {
  flex: 1;
  min-width: 0;
}

.order-mobile-title {
  font-size: 14px;
  font-weight: 500;
  color: #111827;
  line-height: 1.35;
  margin-bottom: 4px;
}

.order-mobile-action {
  font-size: 13px;
  font-weight: 500;
  margin-bottom: 2px;
}

.order-mobile-price {
  font-size: 12px;
  color: #6b7280;
}

.order-mobile-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 4px;
  flex-shrink: 0;
}

.order-cancel-icon {
  min-width: 32px;
  padding: 0;
}

.order-mobile-filled {
  font-size: 13px;
  font-weight: 500;
  color: #111827;
}

.order-mobile-expiry {
  font-size: 11px;
  color: #9ca3af;
  white-space: nowrap;
}

.filter-btn-cancel {
  color: #dc2626;
}

.filter-btn-cancel .v-icon {
  color: inherit;
}

/* 移动端历史列表 */
.history-mobile-list {
  padding: 0;
}

.history-mobile-list .empty-cell {
  padding: 48px 16px;
  text-align: center;
  color: #6b7280;
  font-size: 14px;
}

.history-mobile-card {
  border-bottom: 1px solid #f3f4f6;
  padding: 14px 16px;
  cursor: pointer;
  transition: background-color 0.15s ease;
}

.history-mobile-card:last-child {
  border-bottom: none;
}

.history-mobile-card:hover {
  background-color: #fafafa;
}

.history-mobile-card.expanded {
  background-color: #f9fafb;
}

.history-mobile-row {
  display: flex;
  align-items: flex-start;
  gap: 12px;
}

.history-mobile-icon {
  width: 40px;
  height: 40px;
  border-radius: 8px;
  display: flex;
  align-items: center;
  justify-content: center;
  flex-shrink: 0;
  color: #fff;
  font-weight: 700;
  font-size: 18px;
}

.history-mobile-main {
  flex: 1;
  min-width: 0;
}

.history-mobile-title {
  font-size: 14px;
  font-weight: 500;
  color: #111827;
  line-height: 1.35;
  margin-bottom: 4px;
}

.history-mobile-activity {
  font-size: 13px;
  color: #6b7280;
}

.history-mobile-right {
  display: flex;
  flex-direction: column;
  align-items: flex-end;
  gap: 2px;
  flex-shrink: 0;
}

.history-mobile-pl {
  font-size: 14px;
  font-weight: 600;
}

.pl-gain {
  color: #059669;
}

.pl-loss {
  color: #dc2626;
}

.history-mobile-time {
  font-size: 12px;
  color: #9ca3af;
}

.history-chevron {
  color: #9ca3af;
  flex-shrink: 0;
  align-self: center;
}

.history-mobile-expanded {
  margin-top: 12px;
  padding-top: 12px;
  border-top: 1px solid #e5e7eb;
}

.history-mobile-detail-row {
  display: flex;
  gap: 16px;
  font-size: 13px;
  color: #6b7280;
  margin-bottom: 10px;
}

.history-detail-label {
  font-weight: 500;
}

.history-mobile-actions {
  display: flex;
  align-items: center;
  gap: 8px;
  justify-content: flex-end;
}

.history-view-btn {
  text-transform: none;
  font-weight: 500;
}

.filter-btn-close-losses {
  color: #6b7280;
}

.side-yes {
  color: #059669;
  font-weight: 500;
}

.side-no {
  color: #dc2626;
  font-weight: 500;
}

.empty-cell {
  text-align: center;
  color: #6b7280;
  padding: 48px 16px !important;
  font-size: 14px;
}

.pagination-bar {
  display: flex;
  align-items: center;
  justify-content: space-between;
  flex-wrap: wrap;
  gap: 12px;
  padding: 12px 16px;
  border-top: 1px solid #e5e7eb;
  font-size: 14px;
  color: #6b7280;
}

.pagination-info {
  flex-shrink: 0;
}

.pagination-controls {
  display: flex;
  align-items: center;
  gap: 12px;
}

.page-size-select {
  min-width: 88px;
  width: 88px;
  font-size: 14px;
}

.page-size-select :deep(.v-field) {
  font-size: 14px;
}

.page-size-select :deep(.v-field__input) {
  min-width: 2ch;
}

.pagination :deep(.v-pagination__item),
.pagination :deep(.v-pagination__prev),
.pagination :deep(.v-pagination__next) {
  min-width: 32px;
  height: 32px;
}

/* Sell position dialog */
.sell-dialog-card {
  padding: 0;
  overflow: hidden;
}

.sell-dialog-header {
  display: flex;
  justify-content: flex-end;
  padding: 12px 16px 0;
}

.sell-dialog-close {
  color: #6b7280;
}

.sell-dialog-body {
  padding: 0 24px 16px;
  text-align: center;
}

.sell-dialog-icon-wrap {
  margin-bottom: 12px;
}

.sell-dialog-body .position-icon {
  margin: 0 auto;
}

.sell-dialog-title {
  font-size: 20px;
  font-weight: 700;
  color: #111827;
  margin: 0 0 8px;
}

.sell-dialog-market {
  font-size: 14px;
  color: #6b7280;
  line-height: 1.4;
  margin: 0 0 20px;
}

.sell-receive-box {
  background-color: #dcfce7;
  border-radius: 12px;
  padding: 16px;
  text-align: left;
  display: flex;
  align-items: center;
  justify-content: space-between;
  gap: 12px;
}

.sell-receive-label {
  display: flex;
  align-items: center;
  gap: 8px;
  font-size: 14px;
  font-weight: 500;
  color: #166534;
}

.sell-receive-value {
  font-size: 18px;
  font-weight: 700;
  color: #166534;
}

.sell-dialog-actions {
  flex-direction: column;
  padding: 8px 24px 24px;
  gap: 12px;
}

.sell-redeem-btn {
  text-transform: none;
  font-weight: 600;
}

.sell-edit-link {
  font-size: 14px;
  color: #2563eb;
  text-decoration: none;
}

.sell-edit-link:hover {
  text-decoration: underline;
}
</style>
