<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>🛡️ TG Spam Guard - 收割机</title>
<link rel="stylesheet" href="https://unpkg.com/element-ui@2.15.14/lib/theme-chalk/index.css">
<style>
  body { margin: 0; background: #f5f7fa; }
  #app { padding: 20px; }
  .header-card {
    background: linear-gradient(135deg, #409eff, #6366f1);
    border-radius: 12px;
    padding: 24px 32px;
    margin-bottom: 20px;
    color: white;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .header-card h1 { margin: 0; font-size: 22px; }
  .header-card .status { display: flex; align-items: center; gap: 8px; font-size: 14px; opacity: 0.9; }
  .stats-row { margin-bottom: 20px; }
  .stat-card { text-align: center; padding: 20px; }
  .stat-card .num { font-size: 32px; font-weight: bold; color: #409eff; }
  .stat-card .label { font-size: 13px; color: #909399; margin-top: 6px; }
  .stat-card.danger .num { color: #f56c6c; }
  .stat-card.success .num { color: #67c23a; }
  .stat-card.warning .num { color: #e6a23c; }
  .chat-panel, .ban-panel { height: 520px; }
  .chat-item {
    padding: 10px 0;
    border-bottom: 1px solid #ebeef5;
    transition: background 0.2s;
  }
  .chat-item:hover { background: #f5f7fa; }
  .chat-item .meta { display: flex; justify-content: space-between; margin-bottom: 4px; }
  .chat-item .user { font-weight: 600; color: #409eff; font-size: 14px; }
  .chat-item .time { font-size: 12px; color: #c0c4cc; }
  .chat-item .text { font-size: 14px; color: #606266; line-height: 1.6; }
  .ban-item {
    padding: 12px 0;
    border-bottom: 1px solid #ebeef5;
    display: flex;
    justify-content: space-between;
    align-items: center;
  }
  .ban-info { flex: 1; }
  .ban-info .user { font-weight: 600; color: #f56c6c; font-size: 14px; }
  .ban-info .reason { font-size: 13px; color: #909399; margin-top: 3px; }
  .ban-info .time { font-size: 12px; color: #c0c4cc; margin-top: 2px; }
  .panel-header {
    display: flex;
    justify-content: space-between;
    align-items: center;
    margin-bottom: 12px;
  }
  .panel-header h3 { margin: 0; font-size: 16px; color: #303133; }
  .empty-text { text-align: center; padding: 60px 0; color: #c0c4cc; }
  .empty-text .icon { font-size: 48px; margin-bottom: 10px; display: block; }
  .sse-dot {
    display: inline-block;
    width: 8px; height: 8px;
    border-radius: 50%;
    margin-right: 6px;
  }
  .sse-dot.on { background: #67c23a; }
  .sse-dot.off { background: #f56c6c; }
</style>
</head>
<body>
<div id="app">
  <!-- 头部 -->
  <div class="header-card">
    <h1>🛡️ TG Spam Guard</h1>
    <div class="status">
      <span class="sse-dot" :class="sseConnected ? 'on' : 'off'"></span>
      {{ sseConnected ? '已连接' : '连接中...' }}
    </div>
  </div>

  <!-- 统计 -->
  <el-row class="stats-row" :gutter="20">
    <el-col :span="6">
      <el-card shadow="hover" class="stat-card">
        <div class="num">{{ stats.today_bans }}</div>
        <div class="label">今日封禁</div>
      </el-card>
    </el-col>
    <el-col :span="6">
      <el-card shadow="hover" class="stat-card danger">
        <div class="num">{{ stats.total_bans }}</div>
        <div class="label">累计封禁</div>
      </el-card>
    </el-col>
    <el-col :span="6">
      <el-card shadow="hover" class="stat-card warning">
        <div class="num">{{ stats.active_bans }}</div>
        <div class="label">当前封禁中</div>
      </el-card>
    </el-col>
    <el-col :span="6">
      <el-card shadow="hover" class="stat-card success">
        <div class="num">{{ chatLogs.length }}</div>
        <div class="label">聊天记录</div>
      </el-card>
    </el-col>
  </el-row>

  <!-- 主内容 -->
  <el-row :gutter="20">
    <!-- 聊天记录 -->
    <el-col :span="12">
      <el-card shadow="hover" class="chat-panel">
        <div class="panel-header">
          <h3>💬 实时聊天</h3>
          <el-tag size="small" type="info">{{ chatLogs.length }} 条</el-tag>
        </div>
        <div style="overflow-y:auto; height:440px;" ref="chatScroll">
          <div v-if="chatLogs.length === 0" class="empty-text">
            <span class="icon">💬</span>等待消息...
          </div>
          <div v-for="(item, i) in chatLogs" :key="i" class="chat-item">
            <div class="meta">
              <span class="user">@{{ item.username }} ({{ item.user_id }})</span>
              <span class="time">{{ formatTime(item.time) }}</span>
            </div>
            <div class="text">{{ item.text }}</div>
          </div>
        </div>
      </el-card>
    </el-col>

    <!-- 封禁列表 -->
    <el-col :span="12">
      <el-card shadow="hover" class="ban-panel">
        <div class="panel-header">
          <h3>🚫 封禁列表</h3>
          <el-button size="mini" icon="el-icon-refresh" @click="loadBans">刷新</el-button>
        </div>
        <div style="overflow-y:auto; height:440px;">
          <div v-if="bans.length === 0" class="empty-text">
            <span class="icon">✅</span>暂无封禁记录
          </div>
          <div v-for="(item, i) in bans" :key="i" class="ban-item">
            <div class="ban-info">
              <div class="user">@{{ item.username }} ({{ item.user_id }})</div>
              <div class="reason">📝 {{ item.reason }}</div>
              <div class="time">⏰ {{ formatTime(item.time) }}</div>
            </div>
            <el-button
              v-if="item.auto_unban !== false"
              size="small"
              type="danger"
              :loading="item._loading"
              @click="unbanUser(item)"
            >解封</el-button>
            <el-tag v-else size="small" type="success">已解封</el-tag>
          </div>
        </div>
      </el-card>
    </el-col>
  </el-row>
</div>

<script src="https://unpkg.com/vue@2.7.16/dist/vue.min.js"></script>
<script src="https://unpkg.com/element-ui@2.15.14/lib/index.js"></script>
<script>
new Vue({
  el: '#app',
  data() {
    return {
      sseConnected: false,
      chatLogs: [],
      bans: [],
      stats: { today_bans: 0, total_bans: 0, active_bans: 0 },
    }
  },
  mounted() {
    this.loadChatHistory()
    this.loadBans()
    this.loadStats()
    this.connectSSE()
    setInterval(() => this.loadStats(), 30000)
  },
  methods: {
    // SSE
    connectSSE() {
      if (this._es) this._es.close()
      const es = new EventSource('/api/stream')
      this._es = es

      es.addEventListener('connected', () => {
        this.sseConnected = true
      })

      es.addEventListener('chat', (e) => {
        const data = JSON.parse(e.data)
        this.chatLogs.unshift(data)
        if (this.chatLogs.length > 100) this.chatLogs.pop()
      })

      es.addEventListener('ban', (e) => {
        const data = JSON.parse(e.data)
        data._loading = false
        this.bans.unshift(data)
        if (this.bans.length > 50) this.bans.pop()
        this.loadStats()
        this.$message({ type: 'error', message: `🚫 封禁 @${data.username} - ${data.reason}`, duration: 5000 })
      })

      es.addEventListener('unban', (e) => {
        const data = JSON.parse(e.data)
        const ban = this.bans.find(b => b.user_id === data.user_id)
        if (ban) ban.auto_unban = false
        this.loadStats()
        this.$message({ type: 'success', message: `✅ 已解封 ${data.username || data.user_id}`, duration: 3000 })
      })

      es.addEventListener('heartbeat', () => {})

      es.onerror = () => {
        this.sseConnected = false
        setTimeout(() => this.connectSSE(), 3000)
      }
    },

    // API
    async loadChatHistory() {
      try {
        const r = await fetch('/api/chat')
        this.chatLogs = await r.json()
      } catch (e) {}
    },
    async loadBans() {
      try {
        const r = await fetch('/api/bans')
        const data = await r.json()
        this.bans = data.map(b => ({ ...b, _loading: false }))
      } catch (e) {}
    },
    async loadStats() {
      try {
        const r = await fetch('/api/stats')
        this.stats = await r.json()
      } catch (e) {}
    },
    async unbanUser(item) {
      this.$set(item, '_loading', true)
      try {
        const r = await fetch(`/api/unban/${item.user_id}`, { method: 'POST' })
        const data = await r.json()
        if (data.ok) {
          item.auto_unban = false
          this.$message.success(`✅ 已解封 @${item.username}`)
          this.loadStats()
        } else {
          this.$message.error(`❌ 解封失败: ${data.error}`)
        }
      } catch (e) {
        this.$message.error('❌ 网络错误')
      }
      this.$set(item, '_loading', false)
    },

    formatTime(iso) {
      if (!iso) return ''
      const d = new Date(iso)
      return d.toLocaleTimeString('zh-CN', { hour: '2-digit', minute: '2-digit', second: '2-digit' })
    },
  }
})
</script>
</body>
</html>
