<template>
  <div class="alarm-mgmt-page">
    <!-- 统计条 -->
    <header class="am-stats">
      <div class="am-stat">
        <span class="am-stat-label">当前活跃</span>
        <span class="am-stat-value" :class="{ 'am-danger': counts.active > 0 }"><b>{{ counts.active }}</b></span>
      </div>
      <div class="am-stat-sep" aria-hidden="true" />
      <div class="am-stat">
        <span class="am-stat-label">今日新增</span>
        <span class="am-stat-value"><b>{{ counts.today }}</b></span>
      </div>
      <div class="am-stat">
        <span class="am-stat-label">已恢复</span>
        <span class="am-stat-value"><b>{{ counts.cleared }}</b></span>
      </div>
      <div class="am-stat">
        <span class="am-stat-label">涉及车辆</span>
        <span class="am-stat-value"><b>{{ counts.cars }}</b></span>
      </div>

      <div class="am-stats-actions">
        <span class="am-live" :class="{ 'is-live': autoRefresh }" @click="autoRefresh = !autoRefresh">
          {{ autoRefresh ? '自动刷新' : '已暂停' }}
        </span>
        <el-button :icon="Refresh" :loading="loading" @click="reload">刷新</el-button>
      </div>
    </header>

    <el-alert
      v-if="!online"
      type="warning"
      show-icon
      :closable="false"
      class="am-offline"
      title="SimpleLite 未连接：以下为平台最近一次采集的报警快照。"
      :description="lastSyncAt ? `最近同步：${formatTime(lastSyncAt)}` : '暂无同步记录'"
    />

    <!-- 筛选条 -->
    <div class="am-toolbar">
      <el-input v-model="search" clearable placeholder="搜索车辆 / 报警信息" class="am-search" :prefix-icon="Search" />
      <el-select v-model="carFilter" clearable filterable placeholder="车辆" class="am-car">
        <el-option v-for="c in carOptions" :key="c.value" :label="c.label" :value="c.value" />
      </el-select>
      <el-select v-model="levelFilter" clearable placeholder="级别" class="am-level">
        <el-option label="严重" :value="'danger'" />
        <el-option label="警告" :value="'warning'" />
        <el-option label="提示" :value="'info'" />
      </el-select>
      <el-date-picker
        v-model="dateRange"
        type="daterange"
        value-format="YYYY-MM-DD"
        start-placeholder="首次起"
        end-placeholder="首次止"
        class="am-date"
        :shortcuts="dateShortcuts"
        unlink-panels
      />
      <span class="am-count">{{ filteredRows.length }} / {{ rows.length }}</span>
    </div>

    <!-- 快捷芯片 -->
    <div class="am-chips" role="tablist">
      <button
        v-for="chip in statusChips"
        :key="chip.key"
        type="button"
        class="am-chip"
        :class="{ 'is-active': quickStatus === chip.key }"
        @click="quickStatus = chip.key"
      >
        {{ chip.label }}<b>{{ chip.count }}</b>
      </button>
    </div>

    <!-- 报警表 -->
    <div v-loading="loading" class="am-table-wrap">
      <el-table
        :data="filteredRows"
        stripe
        height="100%"
        highlight-current-row
        :row-class-name="rowClassName"
        empty-text="暂无匹配报警"
      >
        <el-table-column label="车辆" width="140" show-overflow-tooltip>
          <template #default="{ row }">
            <span>{{ row.carName || `#${row.carId}` }}</span>
          </template>
        </el-table-column>
        <el-table-column label="级别" width="90" align="center">
          <template #default="{ row }">
            <el-tag size="small" :type="levelTagType(row.level)" effect="plain">{{ levelLabel(row.level) }}</el-tag>
          </template>
        </el-table-column>
        <el-table-column label="报警信息" min-width="200" show-overflow-tooltip>
          <template #default="{ row }">
            <span class="am-info">{{ row.info || '—' }}</span>
          </template>
        </el-table-column>
        <el-table-column label="状态" width="96" align="center">
          <template #default="{ row }">
            <el-tag size="small" :type="row.status === 'active' ? 'danger' : 'info'" effect="plain">
              {{ row.status === 'active' ? '活跃' : '已恢复' }}
            </el-tag>
          </template>
        </el-table-column>
        <el-table-column label="首次触发" width="160" sortable :sort-method="(a, b) => sortByTime(a.firstAt, b.firstAt)">
          <template #default="{ row }">{{ formatTime(row.firstAt) }}</template>
        </el-table-column>
        <el-table-column label="最近更新" width="160">
          <template #default="{ row }">{{ formatTime(row.lastAt) }}</template>
        </el-table-column>
        <el-table-column label="恢复时间" width="160">
          <template #default="{ row }">{{ formatTime(row.resolvedAt) }}</template>
        </el-table-column>
        <el-table-column label="持续时长" width="110" align="right">
          <template #default="{ row }">{{ durationText(row) }}</template>
        </el-table-column>
        <el-table-column label="操作" width="90" fixed="right">
          <template #default="{ row }">
            <el-button link type="primary" size="small" @click.stop="locateOnMap(row)">定位</el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>

    <p class="am-footnote">
      报警来自车体状态（车体_AlarmInfo / 车体_AlarmLevel），由平台按车对帐记录：出现即开、消失即恢复，历史长期保留。
    </p>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, onUnmounted, ref } from 'vue'
