<script setup>
import { ref, onMounted, onUnmounted, computed } from 'vue'
import { fetchUrlKeywordsList, fetchUrlKeywords, fetchUrlKeywordsStats } from '../api.js'

const loading = ref(true)
const error = ref(null)
const stats = ref({ size: 0, max_size: 10000, items: [] })
const expandedUrls = ref(new Set())
const urlKeywords = ref({})
const loadingKeywords = ref(new Set())
const search = ref('')

// 分页
const currentPage = ref(1)
const pageSize = ref(50)

let statsInterval = null

onMounted(async () => {
  await load()
  // 容量卡片每 5 秒自动刷新
  statsInterval = setInterval(loadStats, 5000)
})

onUnmounted(() => {
  if (statsInterval) clearInterval(statsInterval)
})

// 只刷新 stats（容量数据），不刷新列表
async function loadStats() {
  try {
    const s = await fetchUrlKeywordsStats()
    stats.value.size = s.size || 0
    stats.value.max_size = s.max_size || 10000
  } catch {
    // 静默失败，不影响用户体验
  }
}

async function load() {
  loading.value = true
  error.value = null
  currentPage.value = 1 // 重置到第一页
  try {
    const data = await fetchUrlKeywordsList()
    stats.value.size = data.size || 0
    stats.value.max_size = data.max_size || 10000
    // items 数组：{ url, title, snippet, keywords }，反转显示（最新在前）
    stats.value.items = (data.items || []).reverse()
  } catch (e) {
    try {
      const s = await fetchUrlKeywordsStats()
      stats.value.size = s.size || 0
      stats.value.max_size = s.max_size || 10000
      stats.value.items = []
    } catch {
      error.value = '无法加载缓存数据'
    }
    console.error(e)
  } finally {
    loading.value = false
  }
}

const usage = computed(() => {
  if (!stats.value.max_size) return 0
  return stats.value.size / stats.value.max_size
})

const filteredItems = computed(() => {
  if (!search.value) return stats.value.items
  const q = search.value.toLowerCase()
  return stats.value.items.filter(item =>
    item.url.toLowerCase().includes(q) ||
    (item.title && item.title.toLowerCase().includes(q)) ||
    (item.snippet && item.snippet.toLowerCase().includes(q))
  )
})

const totalPages = computed(() => {
  return Math.max(1, Math.ceil(filteredItems.value.length / pageSize.value))
})

const paginatedItems = computed(() => {
  const start = (currentPage.value - 1) * pageSize.value
  const end = start + pageSize.value
  return filteredItems.value.slice(start, end)
})

function prevPage() {
  if (currentPage.value > 1) currentPage.value--
}

function nextPage() {
  if (currentPage.value < totalPages.value) currentPage.value++
}

function goToPage(p) {
  if (p >= 1 && p <= totalPages.value) currentPage.value = p
}

// 搜索时回到第一页
function onSearch() {
  currentPage.value = 1
}

async function toggleKeywords(url) {
  if (expandedUrls.value.has(url)) {
    expandedUrls.value.delete(url)
    return
  }

  expandedUrls.value.add(url)

  if (urlKeywords.value[url]) {
    return
  }

  loadingKeywords.value.add(url)
  try {
    const data = await fetchUrlKeywords(url)
    urlKeywords.value[url] = data.keywords || []
  } catch (e) {
    console.error('Failed to load keywords:', e)
    urlKeywords.value[url] = []
  } finally {
    loadingKeywords.value.delete(url)
  }
}

function truncateUrl(url, maxLen = 80) {
  if (url.length <= maxLen) return url
  return url.slice(0, maxLen) + '...'
}

function truncateSnippet(text, maxLen = 200) {
  if (!text) return ''
  if (text.length <= maxLen) return text
  return text.slice(0, maxLen) + '...'
}
</script>

