<script setup>
import { ref, onMounted, onUnmounted } from 'vue'
import { fetchStats, flushIndex, fetchFlushStatus, fetchWorkers, setWorkers, fetchBacklink, triggerBacklink, fetchPriorityStatus, fetchCrawlStatus, addPriority } from '../api.js'

const stats = ref(null)
const loading = ref(true)
const flushing = ref(false)
const error = ref(null)
let refreshInterval = null

// Workers 相关状态
const configuredWorkers = ref(0) // 设定线程数
const activeWorkers = ref(0)    // 实际运行中的 goroutine 数
const workersInput = ref(0)
const workersSaving = ref(false)

// Priority 相关状态
const priorityStatus = ref(null) // { level1, level2_queue, level2_inflight, active, max_workers }
const batchUrls = ref('')
const batchAdding = ref(false)

// 爬取状态
const crawlStatus = ref(null) // { current_epoch, max_epoch, queue_length, completed_count, visited_total, is_running }

onMounted(async () => {
  await Promise.all([loadStats(), loadWorkers(), loadBacklink(), loadPriorityStatus(), loadCrawlStatus()])
  refreshInterval = setInterval(() => {
    loadStats()
    loadWorkers()
    loadBacklink()
    loadPriorityStatus()
    loadCrawlStatus()
  }, 5000)
})

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

async function loadStats() {
  try {
    stats.value = await fetchStats()
    error.value = null
  } catch (e) {
    error.value = '无法加载统计数据，可能人服务器未启动或端口不对'
    console.error(e)
  } finally {
    loading.value = false
  }
}

async function loadWorkers() {
  try {
    const res = await fetchWorkers()
    configuredWorkers.value = res.configured
    activeWorkers.value = res.active
    workersInput.value = res.configured
  } catch (e) {
    console.error('Failed to load workers:', e)
  }
}

async function saveWorkers() {
  const n = parseInt(workersInput.value, 10)
  if (isNaN(n) || n < 1 || n > 500) {
    error.value = '线程数必须在 1~500 之间'
    return
  }
  workersSaving.value = true
  try {
    await setWorkers(n)
    configuredWorkers.value = n
    error.value = null
  } catch (e) {
    error.value = '修改线程数失败: ' + e.message
  } finally {
    workersSaving.value = false
  }
}

async function loadBacklink() {
  try {
    backlinkStatus.value = await fetchBacklink()
  } catch (e) {
    console.error('Failed to load backlink status:', e)
  }
}

async function loadPriorityStatus() {
  try {
    priorityStatus.value = await fetchPriorityStatus()
  } catch (e) {
    console.error('Failed to load priority status:', e)
  }
}

async function loadCrawlStatus() {
  try {
    crawlStatus.value = await fetchCrawlStatus()
  } catch (e) {
    console.error('Failed to load crawl status:', e)
  }
}

async function doTriggerBacklink() {
  backlinkTriggering.value = true
  try {
    await triggerBacklink()
    // 立即刷新状态，显示 running=true
    backlinkStatus.value = await fetchBacklink()
    error.value = null
  } catch (e) {
    error.value = '触发反链计算失败: ' + e.message
  } finally {
    backlinkTriggering.value = false
  }
}

function formatBacklinkTime(isoStr) {
  if (!isoStr) return '--'
  const d = new Date(isoStr)
  const now = new Date()
  const diffMs = d - now
  const diffMin = Math.floor(diffMs / 60000)
  const diffH = Math.floor(diffMin / 60)
  const diffD = Math.floor(diffH / 24)
  const time = d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit' })
  const date = d.toLocaleDateString('zh-CN', { month: 'short', day: 'numeric' })

  if (diffD > 0) return `${date} ${time} (${diffD}天后)`
  if (diffH > 0) return `${date} ${time} (${diffH}小时后)`
  if (diffMin > 0) return `${time} (${diffMin}分钟后)`
  return `${time} (即将执行)`
}

function formatBacklinkLastRun(isoStr) {
  if (!isoStr) return '从未执行'
  const d = new Date(isoStr)
  return d.toLocaleString('zh-CN', { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })
}

