<template>
  <div class="port-status">
    <a-row :gutter="[24, 24]">
      <!-- 顶部概览 -->
      <a-col :span="24">
        <a-card>
          <div class="overview-bar">
            <div class="overview-item">
              <span class="overview-label">面板数量</span>
              <a-tag color="blue">{{ panelCount }} 个</a-tag>
            </div>
            <div class="overview-item">
              <span class="overview-label">端口总数</span>
              <a-tag color="purple">{{ totalPorts }} 个</a-tag>
            </div>
            <div class="overview-item">
              <span class="overview-label">告警端口</span>
              <a-tag color="red">{{ alarmPortCount }} 个</a-tag>
            </div>
            <div class="overview-item">
              <span class="overview-label">最近更新</span>
              <span class="overview-value">{{ lastUpdate }}</span>
            </div>
            <div class="overview-item">
              <a-button type="primary" size="small" @click="refreshData" :loading="loading">
                刷新
              </a-button>
              <a-button size="small" @click="clearEvents" :style="{ marginLeft: '8px' }">
                清除事件
              </a-button>
              <a-button size="small" type="dashed" @click="openSyncModal" :style="{ marginLeft: '8px' }">
                同步映射
              </a-button>
            </div>
          </div>
        </a-card>
      </a-col>

      <!-- 同步映射弹窗 -->
      <a-modal
        v-model:open="syncModalVisible"
        title="同步端口映射"
        :confirm-loading="syncing"
        @ok="handleSyncMapping"
        @cancel="syncModalVisible = false"
        width="600px"
      >
        <a-alert
          message="同步映射说明"
          description="将期望的UID映射到指定端口。同步后，系统会比较实际连接UID与期望UID，不匹配时触发告警。"
          type="info"
          show-icon
          :style="{ marginBottom: '16px' }"
        />
        <a-tabs v-model:activeKey="syncMode">
          <a-tab-pane key="single" tab="单个端口">
            <a-form layout="vertical">
              <a-row :gutter="16">
                <a-col :span="8">
                  <a-form-item label="面板ID">
                    <a-input-number
                      v-model:value="syncForm.panel_id"
                      :min="1"
                      style="width: 100%"
                      placeholder="1"
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="8">
                  <a-form-item label="端口ID">
                    <a-input-number
                      v-model:value="syncForm.port_id"
                      :min="1"
                      style="width: 100%"
                      placeholder="1"
                    />
                  </a-form-item>
                </a-col>
                <a-col :span="8">
                  <a-form-item label="期望UID">
                    <a-input
                      v-model:value="syncForm.jumper_uid"
                      placeholder="A1B2C3D4"
                      :maxlength="8"
                    />
                  </a-form-item>
                </a-col>
              </a-row>
              <a-button type="primary" @click="syncSinglePort" :loading="syncing">
                同步单个端口
              </a-button>
            </a-form>
          </a-tab-pane>
          <a-tab-pane key="batch" tab="批量同步">
            <a-alert
              message="批量格式"
              description="每行一个映射，格式: panel_id,port_id,jumper_uid (如: 1,1,A1B2C3D4)"
              type="warning"
              show-icon
              :style="{ marginBottom: '12px' }"
            />
            <a-textarea
              v-model:value="batchSyncText"
              :rows="8"
              placeholder="1,1,A1B2C3D4&#10;1,2,A1B2C3D5&#10;2,1,A1B2C3D6"
            />
            <a-button
              type="primary"
              @click="syncBatchPorts"
              :loading="syncing"
              :style="{ marginTop: '12px' }"
            >
              批量同步
            </a-button>
          </a-tab-pane>
        </a-tabs>
      </a-modal>

      <!-- 端口状态面板 -->
      <a-col :xs="24" :lg="14">
        <a-card title="端口状态">
          <a-empty v-if="Object.keys(portState).length === 0" description="暂无端口数据" />
          <div v-else class="port-grid">
            <div
              v-for="(panelData, panelId) in sortedPortState"
              :key="panelId"
              class="panel-section"
            >
              <div class="panel-header">面板 {{ panelId }}</div>
              <div class="ports-row">
                <div
                  v-for="(portData, portId) in panelData"
                  :key="portId"
                  class="port-cell"
                  :class="getPortClass(portData)"
                  :title="getPortTitle(panelId, portId, portData)"
                >
                  <div class="port-number">{{ portId }}</div>
                  <div class="port-uid">{{ formatUid(portData.last_uid) }}</div>
                </div>
              </div>
            </div>
          </div>
          <!-- 图例 -->
          <div class="port-legend">
            <div class="legend-item">
              <span class="dot" :style="{ background: portColors.idle }"></span> 无设备
            </div>
            <div class="legend-item">
              <span class="dot" :style="{ background: portColors.normal }"></span> 正常
            </div>
            <div class="legend-item">
              <span class="dot" :style="{ background: portColors.alarm }"></span> 告警
            </div>
          </div>
        </a-card>
      </a-col>

      <!-- 事件历史 -->
      <a-col :xs="24" :lg="10">
        <a-card title="事件历史">
          <a-empty v-if="events.length === 0" description="暂无事件" />
          <a-timeline v-else>
            <a-timeline-item
              v-for="(event, index) in recentEvents"
              :key="index"
              :color="getEventColor(event.event_type)"
            >
              <div class="event-item">
                <div class="event-header">
                  <a-tag :color="getEventTagColor(event.event_type)" size="small">
                    {{ eventTypeText[event.event_type] || event.event_type }}
                  </a-tag>
                  <span class="event-time">{{ formatTime(event.timestamp) }}</span>
                </div>
                <div class="event-detail">
                  面板 {{ event.panel_id }} 端口 {{ event.port_id }}
                </div>
                <div class="event-uid">
                  UID: {{ formatUid(event.jumper_uid) }}
                </div>
              </div>
            </a-timeline-item>
          </a-timeline>
        </a-card>
      </a-col>
    </a-row>
  </div>