<template>
  <div class="p-4 md:p-8">
    <!-- Header -->
    <div class="flex flex-col md:flex-row md:items-center justify-between mb-4 md:mb-6 gap-3">
      <div>
        <h1 class="text-xl md:text-2xl font-semibold text-white mb-1">关键词缓存</h1>
        <p class="text-sm text-gray-500">LRU 缓存，共 {{ stats.size.toLocaleString() }} 条记录</p>
      </div>
      <div class="flex items-center gap-3">
        <!-- 缓存状态卡片（自动刷新） -->
        <div class="bg-gray-900 border border-gray-700 rounded-lg px-3 py-2 flex items-center gap-3">
          <div class="flex flex-col">
            <span class="text-[10px] text-gray-500 uppercase">容量</span>
            <span class="text-sm font-medium text-gray-300">
              {{ stats.size.toLocaleString() }} / {{ stats.max_size.toLocaleString() }}
            </span>
          </div>
          <div class="w-12 h-12 relative">
            <svg viewBox="0 0 36 36" class="w-full h-full transform -rotate-90">
              <path
                class="text-gray-800"
                d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
                fill="none"
                stroke="currentColor"
                stroke-width="4"
              />
              <path
                :class="usage > 0.9 ? 'text-red-500' : usage > 0.7 ? 'text-yellow-500' : 'text-green-500'"
                d="M18 2.0845 a 15.9155 15.9155 0 0 1 0 31.831 a 15.9155 15.9155 0 0 1 0 -31.831"
                fill="none"
                stroke="currentColor"
                stroke-width="4"
                :stroke-dasharray="`${(usage * 100).toFixed(0)}, 100`"
              />
            </svg>
            <span class="absolute inset-0 flex items-center justify-center text-[8px] font-medium text-gray-400">
              {{ (usage * 100).toFixed(0) }}%
            </span>
          </div>
        </div>
        <button
          @click="load"
          class="bg-blue-600 hover:bg-blue-700 text-white text-sm px-4 py-2 rounded-lg transition-colors"
        >
          刷新
        </button>
      </div>
    </div>

    <!-- Search -->
    <div class="mb-4 md:mb-5">
      <div class="relative max-w-sm">
        <input
          v-model="search"
          @input="onSearch"
          type="text"
          placeholder="搜索 URL、标题或摘要..."
          class="w-full bg-gray-900 border border-gray-700 text-gray-200 text-sm rounded-lg pl-10 pr-4 py-2 focus:border-blue-500 focus:outline-none placeholder-gray-600"
        />
        <span class="absolute left-3 top-1/2 -translate-y-1/2 text-gray-500">🔍</span>
      </div>
    </div>

    <!-- Loading -->
    <div v-if="loading" class="flex items-center justify-center h-48">
      <div class="text-gray-400 animate-pulse">加载中...</div>
    </div>

    <!-- Error -->
    <div v-else-if="error" class="bg-red-900/30 border border-red-800 rounded-lg p-4 text-red-300">
      {{ error }}
    </div>

    <!-- Empty -->
    <div v-else-if="!stats.items.length && !search" class="bg-gray-900 border border-gray-800 rounded-xl p-12 text-center">
      <div class="text-4xl mb-3">📭</div>
      <div class="text-gray-400">缓存为空</div>
      <div class="text-xs text-gray-600 mt-1">爬取页面时会自动填充此缓存</div>
    </div>

    <!-- URL List with Pagination -->
    <div v-else class="bg-gray-900 border border-gray-800 rounded-xl overflow-hidden">
      <div class="divide-y divide-gray-800">
        <div
          v-for="item in paginatedItems"
          :key="item.url"
          class="p-4 hover:bg-gray-800/40 transition-colors"
        >
          <!-- URL 标题行 -->
          <div class="flex items-start justify-between gap-3 mb-1">
            <a
              :href="item.url"
              target="_blank"
              rel="noopener noreferrer"
              class="text-sm text-blue-400 hover:text-blue-300 break-all line-clamp-2 flex-1"
              :title="item.url"
            >
              {{ truncateUrl(item.url) }}
            </a>
            <button
              @click="toggleKeywords(item.url)"
              class="shrink-0 text-xs text-gray-500 hover:text-blue-400 flex items-center gap-1"
            >
              <span>{{ expandedUrls.has(item.url) ? '▲' : '▼' }}</span>
              <span v-if="loadingKeywords.has(item.url)">加载中</span>
              <span v-else-if="urlKeywords[item.url] || item.keywords?.length">已缓存</span>
            </button>
          </div>

          <!-- 标题 -->
          <div v-if="item.title" class="text-sm text-gray-300 font-medium mb-1">
            {{ item.title }}
          </div>

          <!-- 摘要 -->
          <div v-if="item.snippet" class="text-xs text-gray-500 leading-relaxed mb-2">
            {{ truncateSnippet(item.snippet) }}
          </div>

          <!-- 关键词 -->
          <div v-if="expandedUrls.has(item.url)" class="mt-2">
            <template v-if="urlKeywords[item.url]?.length || item.keywords?.length">
              <div class="flex flex-wrap gap-1.5">
                <span
                  v-for="kw in (urlKeywords[item.url] || item.keywords || [])"
                  :key="kw.word"
                  class="text-xs px-2 py-0.5 rounded bg-gray-800 text-gray-300 border border-gray-700"
                  :title="`权重: ${kw.weight.toFixed(4)}`"
                >
                  {{ kw.word }}
                  <span class="text-gray-500 text-[10px] ml-0.5">{{ kw.weight.toFixed(2) }}</span>
                </span>
              </div>
              <div class="text-xs text-gray-600 mt-2">
                共 {{ (urlKeywords[item.url] || item.keywords || []).length }} 个关键词
              </div>
            </template>
            <span v-else-if="!loadingKeywords.has(item.url)" class="text-xs text-gray-600">
              暂无关键词
            </span>
            <span v-else class="text-xs text-gray-500">
              加载中...
            </span>
          </div>
        </div>

        <div v-if="!paginatedItems.length" class="p-8 text-center text-gray-600">
          没有找到匹配的记录
        </div>
      </div>

      <!-- Pagination -->
      <div class="px-4 py-3 border-t border-gray-800 flex items-center justify-between">
        <div class="text-xs text-gray-500">
          第 {{ (currentPage - 1) * pageSize + 1 }}-{{ Math.min(currentPage * pageSize, filteredItems.length) }} 条 /
          共 {{ filteredItems.length }} 条
        </div>
        <div class="flex items-center gap-1">
          <button
            @click="prevPage"
            :disabled="currentPage === 1"
            class="px-2 py-1 text-xs rounded bg-gray-800 text-gray-400 hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            ‹
          </button>
          <button
            v-for="p in totalPages <= 5 ? totalPages : (() => {
              const pages = []
              const start = Math.max(1, currentPage - 2)
              const end = Math.min(totalPages, start + 4)
              for (let i = start; i <= end; i++) pages.push(i)
              return pages
            })()"
            :key="p"
            @click="goToPage(p)"
            :class="[
              'px-2 py-1 text-xs rounded',
              p === currentPage
                ? 'bg-blue-600 text-white'
                : 'bg-gray-800 text-gray-400 hover:bg-gray-700'
            ]"
          >
            {{ p }}
          </button>
          <button
            v-if="totalPages > 5 && currentPage < totalPages - 2"
            class="px-1 py-1 text-xs text-gray-600"
          >
            ...
          </button>
          <button
            v-if="totalPages > 5 && currentPage < totalPages - 2"
            @click="goToPage(totalPages)"
            class="px-2 py-1 text-xs rounded bg-gray-800 text-gray-400 hover:bg-gray-700"
          >
            {{ totalPages }}
          </button>
          <button
            @click="nextPage"
            :disabled="currentPage === totalPages"
            class="px-2 py-1 text-xs rounded bg-gray-800 text-gray-400 hover:bg-gray-700 disabled:opacity-50 disabled:cursor-not-allowed"
          >
            ›
          </button>
        </div>
      </div>
    </div>
  </div>
</template>
