<template>
  <div class="ai-analysis-container" :class="{ 'theme-dark': isDarkTheme }" :style="{ '--primary-color': primaryColor }">
    <!-- 全宽主内容区域 -->
    <div class="main-content-full">
      <!-- 顶部指数条 -->
      <div class="top-index-bar">
        <!-- 情绪指标 - 独立加载 -->
        <template v-if="loadingSentiment">
          <div class="indicator-box skeleton-box">
            <span class="skeleton-text short"></span>
            <span class="skeleton-text"></span>
          </div>
          <div class="indicator-box skeleton-box">
            <span class="skeleton-text short"></span>
            <span class="skeleton-text"></span>
          </div>
          <div class="indicator-box skeleton-box">
            <span class="skeleton-text short"></span>
            <span class="skeleton-text"></span>
          </div>
        </template>
        <template v-else>
          <div class="indicator-box fear-greed" :class="getFearGreedClass(marketData.fearGreed)">
            <span class="ind-label">{{ $t('globalMarket.fearGreedShort') }}</span>
            <span class="ind-value">{{ marketData.fearGreed || '--' }}</span>
          </div>
          <div class="indicator-box vix" :class="getVixLevel(marketData.vix)">
            <span class="ind-label">VIX</span>
            <span class="ind-value">{{ marketData.vix || '--' }}</span>
          </div>
          <div class="indicator-box dxy">
            <span class="ind-label">DXY</span>
            <span class="ind-value">{{ marketData.dxy || '--' }}</span>
          </div>
        </template>

        <!-- 全球指数滚动条 - 独立加载 -->
        <div class="indices-marquee">
          <template v-if="loadingIndices">
            <div class="indices-loading">
              <a-icon type="loading" /> {{ $t('common.loading') || '加载中...' }}
            </div>
          </template>
          <template v-else-if="marketData.indices.length > 0">
            <div class="marquee-track">
              <div class="index-item" v-for="idx in marketData.indices" :key="'a-'+idx.symbol">
                <span class="idx-flag">{{ idx.flag }}</span>
                <span class="idx-symbol">{{ idx.symbol }}</span>
                <span class="idx-price">{{ formatPrice(idx.price) }}</span>
                <span class="idx-change" :class="idx.change >= 0 ? 'up' : 'down'">
                  <a-icon :type="idx.change >= 0 ? 'caret-up' : 'caret-down'" />
                  {{ Math.abs(idx.change).toFixed(2) }}%
                </span>
              </div>
              <div class="index-item" v-for="idx in marketData.indices" :key="'b-'+idx.symbol">
                <span class="idx-flag">{{ idx.flag }}</span>
                <span class="idx-symbol">{{ idx.symbol }}</span>
                <span class="idx-price">{{ formatPrice(idx.price) }}</span>
                <span class="idx-change" :class="idx.change >= 0 ? 'up' : 'down'">
                  <a-icon :type="idx.change >= 0 ? 'caret-up' : 'caret-down'" />
                  {{ Math.abs(idx.change).toFixed(2) }}%
                </span>
              </div>
            </div>
          </template>
          <template v-else>
            <div class="indices-empty">--</div>
          </template>
        </div>
        <a-button type="link" size="small" class="refresh-btn" :loading="loadingMarket" @click="loadMarketData">
          <a-icon type="sync" :spin="loadingMarket" />
        </a-button>
      </div>

      <!-- 主体三栏布局 -->
      <div class="main-body">
        <!-- 左侧：热力图 + 财经日历 -->
        <div class="left-panel">
          <!-- 热力图 - 独立加载 -->
          <div class="heatmap-box">
            <div class="box-header">
              <a-radio-group v-model="heatmapType" size="small" button-style="solid">
                <a-radio-button value="crypto">{{ $t('globalMarket.cryptoHeatmap') }}</a-radio-button>
                <a-radio-button value="commodities">{{ $t('globalMarket.commoditiesHeatmap') }}</a-radio-button>
                <a-radio-button value="sectors">{{ $t('globalMarket.sectorHeatmap') }}</a-radio-button>
                <a-radio-button value="forex">{{ $t('globalMarket.forexHeatmap') }}</a-radio-button>
              </a-radio-group>
            </div>
            <div class="heatmap-grid">
              <template v-if="loadingHeatmap">
                <div v-for="i in 12" :key="'skel-'+i" class="heat-cell skeleton-cell">
                  <span class="skeleton-text short"></span>
                  <span class="skeleton-text"></span>
                </div>
              </template>
              <template v-else-if="currentHeatmap.length > 0">
                <div v-for="(item, i) in currentHeatmap.slice(0, 12)" :key="i" class="heat-cell" :style="getHeatmapStyle(item.value)">
                  <span class="heat-name">{{ getHeatmapName(item) }}</span>
                  <span class="heat-price" v-if="item.price">{{ formatHeatmapPrice(item.price) }}</span>
                  <span class="heat-val">{{ item.value >= 0 ? '+' : '' }}{{ formatNum(item.value) }}%</span>
                </div>
              </template>
              <template v-else>
                <div class="heatmap-empty">{{ $t('common.noData') || '暂无数据' }}</div>
              </template>
            </div>
          </div>

          <!-- 财经日历 - 独立加载 -->
          <div class="calendar-box">
            <div class="box-header">
              <span class="box-title"><a-icon type="calendar" /> {{ $t('globalMarket.calendar') }}</span>
            </div>
            <div class="calendar-list">
              <template v-if="loadingCalendar">
                <div v-for="i in 5" :key="'cal-skel-'+i" class="cal-item skeleton-item">
                  <span class="skeleton-text short"></span>
                  <span class="skeleton-text short"></span>
                  <span class="skeleton-text"></span>
                </div>
              </template>
              <template v-else-if="marketData.calendar.length > 0">
                <div v-for="evt in marketData.calendar.slice(0, 10)" :key="evt.id" class="cal-item" :class="evt.importance">
                  <span class="cal-date">{{ formatCalendarDate(evt.date) }}</span>
                  <span class="cal-time">{{ evt.time || '--:--' }}</span>
                  <span class="cal-flag">{{ getCountryFlag(evt.country) }}</span>
                  <span class="cal-name">{{ isZhLocale ? evt.name : evt.name_en }}</span>
                  <span class="cal-impact" :class="getImpactClass(evt)">
                    <a-icon v-if="getImpactClass(evt) === 'bullish'" type="arrow-up" />
                    <a-icon v-else-if="getImpactClass(evt) === 'bearish'" type="arrow-down" />
                    <a-icon v-else type="minus" />
                    {{ evt.actual || evt.forecast || '--' }}
                  </span>
                </div>
              </template>
              <template v-else>
                <div class="cal-empty">{{ $t('globalMarket.noEvents') }}</div>
              </template>
            </div>
          </div>
        </div>

        <!-- 右侧：工具栏 + AI 分析 -->
        <div class="right-panel">
          <!-- 分析工具栏 -->
          <div class="analysis-toolbar">
            <a-select
              v-model="selectedSymbol"
              :placeholder="$t('dashboard.analysis.empty.selectSymbol')"
              size="large"
              show-search
              allow-clear
              :filter-option="filterSymbolOption"
              @change="handleSymbolChange"
              class="symbol-selector"
            >
              <a-select-option
                v-for="stock in (watchlist || [])"
                :key="`${stock.market}-${stock.symbol}`"
                :value="`${stock.market}:${stock.symbol}`"
              >
                <span class="symbol-option">
                  <a-tag :color="getMarketColor(stock.market)" size="small">{{ getMarketName(stock.market) }}</a-tag>
                  <strong style="margin-left: 6px;">{{ stock.symbol }}</strong>
                  <span v-if="stock.name" class="symbol-name">{{ stock.name }}</span>
                </span>
              </a-select-option>
              <a-select-option key="add-stock-option" value="__add_stock_option__" class="add-stock-option">
                <div style="text-align: center; padding: 4px 0; color: #1890ff;">
                  <a-icon type="plus" style="margin-right: 4px;" />{{ $t('dashboard.analysis.watchlist.add') }}
                </div>
              </a-select-option>
            </a-select>
            <a-button
