<template>
  <div class="node-dashboard">
    <!-- 页面头部 -->
    <div class="dashboard-header">
      <h1>EasyTier 节点状态监控</h1>
      <p class="subtitle">实时监控所有共享节点的健康状态和连接信息</p>
    </div>

    <!-- 统计卡片 -->
    <el-row :gutter="20" class="stats-row">
      <el-col :span="6">
        <el-card class="stat-card">
          <div class="stat-content">
            <div class="stat-number">{{ totalNodes }}</div>
            <div class="stat-label">总节点数</div>
          </div>
          <el-icon class="stat-icon" color="#409EFF">
            <Monitor />
          </el-icon>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stat-card">
          <div class="stat-content">
            <div class="stat-number">{{ activeNodes }}</div>
            <div class="stat-label">在线节点</div>
          </div>
          <el-icon class="stat-icon" color="#67C23A">
            <CircleCheck />
          </el-icon>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stat-card">
          <div class="stat-content">
            <div class="stat-number">{{ averageLoad }} %</div>
            <div class="stat-label">平均负载</div>
          </div>
          <el-icon class="stat-icon" color="#E6A23C">
            <Link />
          </el-icon>
        </el-card>
      </el-col>
      <el-col :span="6">
        <el-card class="stat-card">
          <div class="stat-content">
            <div class="stat-number">{{ averageUptime }}%</div>
            <div class="stat-label">平均在线率</div>
          </div>
          <el-icon class="stat-icon" color="#F56C6C">
            <TrendCharts />
          </el-icon>
        </el-card>
      </el-col>
    </el-row>

    <!-- 搜索和筛选 -->
    <el-card class="filter-card">
      <el-row :gutter="26">
        <el-col :span="8">
          <el-input v-model="searchText" placeholder="搜索节点名称、主机地址或描述" prefix-icon="Search" clearable
            @input="handleSearch" />
        </el-col>
        <el-col :span="4">
          <el-select v-model="statusFilter" placeholder="状态筛选" clearable @change="handleFilter">
            <el-option label="全部" value="" />
            <el-option label="在线" value="true" />
            <el-option label="离线" value="false" />
          </el-select>
        </el-col>
        <el-col :span="4">
          <el-select v-model="protocolFilter" placeholder="协议筛选" clearable @change="handleFilter">
            <el-option label="全部" value="" />
            <el-option label="TCP" value="tcp" />
            <el-option label="UDP" value="udp" />
            <el-option label="WS" value="ws" />
            <el-option label="WSS" value="wss" />
          </el-select>
        </el-col>
        <!-- 新增：标签多选筛选 -->
        <el-col :span="4">
          <el-select v-model="selectedTags" multiple collapse-tags collapse-tags-tooltip filterable clearable
            placeholder="按标签筛选（可多选）" @change="handleFilter">
            <el-option v-for="tag in allTags" :key="tag" :label="tag" :value="tag">
              <span class="tag-option" :style="getTagStyle(tag)">{{ tag }}</span>
            </el-option>
          </el-select>
        </el-col>

        <el-col :span="4">
          <el-button type="success" @click="$router.push('/submit')">
            <el-icon>
              <Plus />
            </el-icon>
            提交节点
          </el-button>
        </el-col>
      </el-row>
    </el-card>

    <!-- 节点列表 -->
    <el-card ref="nodesCardRef" class="nodes-card">
      <template #header>
        <div class="card-header">
          <span>
            节点列表
            <el-button type="text" :loading="loading" @click="refreshData" style="margin-left: 8px;">
              <el-icon>
                <Refresh />
              </el-icon>
            </el-button>
          </span>
          <el-tag :type="loading ? 'info' : 'success'">
            {{ loading ? '加载中...' : `共 ${pagination.total} 个节点` }}
          </el-tag>
        </div>
      </template>

      <el-table ref="tableRef" :data="nodes" v-loading="loading" stripe style="width: 100%" row-key="id">
        <!-- 展开列 -->
        <el-table-column type="expand" width="50">
          <template #default="{ row }">
            <div class="expanded-content">
              <HealthTimeline :node-info="row" :compact="true" />
            </div>
          </template>
        </el-table-column>

        <el-table-column prop="name" label="节点名称" width="150">
          <template #default="{ row }">
            <div class="node-name">
              <el-icon :color="row.is_active ? '#67C23A' : '#F56C6C'">
                <CircleCheck v-if="row.is_active" />
                <CircleClose v-else />
              </el-icon>
              <span>{{ row.name }}</span>
            </div>
          </template>
        </el-table-column>

        <el-table-column prop="address" label="节点连接地址" width="250">
          <template #header>
            <span>节点连接地址</span>
            <el-tooltip content="可以将节点链接填入命令行的 -p 参数，或者图形界面的节点地址字段（公共服务器或手动皆可）" placement="top" effect="light">
              <el-icon class="help-icon">
                <QuestionFilled />
              </el-icon>
            </el-tooltip>
          </template>
          <template #default="{ row }">
            <el-tag type="primary" size="" style="margin-bottom: 0.2rem;"
              @click="copyAddress(apiUrl + 'node/' + row.id)"> {{
                apiUrl
              }}node/{{ row.id }}</el-tag>
            <el-tag type="info" size="" @click="copyAddress(row.address)">{{ row.address }}</el-tag>
          </template>
        </el-table-column>

        <el-table-column label="版本" width="90">
          <template #default="{ row }">
            <div style="display: flex; flex-direction: column; gap: 1px; align-items: flex-start;">
              <el-tag v-if="row.version" size="small" style="font-size: 11px; padding: 1px 4px;">{{ row.version
              }}</el-tag>
              <span v-else class="text-muted" style="font-size: 11px;">未知</span>
              <el-tag :type="row.allow_relay ? 'success' : 'info'" size="small"
                style="font-size: 9px; padding: 1px 3px;">
                {{ row.allow_relay ? '可中转' : '禁中转' }}
              </el-tag>
            </div>
          </template>
        </el-table-column>

        <el-table-column label="连接状态" width="150">
          <template #default="{ row }">
            <div class="connection-info">
              <span>{{ row.current_connections }}/{{ row.max_connections }}</span>
              <el-progress :percentage="row.usage_percentage" :color="getProgressColor(row.usage_percentage)"
                :stroke-width="6" :show-text="false" />
            </div>
          </template>
        </el-table-column>

        <el-table-column prop="description" label="描述" min-width="200">
          <template #default="{ row }">
            <span class="description">{{ row.description || '暂无描述' }}</span>
          </template>
        </el-table-column>
        <!-- 新增：标签展示 -->
        <el-table-column label="标签" min-width="160">
          <template #default="{ row }">
            <div class="tags-list">
              <el-tag v-for="(tag, idx) in row.tags" :key="tag + idx" size="small" class="tag-chip"
                :style="getTagStyle(tag)" style="margin: 2px 6px 2px 0;">
                {{ tag }}
              </el-tag>
              <span v-if="!row.tags || row.tags.length === 0" class="text-muted">无</span>
            </div>
          </template>
        </el-table-column>

        <el-table-column prop="created_at" label="创建时间" width="180">
          <template #default="{ row }">
            {{ formatDate(row.created_at) }}
          </template>
        </el-table-column>

        <el-table-column label="操作" width="120" fixed="right">
          <template #default="{ row }">
            <el-button type="primary" size="small" @click.stop="viewNodeDetails(row)">
              详情
            </el-button>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-wrapper">
        <el-pagination v-model:current-page="pagination.page" v-model:page-size="pagination.per_page"
          :page-sizes="[10, 20, 50, 100]" :total="pagination.total" layout="total, sizes, prev, pager, next, jumper"
          @size-change="handleSizeChange" @current-change="handleCurrentChange" />
      </div>
    </el-card>

    <!-- 节点详情对话框 -->
    <el-dialog v-model="detailDialogVisible" :title="selectedNode?.name + ' - 详细信息'" width="800px" destroy-on-close>
      <div v-if="selectedNode" class="node-details">
        <el-descriptions :column="2" border>
          <el-descriptions-item label="节点名称">{{ selectedNode.name }}</el-descriptions-item>
          <el-descriptions-item label="状态">
            <el-tag :type="selectedNode.is_active ? 'success' : 'danger'">
              {{ selectedNode.is_active ? '在线' : '离线' }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="主机地址">{{ selectedNode.host }}</el-descriptions-item>
          <el-descriptions-item label="端口">{{ selectedNode.port }}</el-descriptions-item>
          <el-descriptions-item label="协议">{{ selectedNode.protocol.toUpperCase() }}</el-descriptions-item>
          <el-descriptions-item label="版本">{{ selectedNode.version || '未知' }}</el-descriptions-item>
          <el-descriptions-item label="允许中转">
            <el-tag :type="selectedNode.allow_relay ? 'success' : 'info'" size="small">
              {{ selectedNode.allow_relay ? '是' : '否' }}
            </el-tag>
          </el-descriptions-item>
          <el-descriptions-item label="使用率">{{ selectedNode.usage_percentage.toFixed(1) }}%</el-descriptions-item>
          <el-descriptions-item label="创建时间">{{ formatDate(selectedNode.created_at) }}</el-descriptions-item>
          <el-descriptions-item label="更新时间">{{ formatDate(selectedNode.updated_at) }}</el-descriptions-item>
          <el-descriptions-item label="描述" :span="2">{{ selectedNode.description || '暂无描述' }}</el-descriptions-item>
          <!-- 新增：标签 -->
          <el-descriptions-item label="标签" :span="2">
            <div class="tags-list">
              <el-tag v-for="(tag, idx) in selectedNode.tags" :key="tag + idx" size="small" class="tag-chip"
                style="margin: 2px 6px 2px 0;">
                {{ tag }}
              </el-tag>
              <span v-if="!selectedNode.tags || selectedNode.tags.length === 0" class="text-muted">无</span>
            </div>
          </el-descriptions-item>
        </el-descriptions>

        <!-- 健康状态统计 -->
        <div class="health-stats" v-if="healthStats">
          <h3>健康状态统计 (最近24小时)</h3>
          <el-row :gutter="20">
            <el-col :span="6">
              <div class="health-stat-item">
                <div class="stat-value">{{ healthStats.uptime_percentage?.toFixed(1) || 0 }}%</div>
                <div class="stat-label">在线率</div>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="health-stat-item">
                <div class="stat-value">{{ (selectedNode.last_response_time / 1000) || 0 }}ms</div>
                <div class="stat-label">平均响应时间</div>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="health-stat-item">
                <div class="stat-value">{{ healthStats.total_checks || 0 }}</div>
                <div class="stat-label">检查次数</div>
              </div>
            </el-col>
            <el-col :span="6">
              <div class="health-stat-item">
                <div class="stat-value">{{ healthStats.failed_checks || 0 }}</div>
                <div class="stat-label">失败次数</div>
              </div>
            </el-col>
          </el-row>
        </div>
      </div>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, reactive, onMounted, computed, watch, nextTick, onBeforeUnmount } from 'vue'