async function doFlush() {
  flushing.value = true
  try {
    await flushIndex()
    // 轮询刷盘状态，直到完成
    while (true) {
      await new Promise(r => setTimeout(r, 1000)) // 等待 1s
      const status = await fetchFlushStatus()
      if (!status.flushing) break
    }
    // 刷盘完成，重新拉取 stats
    stats.value = await fetchStats()
  } catch (e) {
    error.value = '刷盘失败: ' + e.message
  } finally {
    flushing.value = false
  }
}

function fmt(n) {
  if (!n && n !== 0) return '0'
  return Number(n).toLocaleString()
}

function topDomains(domains) {
  if (!domains) return []
  return Object.entries(domains).sort((a, b) => b[1] - a[1]).slice(0, 10)
}

function langColor(lang) {
  const map = { zh: '#e53e3e', en: '#3182ce', ja: '#e53e3e', ko: '#3182ce', fr: '#38a169', de: '#d69e2e', es: '#38a169', ru: '#805ad5', other: '#718096' }
  return map[lang] || map.other
}

function isValidUrl(s) {
  try {
    const u = new URL(s)
    return u.protocol === 'http:' || u.protocol === 'https:'
  } catch {
    return false
  }
}

async function doBatchAdd() {
  const lines = batchUrls.value.split('\n').map(l => l.trim()).filter(l => l)
  const valid = lines.filter(isValidUrl)
  if (valid.length === 0) {
    error.value = '未检测到有效 URL'
    return
  }
  batchAdding.value = true
  let ok = 0, fail = 0
  try {
    for (const url of valid) {
      try {
        await addPriority(url)
        ok++
      } catch {
        fail++
      }
    }
    batchUrls.value = ''
    await loadPriorityStatus()
    error.value = null
    if (fail > 0) {
      error.value = `添加完成：${ok} 成功，${fail} 失败`
    }
  } finally {
    batchAdding.value = false
  }
}
</script>