import { useRouter } from 'vue-router'
import { ElMessage } from 'element-plus'
import { Refresh, Search } from '@element-plus/icons-vue'
import { fetchAlarmFeed } from '@/api/alarm'
import type { VehicleAlarm } from '@/types/alarm'
import { dateShortcuts, formatTime, isToday, parseTime, sortByTime } from '@/utils/dateTime'

type QuickKey = 'all' | 'active' | 'cleared'
type TagType = 'success' | 'warning' | 'danger' | 'info' | 'primary'
type LevelKey = 'danger' | 'warning' | 'info'

const router = useRouter()

const rows = ref<VehicleAlarm[]>([])
const loading = ref(false)
const autoRefresh = ref(true)
const online = ref(true)
const lastSyncAt = ref<string | null>(null)

const search = ref('')
const carFilter = ref<number | null>(null)
const levelFilter = ref<LevelKey | null>(null)
const quickStatus = ref<QuickKey>('all')
const dateRange = ref<[string, string] | null>(null)

let pollTimer: ReturnType<typeof setInterval> | null = null

function levelKeyOf(level: number): LevelKey {
  if (level >= 2) return 'danger'
  if (level === 1) return 'warning'
  return 'info'
}
function levelLabel(level: number): string {
  return { danger: '严重', warning: '警告', info: '提示' }[levelKeyOf(level)]
}
function levelTagType(level: number): TagType {
  return levelKeyOf(level)
}

function durationText(row: VehicleAlarm): string {
  let secs = row.durationSecs ?? null
  if (secs == null && row.status === 'active') {
    const t = parseTime(row.firstAt)
    if (t != null) secs = Math.max(0, Math.round((Date.now() - t) / 1000))
  }
  if (secs == null) return '—'
  if (secs < 60) return `${secs}秒`
  const m = Math.floor(secs / 60)
  const s = secs % 60
  if (m < 60) return s ? `${m}分${s}秒` : `${m}分`
  const h = Math.floor(m / 60)
  return `${h}时${m % 60}分`
}

function inDateRange(row: VehicleAlarm): boolean {
  if (!dateRange.value) return true
  const t = parseTime(row.firstAt)
  if (t == null) return false
  const [from, to] = dateRange.value
  return t >= Date.parse(`${from}T00:00:00`) && t <= Date.parse(`${to}T23:59:59.999`)
}

const carOptions = computed(() => {
  const map = new Map<number, string>()
  for (const r of rows.value) if (!map.has(r.carId)) map.set(r.carId, r.carName || `#${r.carId}`)
  return [...map.entries()].map(([value, label]) => ({ value, label })).sort((a, b) => a.value - b.value)
})

const filteredRows = computed(() => {
  const q = search.value.trim().toLowerCase()
  const tokens = q ? q.split(/\s+/).filter(Boolean) : []
  return rows.value.filter((row) => {
    if (quickStatus.value === 'active' && row.status !== 'active') return false
    if (quickStatus.value === 'cleared' && row.status !== 'cleared') return false
    if (carFilter.value != null && row.carId !== carFilter.value) return false
    if (levelFilter.value && levelKeyOf(row.level) !== levelFilter.value) return false
    if (!inDateRange(row)) return false
    if (!tokens.length) return true
    const hay = [row.carName, String(row.carId), row.info, String(row.level)].join(' ').toLowerCase()
    return tokens.every((tok) => hay.includes(tok))
  })
})

const counts = computed(() => ({
  active: rows.value.filter((r) => r.status === 'active').length,
  cleared: rows.value.filter((r) => r.status === 'cleared').length,
  today: rows.value.filter((r) => isToday(r.firstAt)).length,
  cars: new Set(rows.value.filter((r) => r.status === 'active').map((r) => r.carId)).size
}))

const statusChips = computed(() => [
  { key: 'all' as const, label: '全部', count: rows.value.length },
  { key: 'active' as const, label: '活跃', count: counts.value.active },
  { key: 'cleared' as const, label: '已恢复', count: counts.value.cleared }
])