import { ElMessage } from 'element-plus'
import { nodeApi } from '../api'
import dayjs from 'dayjs'
import HealthTimeline from '../components/HealthTimeline.vue'
import {
  Monitor,
  CircleCheck,
  CircleClose,
  Link,
  TrendCharts,
  Search,
  Refresh,
  Plus
} from '@element-plus/icons-vue'
import { getTagStyle } from '../utils/tagColor'

// 响应式数据
const loading = ref(false)
const nodes = ref([])
const searchText = ref('')
const statusFilter = ref('')
const protocolFilter = ref('')
const selectedTags = ref([])
const allTags = ref([])
const detailDialogVisible = ref(false)
const selectedNode = ref(null)
const healthStats = ref(null)
const expandedRows = ref([])
const apiUrl = ref(window.location.href)
const tableRef = ref(null)
const nodesCardRef = ref(null)

// 请求取消控制（避免重复请求覆盖）
let fetchController = null

// 分页数据
const pagination = reactive({
  page: 1,
  per_page: 50,
  total: 0
})

// 计算属性
const totalNodes = computed(() => nodes.value.length)
const activeNodes = computed(() => nodes.value.filter(node => node.is_active).length)
const averageLoad = computed(() =>
  (nodes.value.reduce((sum, node) => sum + node.current_connections, 0) / (nodes.value.length)).toFixed(2)
)
const averageUptime = computed(() => {
  if (nodes.value.length === 0) return 0
  const activeCount = nodes.value.filter(node => node.is_active).length
  return ((activeCount / nodes.value.length) * 100).toFixed(1)
})