type="primary"
size="large"
icon="thunderbolt"
@click="startFastAnalysis"
:loading="analyzing"
:disabled="!selectedSymbol"
class="analyze-button">
              {{ $t('fastAnalysis.startAnalysis') }}
            </a-button>
            <a-button size="large" icon="history" @click="showHistoryModal = true; loadHistoryList()" class="history-button">
              {{ $t('fastAnalysis.history') }}
            </a-button>
          </div>

          <!-- 分析结果区域 -->
          <div class="analysis-main">
            <div v-if="!analysisResult && !analyzing" class="analysis-placeholder">
              <div class="placeholder-content">
                <div class="placeholder-icon"><a-icon type="robot" /></div>
                <h3>{{ $t('fastAnalysis.selectTip') }}</h3>
                <p>{{ $t('fastAnalysis.selectHint') }}</p>
              </div>
            </div>
            <FastAnalysisReport
              v-if="analysisResult || analyzing"
              :result="analysisResult"
              :loading="analyzing"
              :error="analysisError"
              @retry="startFastAnalysis"
            />
          </div>
        </div>

        <!-- 右侧自选股面板 -->
        <div class="watchlist-panel">
          <div class="panel-header">
            <span class="panel-title"><a-icon type="star" theme="filled" /> {{ $t('dashboard.analysis.watchlist.title') }}</span>
            <a-button type="link" size="small" @click="showAddStockModal = true">
              <a-icon type="plus" />
            </a-button>
          </div>
          <div class="watchlist-list">
            <div
              v-for="stock in (watchlist || [])"
              :key="`${stock.market}-${stock.symbol}`"
              class="watchlist-item"
              :class="{ active: selectedSymbol === `${stock.market}:${stock.symbol}` }"
              @click="selectWatchlistItem(stock)"
            >
              <div class="item-main">
                <span class="item-symbol">{{ stock.symbol }}</span>
                <span class="item-name">{{ stock.name || getMarketName(stock.market) }}</span>
              </div>
              <div class="item-price" v-if="watchlistPrices[`${stock.market}:${stock.symbol}`]">
                <span class="price-value">{{ formatPrice(watchlistPrices[`${stock.market}:${stock.symbol}`].price) }}</span>
                <span class="price-change" :class="(watchlistPrices[`${stock.market}:${stock.symbol}`]?.change || 0) >= 0 ? 'up' : 'down'">
                  {{ (watchlistPrices[`${stock.market}:${stock.symbol}`]?.change || 0) >= 0 ? '+' : '' }}{{ formatNum(watchlistPrices[`${stock.market}:${stock.symbol}`]?.change) }}%
                </span>
              </div>
              <a-icon type="close" class="item-remove" @click.stop="removeFromWatchlist(stock)" />
            </div>
            <div v-if="!watchlist || watchlist.length === 0" class="watchlist-empty">
              <a-icon type="inbox" />
              <p>{{ $t('dashboard.analysis.empty.noWatchlist') }}</p>
              <a-button type="primary" size="small" @click="showAddStockModal = true">
                <a-icon type="plus" /> {{ $t('dashboard.analysis.watchlist.add') }}
              </a-button>
            </div>
          </div>
        </div>
      </div>
    </div>

    <!-- 添加股票弹窗 -->
    <a-modal
      :title="$t('dashboard.analysis.modal.addStock.title')"
      :visible="showAddStockModal"
      @ok="handleAddStock"
      @cancel="handleCloseAddStockModal"
      :confirmLoading="addingStock"
      width="600px"
      :okText="$t('dashboard.analysis.modal.addStock.confirm')"
      :cancelText="$t('dashboard.analysis.modal.addStock.cancel')"
    >
      <div class="add-stock-modal-content">
        <!-- Tab标签 -->
        <a-tabs v-model="selectedMarketTab" @change="handleMarketTabChange" class="market-tabs">
          <a-tab-pane
            v-for="marketType in marketTypes"
            :key="marketType.value"
            :tab="$t(marketType.i18nKey || `dashboard.analysis.market.${marketType.value}`)"
          >
          </a-tab-pane>
        </a-tabs>

        <!-- 搜索/输入框 -->
        <div class="symbol-search-section">
          <a-input-search
            v-model="symbolSearchKeyword"
            :placeholder="$t('dashboard.analysis.modal.addStock.searchOrInputPlaceholder')"
            @search="handleSearchOrInput"
            @change="handleSymbolSearchInput"
            :loading="searchingSymbols"
            size="large"
            allow-clear
          >
            <a-button slot="enterButton" type="primary" icon="search">
              {{ $t('dashboard.analysis.modal.addStock.search') }}
            </a-button>
          </a-input-search>
        </div>

        <!-- 搜索结果 -->
        <div v-if="symbolSearchResults.length > 0" class="search-results-section">
          <div class="section-title">
            <a-icon type="search" style="margin-right: 4px;" />
            {{ $t('dashboard.analysis.modal.addStock.searchResults') }}
          </div>
          <a-list
            :data-source="symbolSearchResults"
            :loading="searchingSymbols"
            size="small"
            class="symbol-list"
          >
            <a-list-item slot="renderItem" slot-scope="item" class="symbol-list-item" @click="selectSymbol(item)">
              <a-list-item-meta>
                <template slot="title">
                  <div class="symbol-item-content">
                    <span class="symbol-code">{{ item.symbol }}</span>
                    <span class="symbol-name">{{ item.name }}</span>
                    <a-tag v-if="item.exchange" size="small" color="blue" style="margin-left: 8px;">
                      {{ item.exchange }}
                    </a-tag>
                  </div>
                </template>
              </a-list-item-meta>
            </a-list-item>
          </a-list>
        </div>

        <!-- 热门标的 -->
        <div class="hot-symbols-section">
          <div class="section-title">
            <a-icon type="fire" style="color: #ff4d4f; margin-right: 4px;" />
            {{ $t('dashboard.analysis.modal.addStock.hotSymbols') }}
          </div>
          <a-spin :spinning="loadingHotSymbols">
            <a-list
              v-if="hotSymbols.length > 0"
              :data-source="hotSymbols"
              size="small"
              class="symbol-list"
            >
              <a-list-item slot="renderItem" slot-scope="item" class="symbol-list-item" @click="selectSymbol(item)">
                <a-list-item-meta>
                  <template slot="title">
                    <div class="symbol-item-content">
                      <span class="symbol-code">{{ item.symbol }}</span>
                      <span class="symbol-name">{{ item.name }}</span>
                      <a-tag v-if="item.exchange" size="small" color="orange" style="margin-left: 8px;">
                        {{ item.exchange }}
                      </a-tag>
                    </div>
                  </template>
                </a-list-item-meta>
              </a-list-item>
            </a-list>
            <a-empty v-else :description="$t('dashboard.analysis.modal.addStock.noHotSymbols')" :image="false" />
          </a-spin>
        </div>

        <!-- 选中的标的显示 -->
        <div v-if="selectedSymbolForAdd" class="selected-symbol-section">
          <a-alert
            :message="$t('dashboard.analysis.modal.addStock.selectedSymbol')"
            type="info"
            show-icon
            closable
            @close="selectedSymbolForAdd = null"
          >
            <template slot="description">
              <div class="selected-symbol-info">
                <a-tag :color="getMarketColor(selectedSymbolForAdd.market)" style="margin-right: 8px;">
                  {{ $t(`dashboard.analysis.market.${selectedSymbolForAdd.market}`) }}
                </a-tag>
                <strong>{{ selectedSymbolForAdd.symbol }}</strong>
                <span v-if="selectedSymbolForAdd.name" style="color: #999; margin-left: 8px;">{{ selectedSymbolForAdd.name }}</span>
              </div>
            </template>
          </a-alert>
        </div>
      </div>
    </a-modal>

    <!-- 历史分析列表弹窗 -->
    <a-modal
      :title="$t('dashboard.analysis.modal.history.title')"
      :visible="showHistoryModal"
      @cancel="showHistoryModal = false"
      :footer="null"
      width="800px"
      :bodyStyle="{ maxHeight: '60vh', overflowY: 'auto' }"
    >
      <a-spin :spinning="historyLoading">
        <a-list
          :data-source="historyList"
          :pagination="{
            current: historyPage,
            pageSize: historyPageSize,
            total: historyTotal,
            onChange: (page) => { historyPage = page; loadHistoryList() },
            showSizeChanger: true,
            pageSizeOptions: ['10', '20', '50'],
            onShowSizeChange: (current, size) => { historyPageSize = size; historyPage = 1; loadHistoryList() }
          }"
        >
          <a-list-item slot="renderItem" slot-scope="item">
            <a-list-item-meta>
              <template slot="title">
                <div style="display: flex; align-items: center; justify-content: space-between;">
                  <div>
                    <a-tag :color="getMarketColor(item.market)" style="margin-right: 8px;">
                      {{ getMarketName(item.market) }}
                    </a-tag>
                    <strong>{{ item.symbol }}</strong>
                    <a-tag
                      :color="item.decision === 'BUY' ? 'green' : (item.decision === 'SELL' ? 'red' : 'blue')"
                      style="margin-left: 12px;"
                    >
                      {{ item.decision }}
                    </a-tag>
                    <span style="color: #999; margin-left: 8px; font-size: 12px;">
                      {{ $t('fastAnalysis.confidence') }}: {{ item.confidence }}%
                    </span>
                  </div>
                  <div>
                    <a-button
                      type="link"
                      size="small"
                      icon="eye"
                      @click="viewHistoryResult(item)"
                    >
                      {{ $t('dashboard.analysis.modal.history.viewResult') }}
                    </a-button>
                    <a-popconfirm
                      :title="$t('dashboard.analysis.modal.history.deleteConfirm')"
                      :ok-text="$t('common.confirm')"
                      :cancel-text="$t('common.cancel')"
                      @confirm="deleteHistoryItem(item)"
                    >
                      <a-button
                        type="link"
                        size="small"
                        icon="delete"
                        style="color: #ff4d4f;"
                      >
                        {{ $t('dashboard.analysis.modal.history.delete') }}
                      </a-button>
                    </a-popconfirm>
                  </div>
                </div>
              </template>
              <template slot="description">
                <div style="color: #666; font-size: 12px;">
                  <span v-if="item.price">${{ formatNumber(item.price) }}</span>
                  <span v-if="item.summary" style="margin-left: 8px;">{{ item.summary.substring(0, 80) }}{{ item.summary.length > 80 ? '...' : '' }}</span>
                </div>
                <div v-if="item.created_at" style="color: #999; font-size: 12px; margin-top: 4px;">
                  {{ formatIsoTime(item.created_at) }}
                </div>
              </template>
            </a-list-item-meta>
          </a-list-item>
        </a-list>
        <a-empty v-if="!historyLoading && historyList.length === 0" :description="$t('dashboard.analysis.empty.noHistory')" />
      </a-spin>
    </a-modal>
  </div>
