<template>
  <div class="lof-app">
    <div class="header">
      <div class="title">
        <span class="update-time">数据更新时间：{{ lastUpdateTime }}</span>
      </div>
      <div class="tool-bar">
        <el-button @click="showFilters = !showFilters" class="filter-toggle-btn" :icon="showFilters ? RefreshRight : Search">
          {{ showFilters ? '收起筛选' : '筛选' }}
        </el-button>
        <el-button @click="manualRefresh" :loading="loading" type="primary" :icon="Refresh">
          手动刷新
        </el-button>
      </div>
    </div>

    <div class="filter-bar" v-show="showFilters">
      <el-input v-model="searchCode" placeholder="基金代码" clearable class="filter-input filter-input-sm" />
      <el-input v-model="searchName" placeholder="基金名称" clearable class="filter-input" />
      <el-select v-model="filterStatus" placeholder="申购状态" clearable class="filter-select">
        <el-option v-for="s in statusOptions" :key="s" :label="s" :value="s" />
      </el-select>
      <el-select v-model="filterRedeemStatus" placeholder="赎回状态" clearable class="filter-select">
        <el-option v-for="s in redeemStatusOptions" :key="s" :label="s" :value="s" />
      </el-select>
      <el-checkbox v-model="filterByScale" class="filter-checkbox">规模≥3000万</el-checkbox>
      <el-radio-group v-model="showOnlyFavorites" size="small" class="filter-radio">
        <el-radio-button :label="false">全部基金</el-radio-button>
        <el-radio-button :label="true">我的关注</el-radio-button>
      </el-radio-group>
      <el-button @click="resetFilter" :icon="RefreshRight" class="filter-reset-btn">重置</el-button>
    </div>

    <el-table :data="displayList" v-loading="loading" height="calc(100vh - 180px)" border :default-sort="{ prop: 'premiumRate', order: 'descending' }" style="width: 100%" size="small">
      <el-table-column prop="fundCode" label="基金代码" align="center" min-width="80">
        <template #default="{ row }">
          <a class="fund-code-link" @click="goHistory(row)">{{ row.fundCode }}</a>
        </template>
      </el-table-column>
      <el-table-column prop="fundName" label="基金名称" align="center" min-width="100" />
      <el-table-column prop="premiumRate" label="溢价率(昨日)" align="center" min-width="95" sortable :sort-method="(a, b) => numericSort(a, b, 'premiumRate')">
        <template #default="{ row }">
          <span :class="getRateClass(row.premiumRate)">
            {{ row.premiumRate }}%
          </span>
        </template>
      </el-table-column>
      <el-table-column prop="estimatePremiumRate" label="溢价率(实时)" align="center" min-width="95" sortable :sort-method="(a, b) => numericSort(a, b, 'estimatePremiumRate')">
        <template #default="{ row }">
          <span :class="getRateClass(row.estimatePremiumRate)">
            {{ row.estimatePremiumRate }}%
          </span>
        </template>
      </el-table-column>
      <el-table-column label="申购状态" align="center" width="85">
        <template #default="{ row }">
          <el-tag :type="row.purchaseStatus === '暂停申购' ? 'danger' : row.purchaseStatus === '开放申购' ? 'success' : 'info'" size="small" style="white-space: nowrap;">
            {{ row.purchaseStatus }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column label="赎回状态" align="center" width="85">
        <template #default="{ row }">
          <el-tag :type="row.redemptionStatus === '暂停赎回' ? 'danger' : row.redemptionStatus === '开放赎回' ? 'success' : 'info'" size="small" style="white-space: nowrap;">
            {{ row.redemptionStatus || '-' }}
          </el-tag>
        </template>
      </el-table-column>
      <el-table-column prop="purchaseLimit" label="日限额" align="center" min-width="85" sortable :sort-method="(a, b) => numericSort(a, b, 'purchaseLimit')" />
      <!-- 溢价率(实时2) - 已隐藏，保留计算逻辑
      <el-table-column prop="estimatePremiumRate2" label="溢价率(实时2)" align="center" min-width="95" sortable :sort-method="(a, b) => numericSort(a, b, 'estimatePremiumRate2')">
        <template #default="{ row }">
          <span :class="getRateClass(row.estimatePremiumRate2)">
            {{ row.estimatePremiumRate2 }}%
          </span>
        </template>
      </el-table-column>
      -->
      <el-table-column prop="tradePrice" label="场内价格" align="center" min-width="80" sortable :sort-method="(a, b) => numericSort(a, b, 'tradePrice')" />
      <el-table-column prop="netValue" label="场外净值(昨日)" align="center" min-width="105" sortable :sort-method="(a, b) => numericSort(a, b, 'netValue')" />
      <el-table-column prop="estimateValue" label="估算净值(实时)" align="center" min-width="105" sortable :sort-method="(a, b) => numericSort(a, b, 'estimateValue')" />
      <el-table-column prop="increaseRate" label="涨跌幅" align="center" min-width="80" sortable :sort-method="(a, b) => numericSort(a, b, 'increaseRate')">
        <template #default="{ row }">
          <span :class="getRateClass(row.increaseRate)">
            {{ row.increaseRate }}%
          </span>
        </template>
      </el-table-column>
      <el-table-column prop="fundSize" label="基金规模" align="center" min-width="85" sortable :sort-method="(a, b) => numericSort(a, b, 'fundSize')" />
      <el-table-column prop="turnover" label="成交额" align="center" min-width="85" sortable :sort-method="(a, b) => numericSort(a, b, 'turnover')" />
      <el-table-column label="关注" align="center" width="55">
        <template #default="{ row }">
          <el-switch
            :model-value="favorites.has(row.fundCode)"
            @change="(val) => toggleFavorite(row.fundCode, val)"
          />
        </template>
      </el-table-column>
    </el-table>
  </div>
</template>

<script setup>
import { ref, onMounted, computed } from 'vue'
import { useRouter } from 'vue-router'
import axios from 'axios'
import { ElMessage } from 'element-plus'
import { Refresh, RefreshRight, Search } from '@element-plus/icons-vue'

// 后端接口地址
const API_URL = '/api/lof'

// ========== IndexedDB 收藏 ==========
const DB_NAME = 'lof-monitor'
const DB_VERSION = 1
const STORE_NAME = 'favorites'

function openDB() {
  return new Promise((resolve, reject) => {
    const request = indexedDB.open(DB_NAME, DB_VERSION)
    request.onerror = () => reject(request.error)
    request.onsuccess = () => resolve(request.result)
    request.onupgradeneeded = (event) => {
      const db = event.target.result
      if (!db.objectStoreNames.contains(STORE_NAME)) {
        db.createObjectStore(STORE_NAME, { keyPath: 'fundCode' })
      }
    }
  })
}

async function addFavoriteDB(fundCode) {
  const db = await openDB()
  return new Promise((resolve, reject) => {
    const tx = db.transaction(STORE_NAME, 'readwrite')
    const store = tx.objectStore(STORE_NAME)
    const request = store.put({ fundCode, time: Date.now() })
    request.onsuccess = () => resolve()
    request.onerror = () => reject(request.error)
  })
}

async function removeFavoriteDB(fundCode) {
  const db = await openDB()
  return new Promise((resolve, reject) => {
    const tx = db.transaction(STORE_NAME, 'readwrite')
    const store = tx.objectStore(STORE_NAME)
    const request = store.delete(fundCode)
    request.onsuccess = () => resolve()
    request.onerror = () => reject(request.error)
  })
}

async function getAllFavoritesDB() {
  const db = await openDB()
  return new Promise((resolve, reject) => {
    const tx = db.transaction(STORE_NAME, 'readonly')
    const store = tx.objectStore(STORE_NAME)
    const request = store.getAll()
    request.onsuccess = () => resolve(request.result.map(item => item.fundCode))
    request.onerror = () => reject(request.error)
  })
}
// ========== IndexedDB 结束 ==========

const fundList = ref([])
const loading = ref(false)
const searchCode = ref('')
const searchName = ref('')
const filterStatus = ref('')
const filterRedeemStatus = ref('')
const lastUpdateTime = ref('')
const favorites = ref(new Set())
const showOnlyFavorites = ref(false)
const filterByScale = ref(true)
const showFilters = ref(window.innerWidth > 768)
const router = useRouter()

function parseFundSize(sizeStr) {
  if (!sizeStr || sizeStr === '-') return 0
  if (sizeStr.endsWith('亿')) {
    return parseFloat(sizeStr) * 1e8
  }
  if (sizeStr.endsWith('万')) {
    return parseFloat(sizeStr) * 1e4
  }
  return parseFloat(sizeStr) || 0
}

function goHistory(row) {
  router.push({ path: '/history', query: { fundCode: row.fundCode, fundName: row.fundName } })
}

function formatTime(date) {
  const pad = n => String(n).padStart(2, '0')
  return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`
}

// 申购状态选项
const statusOptions = computed(() => {
  const set = new Set(fundList.value.map(i => i.purchaseStatus).filter(Boolean))
  return Array.from(set).sort()
})

// 赎回状态选项
const redeemStatusOptions = computed(() => {
  const set = new Set(fundList.value.map(i => i.redemptionStatus).filter(Boolean))
  return Array.from(set).sort()
})

// 筛选
const displayList = computed(() => {
  let list = [...fundList.value]
  if (showOnlyFavorites.value) {
    list = list.filter(i => favorites.value.has(i.fundCode))
  }
  if (searchCode.value) {
    list = list.filter(i => String(i.fundCode).includes(searchCode.value.trim()))
  }
  if (searchName.value) {
    list = list.filter(i => String(i.fundName).includes(searchName.value.trim()))
  }
  if (filterStatus.value) {
    list = list.filter(i => i.purchaseStatus === filterStatus.value)
  }
  if (filterRedeemStatus.value) {
    list = list.filter(i => i.redemptionStatus === filterRedeemStatus.value)
  }
  if (filterByScale.value) {
    list = list.filter(i => parseFundSize(i.fundSize) >= 30000000)
  }
  return list
})

function resetFilter() {
  searchCode.value = ''
  searchName.value = ''
  filterStatus.value = ''
  filterRedeemStatus.value = ''
  showOnlyFavorites.value = false
  filterByScale.value = true
}

// 获取数据
async function fetchData() {
  if (loading.value) return
  loading.value = true
  try {
    const res = await axios.get(API_URL)
    if (res.data.code === 200) {
      fundList.value = res.data.data
      lastUpdateTime.value = formatTime(new Date())

      if (res.data.hasMore) {
        try {
          const rem = await axios.get(`${API_URL}/remaining`)
          if (rem.data.code === 200 && rem.data.data.length > 0) {
            fundList.value = [...fundList.value, ...rem.data.data]
          }
        } catch (e) {
          // 小基金数据不影响已显示的大基金
        }
      }
    } else {
      ElMessage.error(res.data.msg || '数据获取失败')
    }
  } catch (err) {
    ElMessage.error('请求失败：请确认 Python 后端已启动')
  } finally {
    loading.value = false
  }
}

// 手动刷新
function manualRefresh() {
  fetchData()
}

// 数值排序方法（供 el-table 列排序使用）
function numericSort(a, b, prop) {
  const va = parseFloat(a[prop]) || 0
  const vb = parseFloat(b[prop]) || 0
  return va - vb
}

// 颜色样式
function getRateClass(rate) {
  const num = parseFloat(rate) || 0
  if (num > 0) return 'rate-up'
  if (num < 0) return 'rate-down'
  return 'rate-zero'
}

async function loadFavorites() {
  try {
    const codes = await getAllFavoritesDB()
    favorites.value = new Set(codes)
  } catch (e) {
    console.error('加载收藏失败', e)
  }
}

async function toggleFavorite(fundCode, isChecked) {
  try {
    if (isChecked) {
      await addFavoriteDB(fundCode)
      favorites.value.add(fundCode)
    } else {
      await removeFavoriteDB(fundCode)
      favorites.value.delete(fundCode)
    }
  } catch (e) {
    console.error('收藏操作失败', e)
    ElMessage.error('收藏操作失败')
  }
}

onMounted(() => {
  loadFavorites()
  fetchData()
})
</script>

<style scoped>
.lof-app {
  padding: 24px;
  box-sizing: border-box;
  width: 100%;
  max-width: 1600px;
  margin: 0 auto;
  overflow-x: auto;
}
.header {
  display: flex;
  justify-content: space-between;
  align-items: center;
  margin-bottom: 12px;
  gap: 12px;
}
.title {
  display: flex;
  flex-direction: column;
  gap: 4px;
  flex-shrink: 0;
}
.update-time {
  font-size: 13px;
  color: var(--text-muted);
  text-align: left;
  white-space: nowrap;
}
.tool-bar {
  display: flex;
  gap: 12px;
  flex-shrink: 0;
}
.filter-bar {
  display: flex;
  gap: 10px;
  margin-bottom: 12px;
  flex-wrap: wrap;
  align-items: center;
}
.filter-input {
  width: 200px;
}
.filter-input-sm {
  width: 160px;
}
.filter-select {
  width: 140px;
}
.filter-toggle-btn {
  display: none;
}
.rate-up {
  color: var(--rate-up);
  font-weight: bold;
}
.rate-down {
  color: var(--rate-down);
  font-weight: bold;
}
.rate-zero {
  color: var(--text-muted);
}
.fund-code-link {
  color: var(--accent);
  cursor: pointer;
  text-decoration: none;
}
.fund-code-link:hover {
  text-decoration: underline;
}

.lof-app .el-table .cell {
  padding: 2px 3px;
}
.lof-app .el-table th.el-table__cell .cell {
  padding: 3px 3px;
}

@media (max-width: 768px) {
  .lof-app {
    padding: 8px;
  }
  .header {
    flex-direction: column;
    align-items: flex-start;
  }
  .tool-bar {
    width: 100%;
    display: flex;
    gap: 8px;
  }
  .tool-bar .el-button {
    flex: 1;
  }
  .filter-toggle-btn {
    display: inline-flex;
  }
  .filter-bar {
    flex-direction: column;
    align-items: stretch;
  }
  .filter-input,
  .filter-input-sm,
  .filter-select {
    width: 100%;
  }
  .filter-checkbox {
    display: flex;
    justify-content: center;
  }
  .filter-radio {
    display: flex;
    width: 100%;
  }
  .filter-radio .el-radio-button {
    flex: 1;
  }
  .filter-radio .el-radio-button__inner {
    width: 100%;
    justify-content: center;
  }
  .filter-reset-btn {
    width: 100%;
  }
  .update-time {
    white-space: normal;
  }

  .lof-app .el-table {
    font-size: 12px;
  }
  .lof-app .fund-code-link {
    font-size: 12px;
  }
  .lof-app .el-tag {
    font-size: 11px;
    padding: 0 4px;
    height: 22px;
    line-height: 20px;
  }
  .lof-app .el-switch {
    --el-switch-height: 16px;
    --el-switch-button-size: 12px;
    --el-switch-font-size: 11px;
  }
}
</style>