<template>
  <div class="p-4 md:p-8">
    <h1 class="text-xl md:text-2xl font-semibold text-white mb-6 md:mb-8">概览</h1>

    <!-- Loading / Error -->
    <div v-if="loading" class="flex items-center justify-center h-48">
      <div class="text-gray-400 animate-pulse">加载中...</div>
    </div>
    <div v-else-if="error" class="bg-red-900/30 border border-red-800 rounded-lg p-4 text-red-300">
      {{ error }}
    </div>

    <template v-else-if="stats">
      <!-- Stat Cards -->
      <div class="grid grid-cols-2 md:grid-cols-5 gap-3 md:gap-5 mb-6 md:mb-8">
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
          <div class="text-sm text-gray-500 mb-2">已爬取 URL</div>
          <div class="text-3xl font-bold text-white">{{ fmt(stats.total_urls) }}</div>
        </div>
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
          <div class="text-sm text-gray-500 mb-2">总词数</div>
          <div class="text-3xl font-bold text-white">{{ fmt(stats.total_words) }}</div>
        </div>
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
          <div class="text-sm text-gray-500 mb-2">域名数量</div>
          <div class="text-3xl font-bold text-white">{{ fmt(stats.total_domains) }}</div>
        </div>
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-5">
          <div class="text-sm text-gray-500 mb-2">待重爬</div>
          <div class="text-3xl font-bold" :class="stats.recrawl_eligible > 0 ? 'text-orange-400' : 'text-green-400'">
            {{ fmt(stats.recrawl_eligible) }}
          </div>
        </div>
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-5 flex flex-col justify-between">
          <div>
            <div class="text-sm text-gray-500 mb-2">待刷盘</div>
            <div class="text-3xl font-bold" :class="stats.pending > 0 ? 'text-yellow-400' : 'text-green-400'">
              {{ fmt(stats.pending) }}
            </div>
          </div>
          <button
            class="mt-3 w-full bg-blue-700 hover:bg-blue-600 disabled:bg-gray-700 disabled:text-gray-500 text-white text-sm font-medium py-1.5 px-3 rounded transition-colors cursor-pointer"
            :disabled="flushing || !stats.pending"
            @click="doFlush"
          >
            {{ flushing ? '刷盘中...' : '立即刷盘' }}
          </button>
        </div>
      </div>

      <!-- 优先爬取队列 -->
      <div v-if="priorityStatus" class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5 mb-6 md:mb-8">
        <h2 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-4">优先爬取队列</h2>
        <div class="grid grid-cols-2 md:grid-cols-4 gap-4">
          <!-- 一级队列 -->
          <div class="bg-gray-800/50 rounded-lg p-4 text-center">
            <div class="text-xs text-gray-500 mb-1">一级队列</div>
            <div class="text-2xl font-bold" :class="(priorityStatus.level1 || 0) > 0 ? 'text-yellow-400' : 'text-gray-500'">
              {{ fmt(priorityStatus.level1 || 0) }}
            </div>
          </div>
          <!-- 二级队列 -->
          <div class="bg-gray-800/50 rounded-lg p-4 text-center">
            <div class="text-xs text-gray-500 mb-1">二级队列</div>
            <div class="text-2xl font-bold" :class="((priorityStatus.level2_queue || 0) + (priorityStatus.level2_inflight || 0)) > 0 ? 'text-yellow-400' : 'text-gray-500'">
              {{ fmt((priorityStatus.level2_queue || 0) + (priorityStatus.level2_inflight || 0)) }}
            </div>
          </div>
          <!-- 线程使用 -->
          <div class="bg-gray-800/50 rounded-lg p-4 text-center">
            <div class="text-xs text-gray-500 mb-1">线程使用</div>
            <div class="text-2xl font-bold" :class="priorityStatus.active > 0 ? 'text-orange-400' : 'text-gray-500'">
              {{ fmt(priorityStatus.active) }}
            </div>
          </div>
          <!-- 线程总数 -->
          <div class="bg-gray-800/50 rounded-lg p-4 text-center">
            <div class="text-xs text-gray-500 mb-1">线程总数</div>
            <div class="text-2xl font-bold text-blue-400">{{ priorityStatus.max_workers }}</div>
          </div>
        </div>
        <!-- 批量添加 -->
        <div class="mt-4 flex gap-2">
          <textarea
            v-model="batchUrls"
            rows="3"
            placeholder="批量添加 URL（每行一个，仅发送有效链接）"
            class="flex-1 bg-gray-800 border border-gray-700 text-gray-200 text-sm rounded-lg px-3 py-2 resize-none focus:outline-none focus:border-blue-500 placeholder-gray-600"
          ></textarea>
          <button
            class="bg-blue-700 hover:bg-blue-600 disabled:bg-gray-700 text-white text-sm font-medium px-4 py-2 rounded-lg transition-colors cursor-pointer whitespace-nowrap self-end"
            :disabled="batchAdding || !batchUrls.trim()"
            @click="doBatchAdd"
          >
            {{ batchAdding ? '添加中...' : '批量添加' }}
          </button>
        </div>
      </div>

      <!-- 爬取进度 -->
      <div v-if="crawlStatus && crawlStatus.max_epoch > 0" class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5 mb-6 md:mb-8">
        <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4 mb-4">
          <h2 class="text-sm font-semibold text-gray-300 uppercase tracking-wider">爬取进度</h2>
          <div class="flex items-center gap-2">
            <span class="text-xs text-gray-500">状态:</span>
            <span class="px-2 py-0.5 rounded text-xs font-medium" :class="crawlStatus.is_running ? 'bg-green-900/50 text-green-400' : 'bg-gray-800 text-gray-500'">
              {{ crawlStatus.is_running ? '运行中' : '已停止' }}
            </span>
          </div>
        </div>
        <div class="grid grid-cols-2 md:grid-cols-5 gap-4">
          <!-- 当前轮次 -->
          <div class="text-center">
            <div class="text-xs text-gray-500 mb-1">当前轮次</div>
            <div class="text-3xl font-bold text-white">
              {{ crawlStatus.current_epoch }}<span class="text-lg text-gray-500">/{{ crawlStatus.max_epoch }}</span>
            </div>
          </div>
          <!-- 本轮队列 -->
          <div class="text-center">
            <div class="text-xs text-gray-500 mb-1">本轮队列</div>
            <div class="text-3xl font-bold" :class="crawlStatus.queue_length > 0 ? 'text-blue-400' : 'text-gray-500'">
              {{ fmt(crawlStatus.queue_length) }}
            </div>
          </div>
          <!-- 已完成 -->
          <div class="text-center">
            <div class="text-xs text-gray-500 mb-1">已完成</div>
            <div class="text-3xl font-bold text-green-400">
              {{ fmt(crawlStatus.completed_count) }}
            </div>
            <div class="text-xs text-gray-600 mt-1">
              {{ crawlStatus.queue_length > 0 ? Math.round(crawlStatus.completed_count / crawlStatus.queue_length * 100) + '%' : '--' }}
            </div>
          </div>
          <!-- 下一轮链接池 -->
          <div class="text-center">
            <div class="text-xs text-gray-500 mb-1">下一轮链接池</div>
            <div class="text-3xl font-bold" :class="crawlStatus.next_pool_size > 0 ? 'text-purple-400' : 'text-gray-500'">
              {{ fmt(crawlStatus.next_pool_size) }}
            </div>
          </div>
          <!-- 已收录总计 -->
          <div class="text-center">
            <div class="text-xs text-gray-500 mb-1">已收录总计</div>
            <div class="text-3xl font-bold text-white">{{ fmt(crawlStatus.visited_total) }}</div>
          </div>
        </div>
        <!-- 进度条 -->
        <div v-if="crawlStatus.queue_length > 0" class="mt-4">
          <div class="bg-gray-800 rounded-full h-2 overflow-hidden">
            <div
              class="h-full bg-gradient-to-r from-blue-600 to-green-500 rounded-full transition-all duration-500"
              :style="{ width: `${(crawlStatus.completed_count / crawlStatus.queue_length) * 100}%` }"
            ></div>
          </div>
        </div>
      </div>

      <!-- Workers Control -->
      <div class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5 mb-6 md:mb-8">
        <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
          <!-- 左侧：主线程 -->
          <div>
            <h2 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-2">爬虫线程</h2>
            <div class="flex items-baseline gap-4">
              <div>
                <div class="text-xs text-gray-500 mb-0.5">实际运行</div>
                <div class="text-3xl font-bold" :class="activeWorkers > 0 ? 'text-green-400' : 'text-gray-500'">
                  {{ activeWorkers }}
                </div>
              </div>
              <div class="text-gray-700 text-xl">/</div>
              <div>
                <div class="text-xs text-gray-500 mb-0.5">设定上限</div>
                <div class="text-3xl font-bold text-white">{{ configuredWorkers }}</div>
              </div>
            </div>
          </div>

          <!-- 调节按钮 -->
          <div class="flex items-center gap-2">
            <button
              class="w-9 h-9 flex items-center justify-center rounded-lg bg-gray-800 hover:bg-gray-700 text-gray-300 hover:text-white text-lg font-bold transition-colors cursor-pointer"
              @click="workersInput = Math.max(1, workersInput - 1)"
              :disabled="workersSaving"
            >−</button>
            <input
              type="number"
              v-model.number="workersInput"
              min="1"
              max="500"
              class="w-20 h-9 text-center bg-gray-800 border border-gray-700 rounded-lg text-white text-sm focus:outline-none focus:border-blue-500 transition-colors [appearance:textfield] [&::-webkit-outer-spin-button]:appearance-none [&::-webkit-inner-spin-button]:appearance-none"
              @keyup.enter="saveWorkers"
            />
            <button
              class="w-9 h-9 flex items-center justify-center rounded-lg bg-gray-800 hover:bg-gray-700 text-gray-300 hover:text-white text-lg font-bold transition-colors cursor-pointer"
              @click="workersInput = Math.min(500, workersInput + 1)"
              :disabled="workersSaving"
            >+</button>
            <button
              class="h-9 px-4 bg-blue-700 hover:bg-blue-600 disabled:bg-gray-700 disabled:text-gray-500 text-white text-sm font-medium rounded-lg transition-colors cursor-pointer"
              :disabled="workersSaving || workersInput === configuredWorkers"
              @click="saveWorkers"
            >
              {{ workersSaving ? '保存中...' : '应用' }}
            </button>
          </div>
        </div>
      </div>

      <!-- Backlink Control -->
      <div v-if="backlinkStatus" class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5 mb-6 md:mb-8">
        <div class="flex flex-col md:flex-row md:items-center md:justify-between gap-4">
          <div class="flex-1">
            <h2 class="text-sm font-semibold text-gray-300 uppercase tracking-wider mb-3">反链计算（PageRank）</h2>
            <div class="grid grid-cols-1 sm:grid-cols-2 gap-3">
              <div>
                <div class="text-xs text-gray-500 mb-0.5">下次自动执行</div>
                <div class="text-lg font-bold" :class="backlinkStatus.running ? 'text-yellow-400' : 'text-white'">
                  {{ backlinkStatus.running ? '计算中...' : formatBacklinkTime(backlinkStatus.next_run) }}
                </div>
              </div>
              <div>
                <div class="text-xs text-gray-500 mb-0.5">上次完成</div>
                <div class="text-lg font-bold text-white">{{ formatBacklinkLastRun(backlinkStatus.last_run) }}</div>
              </div>
            </div>
            <div v-if="backlinkStatus.last_error" class="mt-2 text-xs text-red-400 truncate" :title="backlinkStatus.last_error">
              上次错误：{{ backlinkStatus.last_error }}
            </div>
          </div>
          <button
            class="h-9 px-4 bg-blue-700 hover:bg-blue-600 disabled:bg-gray-700 disabled:text-gray-500 text-white text-sm font-medium rounded-lg transition-colors cursor-pointer whitespace-nowrap"
            :disabled="backlinkTriggering || backlinkStatus.running"
            @click="doTriggerBacklink"
          >
            {{ backlinkTriggering ? '已触发...' : backlinkStatus.running ? '计算中...' : '立即执行' }}
          </button>
        </div>
      </div>

      <div class="grid grid-cols-1 md:grid-cols-2 gap-4 md:gap-5">
        <!-- Domain Distribution -->
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5">
          <h2 class="text-sm font-semibold text-gray-300 mb-3 md:mb-4 uppercase tracking-wider">域名分布 Top 10</h2>
          <div class="space-y-2">
            <div
              v-for="[domain, count] in topDomains(stats.domains)"
              :key="domain"
              class="flex items-center gap-2 md:gap-3"
            >
              <div class="w-24 md:w-36 text-xs text-gray-400 truncate shrink-0" :title="domain">{{ domain }}</div>
              <div class="flex-1 bg-gray-800 rounded-full h-4 md:h-5 overflow-hidden">
                <div
                  class="h-full bg-blue-600 rounded-full transition-all duration-500"
                  :style="{ width: `${(count / stats.domains[Object.keys(stats.domains)[0]]) * 100}%` }"
                ></div>
              </div>
              <div class="w-12 md:w-16 text-xs text-gray-500 text-right shrink-0">{{ fmt(count) }}</div>
            </div>
          </div>
        </div>

        <!-- Language Distribution -->
        <div class="bg-gray-900 border border-gray-800 rounded-xl p-4 md:p-5">
          <h2 class="text-sm font-semibold text-gray-300 mb-3 md:mb-4 uppercase tracking-wider">语种分布</h2>
          <div class="space-y-2">
            <div
              v-for="[lang, count] in Object.entries(stats.languages || {}).sort((a,b) => b[1]-a[1])"
              :key="lang"
              class="flex items-center gap-2 md:gap-3"
            >
              <div class="w-8 md:w-10 text-xs text-gray-400 shrink-0 font-mono">{{ lang }}</div>
              <div class="flex-1 bg-gray-800 rounded-full h-4 md:h-5 overflow-hidden">
                <div
                  class="h-full rounded-full transition-all duration-500"
                  :style="{
                    width: `${(count / stats.total_urls) * 100}%`,
                    backgroundColor: langColor(lang)
                  }"
                ></div>
              </div>
              <div class="w-12 md:w-16 text-xs text-gray-500 text-right shrink-0">{{ fmt(count) }}</div>
            </div>
          </div>
        </div>
      </div>
    </template>
  </div>
</template>