</template>

<script setup>
import { ref, computed, onMounted, onUnmounted } from 'vue'
import { message } from 'ant-design-vue'
import apiService from '../api/apiService'

const loading = ref(false)
const lastUpdate = ref('')
const portState = ref({})
const events = ref([])
const pollTimer = ref(null)

// 同步映射相关
const syncModalVisible = ref(false)
const syncing = ref(false)
const syncMode = ref('single')
const syncForm = ref({
  panel_id: 1,
  port_id: 1,
  jumper_uid: ''
})
const batchSyncText = ref('')

const portColors = {
  idle: '#d9d9d9',
  normal: '#52c41a',
  alarm: '#ff4d4f'
}

const eventTypeText = {
  'CONNECT': '连接',
  'DISCONNECT': '断开',
  'MOVE': '移动',
  'ILLEGAL_CONNECT': '非法连接',
  'ILLEGAL_DISCONNECT': '非法断开'
}

const panelCount = computed(() => Object.keys(portState.value).length)

const totalPorts = computed(() => {
  let count = 0
  for (const panelData of Object.values(portState.value)) {
    count += Object.keys(panelData).length
  }
  return count
})

const alarmPortCount = computed(() => {
  let count = 0
  for (const panelData of Object.values(portState.value)) {
    for (const portData of Object.values(panelData)) {
      if (portData.alarm_count > 0) {
        count++
      }
    }
  }
  return count
})

const sortedPortState = computed(() => {
  const sorted = {}
  const panelIds = Object.keys(portState.value).sort((a, b) => Number(a) - Number(b))
  for (const panelId of panelIds) {
    sorted[panelId] = {}
    const portIds = Object.keys(portState.value[panelId]).sort((a, b) => Number(a) - Number(b))
    for (const portId of portIds) {
      sorted[panelId][portId] = portState.value[panelId][portId]
    }
  }
  return sorted
})

const recentEvents = computed(() => {
  return events.value.slice(0, 20).reverse()
})

function getPortClass(portData) {
  if (!portData.last_uid) return 'port-idle'
  if (portData.alarm_count > 0) return 'port-alarm'
  return 'port-normal'
}

function getPortTitle(panelId, portId, portData) {
  const lines = [`面板 ${panelId} 端口 ${portId}`]
  if (portData.last_uid) {
    lines.push(`当前UID: ${portData.last_uid}`)
  }
  if (portData.expected_uid) {
    lines.push(`期望UID: ${portData.expected_uid}`)
  }
  if (portData.alarm_count > 0) {
    lines.push(`告警次数: ${portData.alarm_count}`)
  }
  return lines.join('\n')
}

function formatUid(uid) {
  if (!uid) return '--'
  if (typeof uid === 'string' && uid.length === 8) {
    return uid.match(/.{1,2}/g)?.join(':') || uid
  }
  return uid.substring(0, 8)
}

function formatTime(timestamp) {
  if (!timestamp) return ''
  const date = new Date(timestamp)
  return date.toLocaleTimeString()
}

function getEventColor(eventType) {
  if (eventType?.includes('ILLEGAL')) return 'red'
  if (eventType === 'CONNECT') return 'green'
  if (eventType === 'DISCONNECT') return 'gray'
  if (eventType === 'MOVE') return 'blue'
  return 'blue'
}

function getEventTagColor(eventType) {
  if (eventType?.includes('ILLEGAL')) return 'red'
  if (eventType === 'CONNECT') return 'green'
  if (eventType === 'DISCONNECT') return 'default'
  if (eventType === 'MOVE') return 'blue'
  return 'default'
}

async function loadPortStatus() {
  try {
    const res = await apiService.port.getStatus()
    if (res.data.success) {
      portState.value = res.data.port_state || {}
    }
  } catch (e) {
    console.error('load port status error:', e)
  }
}

async function loadEvents() {
  try {
    const res = await apiService.port.getEvents(100)
    if (res.data.success) {
      events.value = res.data.events || []
    }
  } catch (e) {
    console.error('load events error:', e)
  }
}

async function refreshData() {
  loading.value = true
  try {
    await Promise.all([loadPortStatus(), loadEvents()])
    lastUpdate.value = new Date().toLocaleTimeString()
  } finally {
    loading.value = false
  }
}

