<template>
  <div class="device-list">
    <!-- 页头 -->
    <div class="page-header">
      <div class="page-title-group">
        <h1 class="page-title">设备列表</h1>
        <span class="page-subtitle">ONU 终端设备管理</span>
      </div>
      <div class="header-actions">
        <el-button type="danger" plain size="small" @click="clearStatus" :loading="clearing">
          清空状态
        </el-button>
        <el-button type="warning" size="small" @click="refreshAllStatus" :loading="refreshing">
          {{ refreshing ? '更新中…' : '全部更新' }}
        </el-button>
      </div>
    </div>

    <!-- 筛选栏 -->
    <div class="filter-bar">
      <div class="filter-group">
        <label class="filter-label">区域</label>
        <el-select
          v-model="filters.region"
          placeholder="全部区域"
          clearable
          @change="search"
          size="small"
          style="width: 160px"
        >
          <el-option v-for="r in regions" :key="r" :label="r" :value="r" />
        </el-select>
      </div>
      <div class="filter-group">
        <label class="filter-label">状态</label>
        <el-select
          v-model="filters.status"
          placeholder="全部"
          clearable
          @change="search"
          size="small"
          style="width: 110px"
        >
          <el-option label="在线" value="online" />
          <el-option label="离线" value="offline" />
          <el-option label="未知" value="unknown" />
        </el-select>
      </div>
      <div class="filter-group">
        <label class="filter-label">搜索</label>
        <el-input
          v-model="filters.keyword"
          placeholder="MAC / 区域 / 学校 / 楼宇 / 房间"
          clearable
          size="small"
          @clear="search"
          @keyup.enter="search"
          style="width: 280px"
        >
          <template #prefix>
            <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
              <circle cx="11" cy="11" r="8"/><line x1="21" y1="21" x2="16.65" y2="16.65"/>
            </svg>
          </template>
        </el-input>
      </div>
      <el-button type="primary" size="small" @click="search">查询</el-button>
    </div>

    <!-- 数据面板 -->
    <div class="data-panel">
      <!-- 统计行 -->
      <div class="data-stats">
        <span class="data-total">共 <strong>{{ total }}</strong> 条记录</span>
        <div class="status-legend">
          <span class="legend-item">
            <span class="led online"></span>在线
          </span>
          <span class="legend-item">
            <span class="led offline"></span>离线
          </span>
          <span class="legend-item">
            <span class="led unknown"></span>未知
          </span>
        </div>
      </div>

      <!-- 表格 -->
      <el-table
        :data="devices"
        border
        stripe
        size="small"
        style="width: 100%"
      >
        <el-table-column type="index" label="#" width="52" align="center">
          <template #default="{ $index }">
            <span class="row-index">{{ (page - 1) * pageSize + $index + 1 }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="region" label="区域" width="90" />
        <el-table-column prop="school_name" label="学校名称" width="170" show-overflow-tooltip />
        <el-table-column prop="building" label="楼宇" width="120" show-overflow-tooltip />
        <el-table-column prop="place_type" label="场所类型" width="110" show-overflow-tooltip />
        <el-table-column prop="room_number" label="房间号" width="90" />
        <el-table-column prop="mac_address" label="MAC 地址" width="160">
          <template #default="{ row }">
            <span class="mac-link" @click="openDetail(row)">
              {{ formatMac(row.mac_address) }}
            </span>
          </template>
        </el-table-column>
        <el-table-column prop="status" label="状态" width="76" align="center">
          <template #default="{ row }">
            <span class="status-badge" :class="row.status">
              <span class="status-dot-sm"></span>
              {{ row.status === 'online' ? '在线' : row.status === 'offline' ? '离线' : '未知' }}
            </span>
          </template>
        </el-table-column>
        <el-table-column prop="distance_m" label="距离" width="80" align="right">
          <template #default="{ row }">
            <span class="mono-val">{{ row.distance_m ? row.distance_m + 'm' : '—' }}</span>
          </template>
        </el-table-column>
        <el-table-column prop="notes" label="备注" min-width="100" show-overflow-tooltip>
          <template #default="{ row }">
            <span style="color: var(--text-muted); font-size: 12px">{{ row.notes || '—' }}</span>
          </template>
        </el-table-column>
      </el-table>

      <!-- 分页 -->
      <div class="pagination-wrap">
        <el-pagination
          v-model:current-page="page"
          v-model:page-size="pageSize"
          :page-sizes="[20, 50, 100]"
          :total="total"
          @current-change="loadDevices"
          @size-change="handleSizeChange"
          layout="total, sizes, prev, pager, next"
        />
      </div>
    </div>

    <!-- 检查结果对话框 -->
    <el-dialog v-model="checkResultVisible" title="全部更新结果" width="680px" destroy-on-close>
      <div v-if="checkInProgress" class="dialog-loading">
        <div class="loading-spinner"></div>
        <span>正在扫描所有 OLT，请稍候…</span>
      </div>
      <div v-else-if="checkResult">
        <el-alert
          :type="checkResult.success ? 'success' : 'error'"
          :title="checkResult.success ? '更新完成' : '更新失败'"
          :description="checkResult.error || ''"
          :closable="false"
          style="margin-bottom: 16px"
        />
        <template v-if="checkResult.success">
          <div class="result-stats">
            <div class="result-stat">
              <span class="rs-val online">{{ checkResult.total_online || 0 }}</span>
              <span class="rs-label">在线设备</span>
            </div>
            <div class="result-stat">
              <span class="rs-val offline">{{ checkResult.total_offline || 0 }}</span>
              <span class="rs-label">离线设备</span>
            </div>
            <div class="result-stat">
              <span class="rs-val warn">{{ (checkResult.errors || []).length }}</span>
              <span class="rs-label">失败 OLT</span>
            </div>
          </div>
          <el-table :data="checkResult.results || []" border size="small" max-height="280">
            <el-table-column prop="olt_location" label="OLT 名称" min-width="150" show-overflow-tooltip />
            <el-table-column label="在线" width="70" align="center">
              <template #default="{ row }">
                <span class="mono-val" style="color: var(--success)">{{ row.online || 0 }}</span>
              </template>
            </el-table-column>
            <el-table-column label="离线" width="70" align="center">
              <template #default="{ row }">
                <span class="mono-val" style="color: var(--danger)">{{ row.offline || 0 }}</span>
              </template>
            </el-table-column>
            <el-table-column label="状态" width="80" align="center">
              <template #default="{ row }">
                <el-tag :type="row.success ? 'success' : 'danger'" size="small">
                  {{ row.success ? '成功' : '失败' }}
                </el-tag>
              </template>
            </el-table-column>
          </el-table>
        </template>
      </div>
      <template #footer>
        <el-button @click="checkResultVisible = false">关闭</el-button>
        <el-button type="primary" @click="checkResultVisible = false; loadDevices()" v-if="!checkInProgress">
          刷新列表
        </el-button>
      </template>
    </el-dialog>

    <!-- 设备详情对话框 -->
    <el-dialog v-model="detailVisible" title="设备详情" width="500px" destroy-on-close>
      <el-descriptions :column="2" border>
        <el-descriptions-item label="MAC 地址" :span="2">
          <span class="mono-val accent">{{ formatMac(selectedDevice.mac_address) }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="区域">{{ selectedDevice.region }}</el-descriptions-item>
        <el-descriptions-item label="学校">{{ selectedDevice.school_name }}</el-descriptions-item>
        <el-descriptions-item label="楼宇">{{ selectedDevice.building || '—' }}</el-descriptions-item>
        <el-descriptions-item label="房间号">{{ selectedDevice.room_number || '—' }}</el-descriptions-item>
        <el-descriptions-item label="状态">
          <span class="status-badge" :class="selectedDevice.status">
            <span class="status-dot-sm"></span>
            {{ selectedDevice.status === 'online' ? '在线' : selectedDevice.status === 'offline' ? '离线' : '未知' }}
          </span>
        </el-descriptions-item>
        <el-descriptions-item label="距离">
          <span class="mono-val">{{ selectedDevice.distance_m ? selectedDevice.distance_m + ' 米' : '—' }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="端口" :span="2">
          <span class="mono-val">{{ formatPort(selectedDevice) }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="型号" :span="2">{{ selectedDevice.model || '—' }}</el-descriptions-item>
        <el-descriptions-item label="所属 OLT" :span="2">{{ selectedDevice.olt_location || '—' }}</el-descriptions-item>
        <el-descriptions-item label="备注" :span="2">{{ selectedDevice.notes || '—' }}</el-descriptions-item>
      </el-descriptions>
      <template #footer>
        <el-button type="info" :loading="deviceRefreshing" @click="doRefreshDevice" :disabled="!selectedDevice.olt_id">更新</el-button>
        <el-button type="primary" @click="openEdit">编辑</el-button>
        <el-button type="success" @click="openProvision" :disabled="selectedDevice.status !== 'online' || !selectedDevice.port_id">
          业务下发
        </el-button>
        <el-button @click="detailVisible = false">关闭</el-button>
      </template>
    </el-dialog>

    <!-- 编辑对话框 -->
    <el-dialog v-model="editVisible" title="编辑设备信息" width="460px" destroy-on-close>
      <el-form :model="editForm" label-width="70px">
        <el-form-item label="区域"><el-input v-model="editForm.region" /></el-form-item>
        <el-form-item label="学校"><el-input v-model="editForm.school_name" /></el-form-item>
        <el-form-item label="楼宇"><el-input v-model="editForm.building" /></el-form-item>
        <el-form-item label="房间号"><el-input v-model="editForm.room_number" /></el-form-item>
        <el-form-item label="备注"><el-input v-model="editForm.notes" type="textarea" :rows="2" /></el-form-item>
      </el-form>
      <template #footer>
        <el-button @click="editVisible = false">取消</el-button>
        <el-button type="primary" :loading="editSaving" @click="saveEdit">保存</el-button>
      </template>
    </el-dialog>

    <!-- 业务下发对话框 -->
    <el-dialog v-model="provisionVisible" title="业务下发" width="540px" destroy-on-close>
      <el-alert
        v-if="provisionResult"
        :type="provisionResult.success ? 'success' : 'error'"
        :title="provisionResult.success ? '下发成功' : '下发失败'"
        :description="provisionResult.message"
        :closable="false"
        style="margin-bottom: 16px"
      />
      <el-descriptions :column="2" border v-if="selectedDevice.mac_address">
        <el-descriptions-item label="MAC 地址">
          <span class="mono-val accent">{{ formatMac(selectedDevice.mac_address) }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="端口">
          <span class="mono-val">{{ formatPort(selectedDevice) }}</span>
        </el-descriptions-item>
        <el-descriptions-item label="学校">{{ selectedDevice.school_name || '—' }}</el-descriptions-item>
        <el-descriptions-item label="状态">
          <span class="status-badge" :class="selectedDevice.status">
            <span class="status-dot-sm"></span>
            {{ selectedDevice.status === 'online' ? '在线' : selectedDevice.status === 'offline' ? '离线' : '未知' }}
          </span>
        </el-descriptions-item>
      </el-descriptions>
      <el-divider>将执行的配置</el-divider>
      <div class="cli-block">
        <pre>system-view
interface {{ formatPort(selectedDevice) }}
uni 1 vlan-mode trunk pvid 4094 2000 to 2000 3000 to 3010
port link-type trunk
undo port trunk permit vlan 1
port trunk permit vlan 2000 3000 to 3010 4094
save force</pre>
      </div>
      <template #footer>
        <el-button @click="provisionVisible = false; provisionResult = null">关闭</el-button>
        <el-button
          type="success"
          @click="doProvision"
          :loading="provisionLoading"
          :disabled="selectedDevice.status !== 'online' || !selectedDevice.port_id"
        >
          确认下发
        </el-button>
      </template>
    </el-dialog>
  </div>
</template>

<script setup>
import { ref, onMounted } from 'vue'
import { useRoute } from 'vue-router'
import { ElMessage } from 'element-plus'
import * as deviceApi from '../api/device'

const route = useRoute()

const devices = ref([])
const total = ref(0)
const page = ref(1)
const pageSize = ref(20)
const regions = ref([])
const filters = ref({ region: '', keyword: '', school_name: '', status: '' })

const detailVisible = ref(false)
const selectedDevice = ref({})
const deviceRefreshing = ref(false)

const provisionVisible = ref(false)
const provisionLoading = ref(false)
const provisionResult = ref(null)
const refreshing = ref(false)
const clearing = ref(false)

const editVisible = ref(false)
const editForm = ref({ region: '', school_name: '', building: '', room_number: '', notes: '' })
const editSaving = ref(false)

const checkResultVisible = ref(false)
const checkResult = ref(null)
const checkInProgress = ref(false)

const clearStatus = async () => {
  clearing.value = true
  try {
    await deviceApi.clearAllStatus()
    ElMessage.success('已清空所有设备状态')
    loadDevices()
  } catch {
    ElMessage.error('清空失败')
  } finally {
    clearing.value = false
  }
}

const refreshAllStatus = async () => {
  refreshing.value = true
  checkResultVisible.value = true
  checkInProgress.value = true
  checkResult.value = null
  try {
    const { data } = await deviceApi.refreshAllStatus()
    checkResult.value = {
      success: true,
      total_online: data.total_online,
      total_offline: data.total_offline,
      results: data.results,
      errors: data.errors,
    }
  } catch (error) {
    checkResult.value = { success: false, error: error.response?.data?.detail || '更新失败' }
  } finally {
    checkInProgress.value = false
    refreshing.value = false
  }
}

const formatMac = (mac) => {
  if (!mac) return ''
  const clean = mac.toUpperCase().replace(/[:-]/g, '')
  if (clean.length !== 12) return mac.toLowerCase()
  return clean.substring(0, 4).toLowerCase() + '-' +
         clean.substring(4, 8).toLowerCase() + '-' +
         clean.substring(8, 12).toLowerCase()
}

const formatPort = (device) => {
  if (device.port_id) return `Onu${device.port_id}`
  if (!device.slot_number && !device.port_number) return '—'
  return `Onu${device.slot_number || '?'}/${device.port_number || '?'}`
}

const openDetail = (row) => {
  selectedDevice.value = { ...row }
  provisionResult.value = null
  detailVisible.value = true
}

const doRefreshDevice = async () => {
  deviceRefreshing.value = true
  try {
    const { data } = await deviceApi.refreshDevice(selectedDevice.value.id)
    selectedDevice.value.status = data.status
    selectedDevice.value.distance_m = data.distance_m
    if (data.model) selectedDevice.value.model = data.model
    ElMessage.success(`更新完成：${data.status === 'online' ? '在线' : '离线'}${data.distance_m ? '，距离 ' + data.distance_m + 'm' : ''}`)
    loadDevices()
  } catch (error) {
    ElMessage.error(error.response?.data?.detail || '更新失败')
  } finally {
    deviceRefreshing.value = false
  }
}

const openEdit = () => {
  editForm.value = {
    region: selectedDevice.value.region || '',
    school_name: selectedDevice.value.school_name || '',
    building: selectedDevice.value.building || '',
    room_number: selectedDevice.value.room_number || '',
    notes: selectedDevice.value.notes || '',
  }
  detailVisible.value = false
  editVisible.value = true
}

const saveEdit = async () => {
  editSaving.value = true
  try {
    await deviceApi.updateDevice(selectedDevice.value.id, editForm.value)
    ElMessage.success('保存成功')
    editVisible.value = false
    loadDevices()
  } catch (error) {
    ElMessage.error(error.response?.data?.detail || '保存失败')
  } finally {
    editSaving.value = false
  }
}

const openProvision = () => {
  provisionResult.value = null
  provisionVisible.value = true
}

const doProvision = async () => {
  provisionLoading.value = true
  try {
    const { data } = await deviceApi.provisionService({ device_id: selectedDevice.value.id })
    provisionResult.value = { success: true, message: data.message }
    ElMessage.success(data.message)
  } catch (error) {
    const msg = error.response?.data?.detail || '下发失败'
    provisionResult.value = { success: false, message: msg }
    ElMessage.error(msg)
  } finally {
    provisionLoading.value = false
  }
}

const loadRegions = async () => {
  const { data } = await deviceApi.getRegions()
  regions.value = data
}

const loadDevices = async () => {
  const { data } = await deviceApi.getDevices({
    skip: (page.value - 1) * pageSize.value,
    limit: pageSize.value,
    region: filters.value.region || undefined,
    keyword: filters.value.keyword || undefined,
    school_name: filters.value.school_name || undefined,
    status: filters.value.status || undefined,
  })
  devices.value = data.items
  total.value = data.total
}

const search = () => {
  page.value = 1
  loadDevices()
}

const handleSizeChange = (val) => {
  pageSize.value = val
  page.value = 1
  loadDevices()
}

onMounted(() => {
  if (route.query.school_name) {
    filters.value.keyword = route.query.school_name
  }
  loadRegions()
  loadDevices()
})
</script>

<style scoped>
.device-list {
  padding: 24px;
}

/* 页头 */
.page-header {
  display: flex;
  align-items: flex-end;
  justify-content: space-between;
  margin-bottom: 20px;
}

.page-title-group {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.page-title {
  margin: 0;
  font-size: 22px;
  font-weight: 700;
  color: var(--text-primary);
  letter-spacing: -0.02em;
}

.page-subtitle {
  font-size: 12px;
  color: var(--text-muted);
}

.header-actions {
  display: flex;
  gap: 8px;
}

/* 筛选栏 */
.filter-bar {
  display: flex;
  align-items: center;
  gap: 16px;
  padding: 14px 18px;
  background: var(--bg-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  margin-bottom: 16px;
  flex-wrap: wrap;
}

.filter-group {
  display: flex;
  align-items: center;
  gap: 8px;
}

.filter-label {
  font-size: 11px;
  color: var(--text-muted);
  letter-spacing: 0.04em;
  white-space: nowrap;
}

/* 数据面板 */
.data-panel {
  background: var(--bg-card);
  border: 1px solid var(--border-default);
  border-radius: var(--radius-lg);
  overflow: hidden;
}

.data-stats {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 12px 16px;
  border-bottom: 1px solid var(--border-subtle);
}

.data-total {
  font-size: 12px;
  color: var(--text-muted);
}

.data-total strong {
  color: var(--text-primary);
  font-variant-numeric: tabular-nums;
}

.status-legend {
  display: flex;
  gap: 16px;
}

.legend-item {
  display: flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  color: var(--text-muted);
}

.led {
  width: 7px;
  height: 7px;
  border-radius: 50%;
  flex-shrink: 0;
}

.led.online  { background: var(--success); box-shadow: 0 0 5px var(--success); }
.led.offline { background: var(--danger); }
.led.unknown { background: var(--text-muted); }

/* 表格中的元素 */
.row-index {
  font-family: var(--font-mono);
  font-size: 11px;
  color: var(--text-muted);
}

.mac-link {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--accent);
  cursor: pointer;
  letter-spacing: 0.02em;
  transition: color 0.15s;
}

.mac-link:hover {
  color: #00f0cc;
  text-decoration: underline;
}

.status-badge {
  display: inline-flex;
  align-items: center;
  gap: 5px;
  font-size: 11px;
  font-weight: 600;
  padding: 2px 7px;
  border-radius: 10px;
  white-space: nowrap;
}

.status-badge.online {
  background: var(--success-dim);
  color: var(--success);
  border: 1px solid rgba(34,197,94,0.25);
}

.status-badge.offline {
  background: var(--danger-dim);
  color: var(--danger);
  border: 1px solid rgba(239,68,68,0.25);
}

.status-badge.unknown {
  background: rgba(255,255,255,0.04);
  color: var(--text-muted);
  border: 1px solid var(--border-subtle);
}

.status-dot-sm {
  width: 5px;
  height: 5px;
  border-radius: 50%;
  background: currentColor;
  flex-shrink: 0;
}

.online .status-dot-sm { box-shadow: 0 0 4px currentColor; }

.mono-val {
  font-family: var(--font-mono);
  font-size: 12px;
  color: var(--text-secondary);
}

.mono-val.accent { color: var(--accent); font-size: 13px; }

/* 分页 */
.pagination-wrap {
  display: flex;
  justify-content: flex-end;
  padding: 14px 16px;
  border-top: 1px solid var(--border-subtle);
}

/* 对话框内元素 */
.dialog-loading {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 16px;
  padding: 48px 0;
  color: var(--text-muted);
  font-size: 13px;
}

.loading-spinner {
  width: 32px;
  height: 32px;
  border: 2px solid var(--border-default);
  border-top-color: var(--accent);
  border-radius: 50%;
  animation: spin 0.8s linear infinite;
}

@keyframes spin { to { transform: rotate(360deg); } }

.result-stats {
  display: flex;
  gap: 32px;
  padding: 16px 0;
  margin-bottom: 16px;
  border-bottom: 1px solid var(--border-subtle);
}

.result-stat {
  display: flex;
  flex-direction: column;
  gap: 4px;
}

.rs-val {
  font-family: var(--font-mono);
  font-size: 28px;
  font-weight: 700;
  line-height: 1;
}

.rs-val.online  { color: var(--success); }
.rs-val.offline { color: var(--danger); }
.rs-val.warn    { color: var(--warning); }

.rs-label {
  font-size: 11px;
  color: var(--text-muted);
  letter-spacing: 0.04em;
}

/* CLI 预览块 */
.cli-block {
  background: #0a0e1a;
  border: 1px solid var(--border-default);
  border-radius: var(--radius-md);
  padding: 14px 16px;
  overflow-x: auto;
}

.cli-block pre {
  margin: 0;
  font-family: var(--font-mono);
  font-size: 12px;
  color: #a3e6d8;
  line-height: 1.7;
  white-space: pre;
}
</style>