// 方法
const fetchTags = async () => {
  try {
    const resp = await nodeApi.getAllTags()
    if (resp.success && Array.isArray(resp.data)) {
      allTags.value = resp.data
    }
  } catch (error) {
    console.error('获取标签列表失败:', error)
  }
}

const fetchNodes = async (with_loading = true) => {
  try {
    if (with_loading) {
      loading.value = true
    }
    const params = {
      page: pagination.page,
      per_page: pagination.per_page
    }

    if (searchText.value) {
      params.search = searchText.value
    }
    if (statusFilter.value !== '') {
      params.is_active = statusFilter.value === 'true'
    }
    if (protocolFilter.value) {
      params.protocol = protocolFilter.value
    }
    if (selectedTags.value && selectedTags.value.length > 0) {
      params.tags = selectedTags.value
    }

    // 取消上一请求，创建新的请求控制器
    if (fetchController) {
      try { fetchController.abort() } catch (_) { }
    }
    fetchController = new AbortController()

    const response = await nodeApi.getNodes(params, { signal: fetchController.signal })
    if (response.success && response.data) {
      nodes.value = response.data.items
      pagination.total = response.data.total
    }
  } catch (error) {
    if (error.name === 'CanceledError' || error.name === 'AbortError') {
      // 被取消的旧请求，忽略
      return
    }
    console.error('获取节点列表失败:', error)
    ElMessage.error('获取节点列表失败')
  } finally {
    if (with_loading) {
      loading.value = false
    }
  }
}