function rowClassName({ row }: { row: VehicleAlarm }) {
  return row.status === 'active' ? 'is-active-alarm-row' : ''
}

function locateOnMap(row: VehicleAlarm) {
  if (!row.carId) { ElMessage.info('无车辆信息'); return }
  void router.push({ path: '/admin/map-monitor', query: { focusKind: 'car', focusId: String(row.carId) } })
}

async function reload() {
  loading.value = true
  try {
    const feed = await fetchAlarmFeed(2000)
    rows.value = feed.alarms
    online.value = feed.online
    lastSyncAt.value = feed.lastSyncAt
  } catch (err) {
    ElMessage.error(`加载报警失败：${(err as Error).message}`)
  } finally {
    loading.value = false
  }
}

onMounted(() => {
  void reload()
  pollTimer = setInterval(() => { if (autoRefresh.value) void reload() }, 6000)
})

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

<style scoped>
.alarm-mgmt-page {
  display: flex;
  flex-direction: column;
  gap: 10px;
  height: calc(100vh - 56px - 36px - 32px);
  min-height: 0;
  color: var(--mg-text-light);
}

.am-stats {
  flex: none;
  display: flex;
  align-items: center;
  gap: 26px;
  min-height: 54px;
  padding: 8px 18px;
  border-radius: 10px;
  background: rgba(var(--mg-bg-card-rgb), 0.94);
  border: 1px solid var(--mg-veil-border);
  overflow-x: auto;
}
.am-stat { display: flex; flex-direction: column; gap: 3px; min-width: 56px; }
.am-stat-label { font-size: 11px; color: var(--mg-text-muted); white-space: nowrap; }
.am-stat-value {
  font-family: var(--mg-font-mono);
  font-variant-numeric: tabular-nums;
  font-size: 17px;
  font-weight: 650;
  line-height: 1.1;
}
.am-stat-value.am-danger b { color: var(--mg-status-danger); }
.am-stat-sep { width: 1px; height: 30px; background: var(--mg-veil-border); flex: none; }
.am-stats-actions { margin-left: auto; display: flex; align-items: center; gap: 10px; flex: none; }
.am-live {
  font-size: 12px;
  color: var(--mg-text-muted);
  cursor: pointer;
  padding: 2px 10px;
  border-radius: 999px;
  border: 1px solid var(--mg-veil-border);
  user-select: none;
}
.am-live.is-live { color: var(--mg-status-success); }

.am-offline { flex: none; }

.am-toolbar {
  flex: none;
  display: flex;
  align-items: center;
  gap: 10px;
  flex-wrap: wrap;
  padding: 8px 12px;
  border-radius: 10px;
  background: rgba(var(--mg-bg-card-rgb), 0.94);
  border: 1px solid var(--mg-veil-border);
}
.am-search { width: min(260px, 100%); }
.am-car { width: 150px; }
.am-level { width: 120px; }
.am-date { width: 250px; }
.am-count { margin-left: auto; font-size: 12px; color: var(--mg-text-muted); font-variant-numeric: tabular-nums; }

.am-chips { flex: none; display: flex; gap: 8px; flex-wrap: wrap; }
.am-chip {
  appearance: none;
  border: 1px solid var(--mg-veil-border);
  background: rgba(var(--mg-bg-card-rgb), 0.9);
  color: var(--mg-text-muted);
  border-radius: 999px;
  padding: 4px 12px;
  font-size: 12px;
  cursor: pointer;
  display: inline-flex;
  align-items: center;
  gap: 6px;
  transition: background 0.15s ease, color 0.15s ease, border-color 0.15s ease;
}
.am-chip b { font-family: var(--mg-font-mono); font-variant-numeric: tabular-nums; color: var(--mg-text-light); }
.am-chip:hover { color: var(--mg-text-light); background: var(--mg-veil-2); }
.am-chip.is-active {
  color: var(--mg-primary);
  border-color: rgba(var(--mg-primary-rgb), 0.45);
  background: rgba(var(--mg-primary-rgb), 0.12);
}

.am-table-wrap {
  flex: 1 1 0;
  min-height: 0;
  border-radius: 10px;
  background: rgba(var(--mg-bg-card-rgb), 0.94);
  border: 1px solid var(--mg-veil-border);
  overflow: hidden;
  padding: 4px;
}
.am-table-wrap :deep(.is-active-alarm-row) { --el-table-tr-bg-color: rgba(239, 68, 68, 0.08); }
.am-info { color: var(--mg-status-danger); }

.am-footnote { flex: none; margin: 0; font-size: 12px; color: var(--mg-text-muted); }

@media (max-width: 960px) {
  .am-search, .am-date { width: 100%; }
}
</style>