</template>

<script>
import { mapGetters, mapState } from 'vuex'
import { getUserInfo } from '@/api/login'
import { getWatchlist, addWatchlist, removeWatchlist, getWatchlistPrices, getMarketTypes, searchSymbols, getHotSymbols } from '@/api/market'
import { fastAnalyze, getAllAnalysisHistory, deleteAnalysisHistory } from '@/api/fast-analysis'
import { getMarketSentiment, getMarketOverview, getMarketHeatmap, getEconomicCalendar } from '@/api/global-market'
import FastAnalysisReport from './components/FastAnalysisReport.vue'

export default {
  name: 'Analysis',
  components: {
    FastAnalysisReport
  },
  data () {
    return {
      loadingMarket: false,
      heatmapType: 'crypto',
      marketData: {
        fearGreed: null,
        vix: null,
        dxy: null,
        indices: [],
        heatmap: { crypto: [], commodities: [], sectors: [], forex: [] },
        calendar: []
      },
      // 独立加载状态 - 渐进式加载
      loadingSentiment: false,
      loadingIndices: false,
      loadingHeatmap: false,
      loadingCalendar: false,
      watchlistPriceTimer: null,
      watchlistPrices: {},
      localUserInfo: {},
      loadingUserInfo: false,
      userId: 1,
      watchlist: [],
      loadingWatchlist: false,
      showAddStockModal: false,
      addingStock: false,
      selectedSymbol: undefined,
      analyzing: false,
      analysisResult: null,
      analysisError: null,
      showHistoryModal: false,
      historyList: [],
      historyLoading: false,
      historyPage: 1,
      historyPageSize: 20,
      historyTotal: 0,
      marketTypes: [],
      selectedMarketTab: '',
      symbolSearchKeyword: '',
      symbolSearchResults: [],
      searchingSymbols: false,
      hotSymbols: [],
      loadingHotSymbols: false,
      selectedSymbolForAdd: null,
      searchTimer: null,
      hasSearched: false
    }
  },
  computed: {
    ...mapGetters(['userInfo']),
    ...mapState({
      navTheme: state => state.app.theme,
      primaryColor: state => state.app.color || '#1890ff'
    }),
    isDarkTheme () {
      return this.navTheme === 'dark' || this.navTheme === 'realdark'
    },
    isZhLocale () {
      return this.$i18n.locale === 'zh-CN'
    },
    currentHeatmap () {
      return this.marketData.heatmap[this.heatmapType] || []
    },
    storeUserInfo () {
      return this.userInfo || {}
    },
    mergedUserInfo () {
      return this.localUserInfo && this.localUserInfo.email ? this.localUserInfo : this.storeUserInfo
    }
  },
  created () {
    this.loadUserInfo()
    this.loadMarketTypes()
    this.loadWatchlist()
    this.loadMarketData()
  },
  mounted () {
    this.startWatchlistPriceRefresh()
  },
  beforeDestroy () {
    if (this.watchlistPriceTimer) {
      clearInterval(this.watchlistPriceTimer)
    }
  },
  methods: {
    filterSymbolOption (input, option) {
      const value = option.componentOptions?.propsData?.value || ''
      if (value === '__add_stock_option__') return true
      return value.toLowerCase().includes(input.toLowerCase())
    },
    handleSymbolChange (value) {
      if (value === '__add_stock_option__') {
        this.showAddStockModal = true
        this.$nextTick(() => {
          this.selectedSymbol = undefined
        })
        return
      }
      this.selectedSymbol = value
      // Clear previous result when symbol changes
      this.analysisResult = null
      this.analysisError = null
    },
    selectWatchlistItem (stock) {
      this.selectedSymbol = `${stock.market}:${stock.symbol}`
      this.analysisResult = null
      this.analysisError = null
    },
    async loadMarketData () {
      // 渐进式加载：每个数据块独立加载，先出来的先显示
      this.loadingMarket = true

      // 1. 加载情绪指标（恐惧贪婪、VIX、DXY）- 通常最快
      this.loadSentimentData()

      // 2. 加载全球指数 - 可能较慢
      this.loadIndicesData()

      // 3. 加载热力图数据
      this.loadHeatmapData()

      // 4. 加载财经日历
      this.loadCalendarData()
    },
    async loadSentimentData () {
      this.loadingSentiment = true
      try {
        const res = await getMarketSentiment()
        if (res?.code === 1 && res?.data) {
          this.marketData.fearGreed = res.data.fear_greed?.value || null
          this.marketData.vix = res.data.vix?.value || null
          this.marketData.dxy = res.data.dxy?.value || null
        }
      } catch (e) {
        console.error('Load sentiment failed:', e)
      } finally {
        this.loadingSentiment = false
        this.checkAllLoaded()
      }
    },
    async loadIndicesData () {
      this.loadingIndices = true
      try {
        const res = await getMarketOverview()
        if (res?.code === 1 && res?.data) {
          this.marketData.indices = res.data.indices || []
        }
      } catch (e) {
        console.error('Load indices failed:', e)
      } finally {
        this.loadingIndices = false
        this.checkAllLoaded()
      }
    },
    async loadHeatmapData () {
      this.loadingHeatmap = true
      try {
        const res = await getMarketHeatmap()
        if (res?.code === 1 && res?.data) {
          this.marketData.heatmap = {
            crypto: res.data.crypto || [],
            commodities: res.data.commodities || [],
            sectors: res.data.sectors || [],
            forex: res.data.forex || []
          }
        }
      } catch (e) {
        console.error('Load heatmap failed:', e)
      } finally {
        this.loadingHeatmap = false
        this.checkAllLoaded()
      }
    },
    async loadCalendarData () {
      this.loadingCalendar = true
      try {
        const res = await getEconomicCalendar()
        if (res?.code === 1) {
          this.marketData.calendar = res.data || []
        }
      } catch (e) {
        console.error('Load calendar failed:', e)
      } finally {
        this.loadingCalendar = false
        this.checkAllLoaded()
      }
    },
    checkAllLoaded () {
      // 当所有数据都加载完成时，关闭总loading状态
      if (!this.loadingSentiment && !this.loadingIndices && !this.loadingHeatmap && !this.loadingCalendar) {
        this.loadingMarket = false
      }
    },
    getFearGreedClass (val) {
      if (!val) return ''
      if (val <= 25) return 'extreme-fear'
      if (val <= 45) return 'fear'
      if (val <= 55) return 'neutral'
      if (val <= 75) return 'greed'
      return 'extreme-greed'
    },
    getVixLevel (val) {
      if (!val) return ''
      if (val < 15) return 'low'
      if (val < 25) return 'medium'
      return 'high'
    },
    formatNum (num, digits = 2) {
      if (num === undefined || num === null || isNaN(num)) return '--'
      return Number(num).toFixed(digits)
    },
    getHeatmapStyle (value) {
      const v = parseFloat(value) || 0
      const intensity = Math.min(Math.abs(v) / 5, 1)
      if (v >= 0) {
        return { background: `rgba(34, 197, 94, ${0.15 + intensity * 0.6})`, color: v > 2 ? '#fff' : '#166534' }
      } else {
        return { background: `rgba(239, 68, 68, ${0.15 + intensity * 0.6})`, color: v < -2 ? '#fff' : '#991b1b' }
      }
    },
    getCountryFlag (country) {
      const flags = { US: '🇺🇸', CN: '🇨🇳', EU: '🇪🇺', JP: '🇯🇵', UK: '🇬🇧', DE: '🇩🇪', AU: '🇦🇺', CA: '🇨🇦' }
      return flags[country] || '🌍'
    },
    formatCalendarDate (dateStr) {
      if (!dateStr) return ''
      try {
        const date = new Date(dateStr)
        const today = new Date()
        const tomorrow = new Date(today)
        tomorrow.setDate(tomorrow.getDate() + 1)

        // 判断是否是今天或明天
        if (date.toDateString() === today.toDateString()) {
          return this.isZhLocale ? '今天' : 'Today'
        }
        if (date.toDateString() === tomorrow.toDateString()) {
          return this.isZhLocale ? '明天' : 'Tmrw'
        }

        // 显示月/日
        const month = date.getMonth() + 1
        const day = date.getDate()
        return `${month}/${day}`
      } catch (e) {
        return dateStr
      }
    },
    formatPrice (price) {
      if (!price) return '--'
      if (price >= 10000) return (price / 1000).toFixed(1) + 'K'
      if (price >= 1000) return price.toFixed(0)
      return price.toFixed(2)
    },
    formatHeatmapPrice (price) {
      if (!price) return ''
      if (price >= 10000) return '$' + (price / 1000).toFixed(1) + 'K'
      if (price >= 1000) return '$' + price.toFixed(0)
      if (price >= 1) return '$' + price.toFixed(2)
      return '$' + price.toFixed(4)
    },
    getHeatmapName (item) {
      // sectors, commodities, forex 都需要多语言适配
      if (this.heatmapType === 'sectors' || this.heatmapType === 'commodities' || this.heatmapType === 'forex') {
        return this.isZhLocale ? (item.name_cn || item.name) : (item.name_en || item.name)
      }
      return item.name
    },
    getImpactClass (evt) {
      return evt.actual_impact || evt.expected_impact || 'neutral'
    },
    getMarketColor (market) {
      const colors = {
        'USStock': 'green',
        'Crypto': 'purple',
        'Forex': 'gold',
        'Futures': 'cyan',
        'AShare': 'blue',
        'HShare': 'orange'
      }
      return colors[market] || 'default'
    },
    getCurrencySymbol (market) {
      const dollarMarkets = ['USStock', 'Crypto', 'Forex', 'Futures']
      return dollarMarkets.includes(market) ? '$' : '¥'
    },
    async startFastAnalysis () {
      if (!this.selectedSymbol) {
        this.$message.warning(this.$t('dashboard.analysis.message.selectSymbol'))
        return
      }

      this.analyzing = true
      this.analysisError = null

      const [market, symbol] = this.selectedSymbol.split(':')
      const language = this.$store.getters.lang || 'zh-CN'

      try {
        const res = await fastAnalyze({
          market: market,
          symbol: symbol,
          language: language,
          timeframe: '1D'
        })

        if (res && res.code === 1 && res.data) {
          this.analysisResult = res.data
          this.$message.success(this.$t('dashboard.analysis.message.analysisComplete'))
        } else {
          throw new Error(res?.msg || '分析失败')
        }
      } catch (error) {
        console.error('Fast analysis failed:', error)
        this.analysisError = error?.response?.data?.msg || error?.message || this.$t('dashboard.analysis.message.analysisFailed')
        this.$message.error(this.analysisError)
      } finally {
        this.analyzing = false
      }
    },
    async loadHistoryList () {
      this.historyLoading = true
      try {
        const res = await getAllAnalysisHistory({
          page: this.historyPage,
          pagesize: this.historyPageSize
        })

        if (res && res.code === 1 && res.data) {
          this.historyList = res.data.list || []
          this.historyTotal = res.data.total || 0
        }
      } catch (error) {
        this.$message.error(this.$t('dashboard.analysis.message.loadHistoryFailed') || '加载历史记录失败')
      } finally {
        this.historyLoading = false
      }
    },
    async viewHistoryResult (item) {
      // 如果有完整结果，直接显示
      if (item.full_result) {
        this.analysisResult = item.full_result
        this.selectedSymbol = `${item.market}:${item.symbol}`
        this.showHistoryModal = false
        return
      }

      // 否则使用历史记录中的基本信息构建显示
      this.analysisResult = {
        decision: item.decision,
        confidence: item.confidence,
        summary: item.summary,
        market_data: {
          current_price: item.price,
          change_24h: 0
        },
        trading_plan: {
          entry_price: item.price,
          stop_loss: item.price * 0.95,
          take_profit: item.price * 1.05
        },
        scores: item.scores || {},
        reasons: item.reasons || [],
        risks: [],
        indicators: item.indicators || {},
        memory_id: item.id,
        analysis_time_ms: 0
      }
      this.selectedSymbol = `${item.market}:${item.symbol}`
      this.showHistoryModal = false
    },
    async deleteHistoryItem (item) {
      try {
        const res = await deleteAnalysisHistory(item.id)
        if (res && res.code === 1) {
          this.$message.success(this.$t('dashboard.analysis.message.deleteSuccess'))
          this.loadHistoryList()
        } else {
          this.$message.error(res?.msg || this.$t('dashboard.analysis.message.deleteFailed'))
        }
      } catch (error) {
        this.$message.error(this.$t('dashboard.analysis.message.deleteFailed'))
      }
    },
    formatTime (timestamp) {
      if (!timestamp) return '-'
      const date = new Date(timestamp * 1000)
      return date.toLocaleString('zh-CN')
    },
    formatIsoTime (isoString) {
      if (!isoString) return '-'
      const date = new Date(isoString)
      return date.toLocaleString('zh-CN')
    },
    getStatusColor (status) {
      const colors = {
        'pending': 'orange',
        'processing': 'blue',
        'completed': 'green',
        'failed': 'red'
      }
      return colors[status] || 'default'
    },
    getStatusText (status) {
      const statusMap = {
        'pending': 'dashboard.analysis.status.pending',
        'processing': 'dashboard.analysis.status.processing',
        'completed': 'dashboard.analysis.status.completed',
        'failed': 'dashboard.analysis.status.failed'
      }
      const key = statusMap[status]
      return key ? this.$t(key) : status
    },
    async loadUserInfo () {
      this.loadingUserInfo = true
      try {
        if (this.storeUserInfo && this.storeUserInfo.email) {
          this.localUserInfo = this.storeUserInfo
          this.userId = this.storeUserInfo.id
          this.loadingUserInfo = false
          this.loadWatchlist()
          return
        }
        const res = await getUserInfo()
        if (res && res.code === 1 && res.data) {
          this.localUserInfo = res.data
          this.userId = res.data.id
          this.$store.commit('SET_INFO', res.data)
          this.loadWatchlist()
        }
      } catch (error) {
        // Silent fail
      } finally {
        this.loadingUserInfo = false
      }
    },
    async loadWatchlist () {
      if (!this.userId) return
      this.loadingWatchlist = true
      try {
        const res = await getWatchlist({ userid: this.userId })
        if (res && res.code === 1 && res.data) {
          this.watchlist = res.data.map(item => ({
            ...item,
            price: 0,
            change: 0,
            changePercent: 0
          }))
          await this.loadWatchlistPrices()
        }
      } catch (error) {
        // Silent fail
      } finally {
        this.loadingWatchlist = false
      }
    },
    async loadWatchlistPrices () {
      if (!this.watchlist || this.watchlist.length === 0) return

      try {
        const watchlistData = this.watchlist.map(item => ({
          market: item.market,
          symbol: item.symbol
        }))

        const res = await getWatchlistPrices({
          watchlist: watchlistData
        })

        if (res && res.code === 1 && res.data) {
          const priceMap = {}
          const pricesObj = {}
          res.data.forEach(item => {
            priceMap[`${item.market}-${item.symbol}`] = item
            // 同时填充 watchlistPrices 对象（使用 : 作为键）
            pricesObj[`${item.market}:${item.symbol}`] = {
              price: item.price || 0,
              change: item.changePercent || 0
            }
          })
          this.watchlistPrices = pricesObj

          this.watchlist = this.watchlist.map(item => {
            const key = `${item.market}-${item.symbol}`
            const priceData = priceMap[key]
            if (priceData) {
              return {
                ...item,
                price: priceData.price || 0,
                change: priceData.change || 0,
                changePercent: priceData.changePercent || 0
              }
            }
            return item
          })
        }
      } catch (error) {
        // Silent fail
      }
    },
    startWatchlistPriceRefresh () {
      this.watchlistPriceTimer = setInterval(() => {
        if (this.watchlist && this.watchlist.length > 0) {
          this.loadWatchlistPrices()
        }
      }, 30000)

      if (this.watchlist && this.watchlist.length > 0) {
        this.loadWatchlistPrices()
      }
    },
    async handleAddStock () {
      let market = ''
      let symbol = ''
      let name = ''

      if (this.selectedSymbolForAdd) {
        market = this.selectedSymbolForAdd.market
        symbol = this.selectedSymbolForAdd.symbol.toUpperCase()
        name = this.selectedSymbolForAdd.name || ''
      } else if (this.symbolSearchKeyword && this.symbolSearchKeyword.trim()) {
        if (!this.selectedMarketTab) {
          this.$message.warning(this.$t('dashboard.analysis.modal.addStock.pleaseSelectMarket'))
          return
        }
        market = this.selectedMarketTab
        symbol = this.symbolSearchKeyword.trim().toUpperCase()
        name = ''
      } else {
        this.$message.warning(this.$t('dashboard.analysis.modal.addStock.pleaseSelectOrEnterSymbol'))
        return
      }

      this.addingStock = true
      try {
        const res = await addWatchlist({
          userid: this.userId,
          market: market,
          symbol: symbol,
          name: name
        })
        if (res && res.code === 1) {
          this.$message.success(this.$t('dashboard.analysis.message.addStockSuccess'))
          this.handleCloseAddStockModal()
          await this.loadWatchlist()
        } else {
          this.$message.error(res?.msg || this.$t('dashboard.analysis.message.addStockFailed'))
        }
      } catch (error) {
        const errorMsg = error?.response?.data?.msg || error?.message || this.$t('dashboard.analysis.message.addStockFailed')
        this.$message.error(errorMsg)
      } finally {
        this.addingStock = false
      }
    },
    handleCloseAddStockModal () {
      this.showAddStockModal = false
      this.selectedSymbolForAdd = null
      this.symbolSearchKeyword = ''
      this.symbolSearchResults = []
      this.hasSearched = false
      this.selectedMarketTab = this.marketTypes.length > 0 ? this.marketTypes[0].value : ''
    },
    handleMarketTabChange (activeKey) {
      this.selectedMarketTab = activeKey
      this.symbolSearchKeyword = ''
      this.symbolSearchResults = []
      this.selectedSymbolForAdd = null
      this.hasSearched = false
      this.loadHotSymbols(activeKey)
    },
    handleSymbolSearchInput (e) {
      const keyword = e.target.value
      this.symbolSearchKeyword = keyword

      if (this.searchTimer) {
        clearTimeout(this.searchTimer)
      }

      if (!keyword || keyword.trim() === '') {
        this.symbolSearchResults = []
        this.hasSearched = false
        this.selectedSymbolForAdd = null
        return
      }

      this.searchTimer = setTimeout(() => {
        this.searchSymbolsInModal(keyword)
      }, 500)
    },
    handleSearchOrInput (keyword) {
      if (!keyword || !keyword.trim()) return

      if (!this.selectedMarketTab) {
        this.$message.warning(this.$t('dashboard.analysis.modal.addStock.pleaseSelectMarket'))
        return
      }

      if (this.symbolSearchResults.length > 0) return

      if (this.hasSearched && this.symbolSearchResults.length === 0) {
        this.handleDirectAdd()
      } else {
        this.searchSymbolsInModal(keyword)
      }
    },
    async searchSymbolsInModal (keyword) {
      if (!keyword || keyword.trim() === '') {
        this.symbolSearchResults = []
        this.hasSearched = false
        return
      }

      if (!this.selectedMarketTab) {
        this.$message.warning(this.$t('dashboard.analysis.modal.addStock.pleaseSelectMarket'))
        return
      }

      this.searchingSymbols = true
      this.hasSearched = true
      try {
        const res = await searchSymbols({
          market: this.selectedMarketTab,
          keyword: keyword.trim(),
          limit: 20
        })
        if (res && res.code === 1 && res.data && res.data.length > 0) {
          this.symbolSearchResults = res.data
        } else {
          this.symbolSearchResults = []
          this.selectedSymbolForAdd = {
            market: this.selectedMarketTab,
            symbol: keyword.trim().toUpperCase(),
            name: ''
          }
        }
      } catch (error) {
        this.symbolSearchResults = []
        this.selectedSymbolForAdd = {
          market: this.selectedMarketTab,
          symbol: keyword.trim().toUpperCase(),
          name: ''
        }
      } finally {
        this.searchingSymbols = false
      }
    },
    handleDirectAdd () {
      if (!this.symbolSearchKeyword || !this.symbolSearchKeyword.trim()) {
        this.$message.warning(this.$t('dashboard.analysis.modal.addStock.pleaseEnterSymbol'))
        return
      }

      if (!this.selectedMarketTab) {
        this.$message.warning(this.$t('dashboard.analysis.modal.addStock.pleaseSelectMarket'))
        return
      }

      this.selectedSymbolForAdd = {
        market: this.selectedMarketTab,
        symbol: this.symbolSearchKeyword.trim().toUpperCase(),
        name: ''
      }
    },
    selectSymbol (symbol) {
      this.selectedSymbolForAdd = {
        market: symbol.market,
        symbol: symbol.symbol,
        name: symbol.name || symbol.symbol
      }
    },
    async loadHotSymbols (market) {
      if (!market) {
        market = this.selectedMarketTab || (this.marketTypes.length > 0 ? this.marketTypes[0].value : '')
      }

      if (!market) return

      this.loadingHotSymbols = true
      try {
        const res = await getHotSymbols({
          market: market,
          limit: 10
        })
        if (res && res.code === 1 && res.data) {
          this.hotSymbols = res.data
        } else {
          this.hotSymbols = []
        }
      } catch (error) {
        this.hotSymbols = []
      } finally {
        this.loadingHotSymbols = false
      }
    },
    async removeFromWatchlist (stock) {
      if (!this.userId) return
      // 支持传入 stock 对象或单独的 symbol/market
      const symbol = typeof stock === 'object' ? stock.symbol : stock
      const market = typeof stock === 'object' ? stock.market : arguments[1]
      try {
        const res = await removeWatchlist({
          userid: this.userId,
          symbol: symbol,
          market: market
        })
        if (res && res.code === 1) {
          this.$message.success(this.$t('dashboard.analysis.message.removeStockSuccess'))
          await this.loadWatchlist()
        } else {
          this.$message.error(res?.msg || this.$t('dashboard.analysis.message.removeStockFailed'))
        }
      } catch (error) {
        this.$message.error(this.$t('dashboard.analysis.message.removeStockFailed'))
      }
    },
    getMarketName (market) {
      return this.$t(`dashboard.analysis.market.${market}`) || market
    },
    formatNumber (num) {
      if (typeof num === 'string') return num
      return num.toLocaleString('en-US', { minimumFractionDigits: 2, maximumFractionDigits: 2 })
    },
    async loadMarketTypes () {
      try {
        const res = await getMarketTypes()
        if (res && res.code === 1 && res.data && Array.isArray(res.data)) {
          this.marketTypes = res.data.map(item => ({
            value: item.value,
            i18nKey: item.i18nKey || `dashboard.analysis.market.${item.value}`
          }))
        } else {
          this.marketTypes = [
            { value: 'USStock', i18nKey: 'dashboard.analysis.market.USStock' },
            { value: 'Crypto', i18nKey: 'dashboard.analysis.market.Crypto' },
            { value: 'Forex', i18nKey: 'dashboard.analysis.market.Forex' },
            { value: 'Futures', i18nKey: 'dashboard.analysis.market.Futures' },
            { value: 'HShare', i18nKey: 'dashboard.analysis.market.HShare' },
            { value: 'AShare', i18nKey: 'dashboard.analysis.market.AShare' }
          ]
        }
      } catch (error) {
        this.marketTypes = [
          { value: 'USStock', i18nKey: 'dashboard.analysis.market.USStock' },
          { value: 'Crypto', i18nKey: 'dashboard.analysis.market.Crypto' },
          { value: 'Forex', i18nKey: 'dashboard.analysis.market.Forex' },
          { value: 'Futures', i18nKey: 'dashboard.analysis.market.Futures' },
          { value: 'HShare', i18nKey: 'dashboard.analysis.market.HShare' },
          { value: 'AShare', i18nKey: 'dashboard.analysis.market.AShare' }
        ]
      }

      if (this.marketTypes.length > 0 && !this.selectedMarketTab) {
        this.selectedMarketTab = this.marketTypes[0].value
      }
    }
  },
  watch: {
    showAddStockModal (newVal) {
      if (newVal) {
        if (this.marketTypes.length > 0 && !this.selectedMarketTab) {
          this.selectedMarketTab = this.marketTypes[0].value
        }
        if (this.selectedMarketTab) {
          this.loadHotSymbols(this.selectedMarketTab)
        }
      } else {
        this.selectedSymbolForAdd = null
        this.symbolSearchKeyword = ''
        this.symbolSearchResults = []
        this.hasSearched = false
        if (this.searchTimer) {
          clearTimeout(this.searchTimer)
          this.searchTimer = null
        }
      }
    }
  }
}
</script>