const refreshData = () => {
  pagination.page = 1
  fetchNodes()
}

const handleSearch = () => {
  pagination.page = 1
  fetchNodes()
}

const handleFilter = () => {
  pagination.page = 1
  fetchNodes()
}

const handleSizeChange = (size) => {
  pagination.per_page = size
  pagination.page = 1
  fetchNodes()
}

const handleCurrentChange = (page) => {
  pagination.page = page
  fetchNodes()
}

const viewNodeDetails = async (node) => {
  selectedNode.value = node
  detailDialogVisible.value = true

  // 获取健康状态统计
  try {
    const response = await nodeApi.getNodeHealthStats(node.id, { hours: 24 })
    if (response.success && response.data) {
      healthStats.value = response.data
    }
  } catch (error) {
    console.error('获取健康状态统计失败:', error)
  }
}

const formatDate = (dateString) => {
  return dayjs(dateString).format('YYYY-MM-DD HH:mm:ss')
}

const getProgressColor = (percentage) => {
  if (percentage < 50) return '#67C23A'
  if (percentage < 80) return '#E6A23C'
  return '#F56C6C'
}

const copyAddress = (address) => {
  try {
    navigator.clipboard.writeText(address).then(() => {
      ElMessage.success(`地址已复制, ${address}`)
    }).catch(() => {
      ElMessage.error(`复制失败, ${address}`)
    })
  } catch (error) {
    ElMessage.error(`复制失败, ${address}`)
  }
}

// 生命周期
onMounted(() => {
  fetchTags()
  fetchNodes()

  // 设置定时刷新
  setInterval(() => {
    fetchNodes(false)
  }, 30000) // 每30秒刷新一次
})

// 智能滚动处理：纵向滚动时页面整体滚动，横向滚动时表格内部滚动
let wheelHandler = null
let wheelTargets = []

const detachWheelHandlers = () => {
  if (wheelTargets && wheelTargets.length) {
    wheelTargets.forEach((el) => {
      try { el.removeEventListener('wheel', wheelHandler, { capture: true }) } catch (_) { }
    })
  }
  wheelTargets = []
}