async function clearEvents() {
  try {
    const res = await apiService.port.clearEvents()
    if (res.data.success) {
      message.success('事件已清除')
      events.value = []
    }
  } catch (e) {
    console.error('clear events error:', e)
    message.error('清除失败')
  }
}

function openSyncModal() {
  syncModalVisible.value = true
}

async function syncSinglePort() {
  if (!syncForm.value.jumper_uid) {
    message.warning('请输入期望UID')
    return
  }
  syncing.value = true
  try {
    const res = await apiService.dtu.sendControl({
      command: 'SYNC_PORT_MAPPING',
      params: {
        target: 'port',
        panel_id: syncForm.value.panel_id,
        port_id: syncForm.value.port_id,
        jumper_uid: syncForm.value.jumper_uid.toUpperCase()
      }
    })
    if (res.data.success) {
      message.success('端口映射已同步')
      syncForm.value.jumper_uid = ''
    } else {
      message.error(res.data.message || '同步失败')
    }
  } catch (e) {
    console.error('sync port mapping error:', e)
    message.error('同步失败')
  } finally {
    syncing.value = false
  }
}

async function syncBatchPorts() {
  if (!batchSyncText.value.trim()) {
    message.warning('请输入批量映射数据')
    return
  }
  const lines = batchSyncText.value.trim().split('\n')
  const mappings = []
  for (const line of lines) {
    const parts = line.split(',').map(p => p.trim())
    if (parts.length >= 3) {
      mappings.push({
        panel_id: parseInt(parts[0]) || 1,
        port_id: parseInt(parts[1]) || 1,
        jumper_uid: parts[2].toUpperCase()
      })
    }
  }
  if (mappings.length === 0) {
    message.warning('无效的映射数据')
    return
  }
  syncing.value = true
  try {
    const res = await apiService.dtu.sendControl({
      command: 'SYNC_ALL_MAPPING',
      params: {
        target: 'port',
        mappings
      }
    })
    if (res.data.success) {
      message.success(`已同步 ${mappings.length} 个端口映射`)
      batchSyncText.value = ''
    } else {
      message.error(res.data.message || '批量同步失败')
    }
  } catch (e) {
    console.error('sync all mapping error:', e)
    message.error('批量同步失败')
  } finally {
    syncing.value = false
  }
}

async function handleSyncMapping() {
  if (syncMode.value === 'single') {
    await syncSinglePort()
  } else {
    await syncBatchPorts()
  }
  if (syncModalVisible.value) {
    syncModalVisible.value = false
  }
}

onMounted(async () => {
  await refreshData()
  pollTimer.value = setInterval(refreshData, 5000)
})

onUnmounted(() => {
  if (pollTimer.value) clearInterval(pollTimer.value)
})
</script>

<style scoped>
.overview-bar {
  display: flex;
  align-items: center;
  gap: 24px;
  flex-wrap: wrap;
}
.overview-item {
  display: flex;
  align-items: center;
  gap: 8px;
}
.overview-label {
  font-size: 14px;
  color: #666;
}
.overview-value {
  font-size: 14px;
  color: #333;
}
.port-grid {
  display: flex;
  flex-direction: column;
  gap: 16px;
}
.panel-section {
  border: 1px solid #f0f0f0;
  border-radius: 8px;
  padding: 12px;
}
.panel-header {
  font-weight: 600;
  margin-bottom: 8px;
  color: #333;
}
.ports-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
}
.port-cell {
  width: 64px;
  height: 56px;
  border-radius: 6px;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
  border: 2px solid rgba(0, 0, 0, 0.1);
  cursor: default;
  transition: all 0.2s;
}
.port-cell:hover {
  transform: scale(1.05);
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.15);
}
.port-idle {
  background-color: #f5f5f5;
}
.port-normal {
  background-color: #f6ffed;
  border-color: #b7eb8f;
}
.port-alarm {
  background-color: #fff2f0;
  border-color: #ffccc7;
  animation: pulse 1.5s infinite;
}
@keyframes pulse {
  0%, 100% { opacity: 1; }
  50% { opacity: 0.7; }
}
.port-number {
  font-size: 14px;
  font-weight: 600;
  color: #333;
}
.port-uid {
  font-size: 9px;
  color: #666;
  margin-top: 2px;
  max-width: 60px;
  overflow: hidden;
  text-overflow: ellipsis;
  white-space: nowrap;
}
.port-legend {
  display: flex;
  gap: 20px;
  margin-top: 16px;
  flex-wrap: wrap;
}
.legend-item {
  display: flex;
  align-items: center;
  gap: 6px;
  font-size: 13px;
  color: #666;
}
.dot {
  display: inline-block;
  width: 14px;
  height: 14px;
  border-radius: 50%;
  border: 1px solid rgba(0, 0, 0, 0.1);
}
.event-item {
  padding: 4px 0;
}
.event-header {
  display: flex;
  align-items: center;
  gap: 8px;
}
.event-time {
  font-size: 12px;
  color: #999;
}
.event-detail {
  font-size: 13px;
  color: #333;
  margin-top: 4px;
}
.event-uid {
  font-size: 12px;
  color: #666;
  font-family: monospace;
}
</style>