<style lang="less" scoped>
.ai-analysis-container {
  display: flex;
  height: calc(100vh - 120px);
  background: #f0f2f5;
  overflow: hidden;
  width: 100%;
  box-sizing: border-box;
}

// 全宽主内容
.main-content-full {
  flex: 1;
  display: flex;
  flex-direction: column;
  overflow: hidden;
  background: #fff;
  border-radius: 12px;
  height: 100%;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.08);
  font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
}

// 顶部指数条
.top-index-bar {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 8px 16px;
  background: #f8fafc;
  border-bottom: 1px solid #e2e8f0;
  font-family: 'SF Mono', Monaco, Consolas, monospace;

  .indicator-box {
    display: flex;
    flex-direction: column;
    align-items: center;
    padding: 4px 10px;
    background: #fff;
    border-radius: 6px;
    border: 1px solid #e2e8f0;
    min-width: 50px;

    .ind-label { font-size: 9px; color: #94a3b8; text-transform: uppercase; }
    .ind-value { font-size: 13px; font-weight: 700; color: #1e293b; }

    &.fear-greed.extreme-fear .ind-value { color: #dc2626; }
    &.fear-greed.fear .ind-value { color: #ea580c; }
    &.fear-greed.neutral .ind-value { color: #ca8a04; }
    &.fear-greed.greed .ind-value { color: #65a30d; }
    &.fear-greed.extreme-greed .ind-value { color: #16a34a; }
    &.vix.low .ind-value { color: #16a34a; }
    &.vix.medium .ind-value { color: #ca8a04; }
    &.vix.high .ind-value { color: #dc2626; }
    &.dxy .ind-value { color: #2563eb; }
  }

  .indices-marquee {
    flex: 1;
    overflow: hidden;
    min-width: 0;

    .marquee-track {
      display: flex;
      gap: 8px;
      animation: marquee 35s linear infinite;
      width: max-content;
      &:hover { animation-play-state: paused; }
    }

    .index-item {
      display: flex;
      align-items: center;
      gap: 4px;
      padding: 4px 8px;
      background: #fff;
      border-radius: 4px;
      border: 1px solid #e2e8f0;
      font-size: 11px;
      white-space: nowrap;

      .idx-flag { font-size: 11px; }
      .idx-symbol { color: #64748b; font-weight: 500; }
      .idx-price { color: #1e293b; font-weight: 600; }
      .idx-change {
        font-weight: 600;
        display: flex;
        align-items: center;
        gap: 1px;
        &.up { color: #16a34a; }
        &.down { color: #dc2626; }
      }
    }
  }

  @keyframes marquee {
    0% { transform: translateX(0); }
    100% { transform: translateX(-50%); }
  }

  .refresh-btn {
    color: #94a3b8;
    flex-shrink: 0;
    &:hover { color: #1e293b; }
  }
}

// 主体三栏布局
.main-body {
  flex: 1;
  display: flex;
  gap: 12px;
  padding: 12px;
  overflow: hidden;
  min-height: 0;
}

// 左侧面板：热力图 + 财经日历
.left-panel {
  width: 280px;
  flex-shrink: 0;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow-y: auto;

  .heatmap-box {
    background: #fff;
    border-radius: 8px;
    padding: 12px;
    border: 1px solid #e2e8f0;

    .box-header {
      margin-bottom: 10px;
      ::v-deep .ant-radio-group .ant-radio-button-wrapper {
        font-size: 10px;
        padding: 0 6px;
        height: 22px;
        line-height: 20px;
        &.ant-radio-button-wrapper-checked {
          background: var(--primary-color, #1890ff);
          border-color: var(--primary-color, #1890ff);
          color: #fff;
        }
      }
    }

    .heatmap-grid {
      display: grid;
      grid-template-columns: repeat(3, 1fr);
      gap: 4px;

      .heat-cell {
        padding: 6px 4px;
        border-radius: 4px;
        text-align: center;
        font-size: 9px;
        .heat-name { display: block; font-weight: 600; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; margin-bottom: 1px; }
        .heat-price { display: block; font-size: 9px; opacity: 0.8; margin-bottom: 1px; }
        .heat-val { font-weight: 700; font-size: 10px; }
      }
    }
  }

  .calendar-box {
    flex: 1;
    background: #fff;
    border-radius: 8px;
    padding: 12px;
    border: 1px solid #e2e8f0;
    display: flex;
    flex-direction: column;
    min-height: 0;
    overflow: hidden;

    .box-header {
      margin-bottom: 8px;
      .box-title {
        font-size: 12px;
        color: #64748b;
        font-weight: 600;
        .anticon { margin-right: 6px; color: var(--primary-color, #1890ff); }
      }
    }

    .calendar-list {
      flex: 1;
      overflow-y: auto;

      &::-webkit-scrollbar { width: 4px; }
      &::-webkit-scrollbar-thumb { background: #cbd5e1; border-radius: 2px; }

      .cal-item {
        display: flex;
        align-items: center;
        gap: 6px;
        padding: 6px 0;
        border-bottom: 1px solid #f1f5f9;
        font-size: 10px;
        &:last-child { border-bottom: none; }
        &.high { border-left: 3px solid #dc2626; padding-left: 8px; margin-left: -4px; }
        &.medium { border-left: 3px solid #ca8a04; padding-left: 8px; margin-left: -4px; }
        &.low { border-left: 3px solid #16a34a; padding-left: 8px; margin-left: -4px; }

        .cal-date {
          font-size: 9px;
          color: #94a3b8;
          min-width: 32px;
          font-weight: 500;
        }
        .cal-time { color: #64748b; min-width: 36px; font-weight: 500; }
        .cal-flag { font-size: 12px; }
        .cal-name { flex: 1; color: #334155; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
        .cal-impact {
          font-weight: 600;
          font-size: 10px;
          display: flex;
          align-items: center;
          gap: 2px;
          &.bullish { color: #16a34a; }
          &.bearish { color: #dc2626; }
          &.neutral { color: #94a3b8; }
        }
      }
      .cal-empty { text-align: center; color: #94a3b8; padding: 20px 0; font-size: 12px; }
    }
  }
}

// 右侧面板：工具栏 + 分析结果
// 中间分析面板
.right-panel {
  flex: 1;
  display: flex;
  flex-direction: column;
  min-width: 0;
  overflow: hidden;
  background: #fff;
  border-radius: 8px;
  border: 1px solid #e2e8f0;

  .analysis-toolbar {
    display: flex;
    align-items: center;
    gap: 12px;
    padding: 12px 16px;
    border-bottom: 1px solid #f1f5f9;
    background: #fafafa;
    border-radius: 8px 8px 0 0;

    .symbol-selector {
      flex: 1;
      max-width: 320px;
    }

    .analyze-button {
      background: var(--primary-color, #1890ff);
      border-color: var(--primary-color, #1890ff);
    }

    .history-button {
      border-color: #d9d9d9;
    }
  }

  .analysis-main {
    flex: 1;
    overflow: auto;
    padding: 16px;
    min-height: 0;

    .analysis-placeholder {
      display: flex;
      align-items: center;
      justify-content: center;
      height: 100%;
      min-height: 300px;

      .placeholder-content {
        text-align: center;
        .placeholder-icon { font-size: 72px; color: var(--primary-color, #1890ff); opacity: 0.5; margin-bottom: 20px; }
        h3 { font-size: 18px; color: #1e293b; margin-bottom: 8px; }
        p { font-size: 14px; color: #64748b; }
      }
    }
  }
}

// 右侧自选股面板
.watchlist-panel {
  width: 200px;
  flex-shrink: 0;
  background: #fff;
  border-radius: 8px;
  border: 1px solid #e2e8f0;
  display: flex;
  flex-direction: column;
  overflow: hidden;

  .panel-header {
    display: flex;
    align-items: center;
    justify-content: space-between;
    padding: 10px 12px;
    border-bottom: 1px solid #f1f5f9;
    background: #fafafa;

    .panel-title {
      font-size: 12px;
      font-weight: 600;
      color: #64748b;
      .anticon { color: #facc15; margin-right: 6px; }
    }
  }

  .watchlist-list {
    flex: 1;
    overflow-y: auto;
    padding: 8px;

    &::-webkit-scrollbar { width: 4px; }
    &::-webkit-scrollbar-thumb { background: #e2e8f0; border-radius: 2px; }

    .watchlist-item {
      display: flex;
      align-items: center;
      padding: 8px 10px;
      border-radius: 6px;
      cursor: pointer;
      transition: all 0.2s;
      margin-bottom: 4px;

      &:hover { background: #f8fafc; }
      &.active { background: #e6f7ff; border: 1px solid #91d5ff; }

      .item-main {
        flex: 1;
        min-width: 0;
        .item-symbol { display: block; font-size: 12px; font-weight: 600; color: #1e293b; }
        .item-name { display: block; font-size: 10px; color: #94a3b8; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; }
      }

      .item-price {
        text-align: right;
        margin-right: 8px;
        font-family: 'SF Mono', Monaco, monospace;
        .price-value { display: block; font-size: 11px; font-weight: 600; color: #1e293b; }
        .price-change {
          display: block;
          font-size: 10px;
          font-weight: 600;
          &.up { color: #16a34a; }
          &.down { color: #dc2626; }
        }
      }

      .item-remove {
        color: #cbd5e1;
        font-size: 12px;
        opacity: 0;
        transition: opacity 0.2s;
        &:hover { color: #dc2626; }
      }

      &:hover .item-remove { opacity: 1; }
    }

    .watchlist-empty {
      text-align: center;
      padding: 24px 12px;
      color: #94a3b8;
      .anticon { font-size: 32px; margin-bottom: 8px; display: block; }
      p { font-size: 12px; margin-bottom: 12px; }
    }
  }
}

@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.5; }
}

/* Responsive */
@media (max-width: 992px) {
  .ai-analysis-container {
    height: auto;
    min-height: calc(100vh - 64px);
    overflow-y: auto;
  }

  .main-content-full {
    height: auto;
    min-height: auto;
  }

  .top-index-bar {
    flex-wrap: wrap;
    padding: 8px;

    .indicator-box {
      min-width: 45px;
      padding: 3px 6px;
    }

    .indices-marquee {
      order: 10;
      width: 100%;
      margin-top: 8px;
    }
  }

  .main-body {
    flex-direction: column;
    padding: 12px;
  }

  .left-panel {
    width: 100%;
    flex-direction: row;
    gap: 12px;

    .heatmap-box, .calendar-box {
      flex: 1;
      min-width: 0;
    }

    .calendar-box {
      max-height: 200px;
    }
  }

  .right-panel {
    .analysis-toolbar {
      flex-wrap: wrap;
      .symbol-selector { width: 100% !important; max-width: none !important; }
      .analyze-button, .history-button { flex: 1; }
    }
  }

  .watchlist-panel {
    width: 100%;
    max-height: 200px;
    order: -1;
  }
}

/* Dark Theme */
.ai-analysis-container.theme-dark {
  background: #131722;
  color: #d1d4dc;

  .main-content-full {
    background: #1e222d;
    box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
  }

  .top-index-bar {
    background: #1e222d;
    border-bottom-color: #363c4e;

    .indicator-box {
      background: #2a2e39;
      border-color: #363c4e;
      .ind-label { color: #868993; }
      .ind-value { color: #d1d4dc; }
    }

    .indices-marquee .index-item {
      background: #2a2e39;
      border-color: #363c4e;
      .idx-symbol { color: #868993; }
      .idx-price { color: #d1d4dc; }
    }

    .refresh-btn {
      color: #868993;
      &:hover { color: #d1d4dc; }
    }
  }

  .watchlist-panel {
    background: #2a2e39;
    border-color: #363c4e;

    .panel-header {
      background: #1e222d;
      border-bottom-color: #363c4e;
      .panel-title { color: #868993; }
    }

    .watchlist-list {
      .watchlist-item {
        &:hover { background: #363c4e; }
        &.active { background: rgba(24, 144, 255, 0.1); border-color: #1890ff; }
        .item-main {
          .item-symbol { color: #d1d4dc; }
          .item-name { color: #64748b; }
        }
        .item-price .price-value { color: #d1d4dc; }
      }
      .watchlist-empty { color: #64748b; }
    }
  }

  .watchlist-bar-legacy {
    background: #1e222d;
    border-bottom-color: #363c4e;

    .stock-chip {
      background: #2a2e39;
      border-color: #363c4e;
      &:hover, &.active { border-color: var(--primary-color, #1890ff); background: rgba(24, 144, 255, 0.1); }
      .chip-symbol { color: #d1d4dc; }
      .chip-price { color: #868993; }
    }
  }

  .left-panel {
    .heatmap-box {
      background: #2a2e39;
      border-color: #363c4e;

      ::v-deep .ant-radio-group .ant-radio-button-wrapper {
        background: #1e222d;
        border-color: #363c4e;
        color: #868993;
        &:hover { color: #d1d4dc; }
      }
    }

    .calendar-box {
      background: #2a2e39;
      border-color: #363c4e;

      .box-title { color: #868993; }
      .cal-item {
        border-bottom-color: #363c4e;
        .cal-date { color: #64748b; }
        .cal-time { color: #868993; }
        .cal-name { color: #d1d4dc; }
      }
      .cal-empty { color: #64748b; }
    }
  }

  .right-panel {
    background: #2a2e39;
    border-color: #363c4e;

    .analysis-toolbar {
      background: #1e222d;
      border-bottom-color: #363c4e;

      .history-button {
        background: #2a2e39;
        border-color: #363c4e;
        color: #d1d4dc;
      }
    }

    .analysis-main {
      .analysis-placeholder .placeholder-content {
        h3 { color: #d1d4dc; }
        p { color: #868993; }
      }
    }
  }

  // 旧样式兼容
  .watchlist-bar-compat {
    background: #1e222d;
    border-top-color: #363c4e;

    .bar-label { color: #868993; }

    .stock-chip {
      background: #2a2e39;
      border-color: #363c4e;

      &:hover, &.active {
        border-color: var(--primary-color, #1890ff);
        background: rgba(24, 144, 255, 0.1);
      }

      .chip-symbol { color: #d1d4dc; }
      .chip-price { color: #868993; }
      .chip-remove { color: #64748b; }
    }
  }

  ::v-deep .symbol-selector {
    .ant-select-selection {
      background-color: #2a2e39;
      border-color: #363c4e;
      color: #d1d4dc;
    }
  }
}

/* Add Stock Modal */
.add-stock-modal-content {
  .market-tabs { margin-bottom: 16px; }
  .symbol-search-section { margin-bottom: 24px; }

  .search-results-section,
  .hot-symbols-section {
    margin-bottom: 24px;

    .section-title {
      font-size: 14px;
      font-weight: 600;
      color: #262626;
      margin-bottom: 12px;
      display: flex;
      align-items: center;
    }
  }

  .symbol-list {
    max-height: 200px;
    overflow-y: auto;
    border: 1px solid #e8e8e8;
    border-radius: 4px;

    .symbol-list-item {
      cursor: pointer;
      padding: 8px 12px;
      transition: background-color 0.3s;

      &:hover { background-color: #f5f5f5; }

      .symbol-item-content {
        display: flex;
        align-items: center;
        gap: 8px;

        .symbol-code {
          font-weight: 600;
          color: #262626;
          min-width: 80px;
        }

        .symbol-name {
          color: #595959;
          flex: 1;
          overflow: hidden;
          text-overflow: ellipsis;
          white-space: nowrap;
        }
      }
    }
  }

  .selected-symbol-section {
    margin-top: 16px;

    .selected-symbol-info {
      display: flex;
      align-items: center;
    }
  }
}

/* 骨架屏加载动画 - 渐进式加载 */
.skeleton-box {
  .skeleton-text {
    display: block;
    height: 12px;
    background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
    background-size: 200% 100%;
    animation: skeleton-pulse 1.5s ease-in-out infinite;
    border-radius: 4px;
    margin: 3px 0;

    &.short { width: 40px; height: 9px; }
  }
}

.skeleton-cell {
  background: #f8fafc !important;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  padding: 8px 4px;

  .skeleton-text {
    width: 80%;
    height: 10px;
    background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
    background-size: 200% 100%;
    animation: skeleton-pulse 1.5s ease-in-out infinite;
    border-radius: 3px;
    margin: 2px 0;

    &.short { width: 50%; height: 8px; }
  }
}

.skeleton-item {
  display: flex;
  align-items: center;
  gap: 8px;
  padding: 6px 0;

  .skeleton-text {
    height: 12px;
    background: linear-gradient(90deg, #e2e8f0 25%, #f1f5f9 50%, #e2e8f0 75%);
    background-size: 200% 100%;
    animation: skeleton-pulse 1.5s ease-in-out infinite;
    border-radius: 4px;
    flex: 1;

    &.short { flex: none; width: 40px; }
  }
}

.indices-loading, .indices-empty {
  display: flex;
  align-items: center;
  justify-content: center;
  height: 100%;
  font-size: 11px;
  color: #94a3b8;
  padding: 4px 16px;
}

.indices-loading {
  .anticon { margin-right: 6px; }
}

.heatmap-empty {
  grid-column: 1 / -1;
  text-align: center;
  padding: 20px;
  color: #94a3b8;
  font-size: 12px;
}

@keyframes skeleton-pulse {
  0% { background-position: 200% 0; }
  100% { background-position: -200% 0; }
}

/* 暗色主题下的骨架屏 */
.theme-dark {
  .skeleton-box, .skeleton-cell, .skeleton-item {
    .skeleton-text {
      background: linear-gradient(90deg, #363c4e 25%, #424857 50%, #363c4e 75%);
      background-size: 200% 100%;
    }
  }

  .skeleton-cell {
    background: #2a2e39 !important;
  }

  .indices-loading, .indices-empty, .heatmap-empty {
    color: #64748b;
  }
}
</style>