const attachWheelHandler = () => {
  const tableEl = tableRef.value?.$el
  const body = tableEl ? tableEl.querySelector('.el-table__body-wrapper') : null
  if (!body) return

  detachWheelHandlers()
  const wrap = body.querySelector('.el-scrollbar__wrap') || body

  wheelHandler = (e) => {
    const deltaX = e.deltaX
    const deltaY = e.deltaY

    // 如果是横向滚动（Shift + 滚轮 或 触摸板横向滑动）
    if (Math.abs(deltaX) > Math.abs(deltaY) || e.shiftKey) {
      // 允许表格内部横向滚动，不阻止默认行为
      return
    }

    // 如果是纵向滚动，阻止表格内部滚动，让页面整体滚动
    if (deltaY) {
      e.preventDefault()
      e.stopPropagation()
      const scroller = document.scrollingElement || document.documentElement
      scroller.scrollTop += deltaY
    }
  }

  body.addEventListener('wheel', wheelHandler, { passive: false, capture: true })
  wheelTargets.push(body)
}

onMounted(() => {
  nextTick(attachWheelHandler)
})

watch(nodes, () => {
  nextTick(attachWheelHandler)
})

onBeforeUnmount(() => {
  detachWheelHandlers()
})
</script>

<style scoped>
.node-dashboard {
  padding: 20px;
  background-color: #f5f7fa;
  min-height: 100vh;
}

.dashboard-header {
  text-align: center;
  margin-bottom: 30px;
}

.dashboard-header h1 {
  color: #303133;
  margin-bottom: 10px;
  font-size: 32px;
  font-weight: 600;
}

.subtitle {
  color: #606266;
  font-size: 16px;
  margin: 0;
}

.stats-row {
  margin-bottom: 16px;
}

.stat-card {
  position: relative;
  overflow: hidden;
  height: 100px;
}

.stat-content {
  padding: 0 16px;
  height: 100%;
  display: flex;
  flex-direction: column;
  justify-content: center;
  align-items: center;
}

.stat-number {
  font-size: 24px;
  font-weight: bold;
  color: #303133;
  line-height: 1;
  margin-bottom: 4px;
}

.stat-label {
  font-size: 12px;
  color: #909399;
  margin: 0;
}

.stat-icon {
  position: absolute;
  right: 12px;
  top: 50%;
  transform: translateY(-50%);
  font-size: 28px;
  opacity: 0.3;
}

.filter-card {
  margin-bottom: 20px;
}

.nodes-card {
  background: white;
  border-radius: 8px;
}

.card-header {
  display: flex;
  justify-content: space-between;
  align-items: center;
}

.node-name {
  display: flex;
  align-items: center;
  gap: 8px;
}

.address {
  margin-left: 8px;
  font-family: monospace;
}

.connection-info {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.description {
  color: #606266;
  font-size: 13px;
}

.text-muted {
  color: #C0C4CC;
}

.pagination-wrapper {
  display: flex;
  justify-content: center;
  margin-top: 20px;
}

.node-details {
  padding: 10px 0;
}

.health-stats {
  margin-top: 30px;
  padding-top: 20px;
  border-top: 1px solid #EBEEF5;
}

.health-stats h3 {
  margin-bottom: 20px;
  color: #303133;
}

.health-stat-item {
  text-align: center;
  padding: 15px;
  background: #f8f9fa;
  border-radius: 6px;
}

.health-stat-item .stat-value {
  font-size: 24px;
  font-weight: bold;
  color: #409EFF;
  margin-bottom: 5px;
}

.health-stat-item .stat-label {
  font-size: 12px;
  color: #909399;
}

.expanded-content {
  padding: 16px 24px;
  background-color: #fafafa;
  border-top: 1px solid #ebeef5;
}

.tag-option {
  display: inline-block;
  padding: 2px 6px;
  border-radius: 4px;
  font-size: 12px;
}

:deep(.el-table__body-wrapper) {
  overflow-x: auto !important;
  overflow-y: hidden !important;
  height: auto !important;
}

:deep(.el-card__body) {
  overflow: visible !important;
}

:deep(.el-table__body-wrapper .el-scrollbar__wrap) {
  overflow-x: auto !important;
  overflow-y: hidden !important;
  height: auto !important;
  max-height: none !important;
}
</style>
