<template>
  <div
    class="vehicle-health-card"
    :class="cardClass"
    @click="onCardClick"
    @dblclick="onCardDblClick"
  >
    <div class="battery-strip">
      <el-progress
        :percentage="batteryPct"
        :stroke-width="4"
        :show-text="false"
        :color="batteryColor"
      />
    </div>

    <div class="card-head">
      <div class="title-block">
        <span class="vid">{{ vehicle.id }}</span>
        <span class="vname" :title="vehicle.name">{{ vehicle.name }}</span>
      </div>
      <div class="head-actions" @click.stop>
        <el-dropdown trigger="click" @command="onMaintenanceCommand">
          <el-button size="small" text :icon="MoreFilled" />
          <template #dropdown>
            <el-dropdown-menu>
              <el-dropdown-item command="online">上线</el-dropdown-item>
              <el-dropdown-item command="offline">下线维护</el-dropdown-item>
              <el-dropdown-item command="repair">现场检修</el-dropdown-item>
              <el-dropdown-item command="blown" divided>返厂检修</el-dropdown-item>
            </el-dropdown-menu>
          </template>
        </el-dropdown>
        <el-switch
          :model-value="switchOn"
          size="small"
          :disabled="!canWrite"
          inline-prompt
          active-text="开"
          inactive-text="关"
          @change="(v: string | number | boolean) => onToggleMaintenance(Boolean(v))"
        />
      </div>
    </div>

    <div class="card-body">
      <div class="thumb">
        <el-icon :size="36"><Van /></el-icon>
      </div>
      <div class="metrics">
        <div class="metric-row">
          <span class="label">IP</span>
          <span class="value mono">{{ vehicle.ip ?? '—' }}</span>
        </div>
        <div class="metric-row">
          <span class="label">延迟</span>
          <span class="value" :class="latencyClass">{{ latencyLabel }}</span>
        </div>
        <div class="metric-row">
          <span class="label">故障率</span>
          <span class="value" :class="faultClass">{{ faultLabel }}</span>
        </div>
        <div class="metric-row">
          <span class="label">群组</span>
          <span class="value">{{ vehicle.group ?? '—' }}</span>
        </div>
        <div class="metric-row">
          <span class="label">状态</span>
          <span class="value">{{ vehicle.lstatus ?? stateLabel }}</span>
        </div>
      </div>
    </div>

    <div class="icon-grid">
      <div class="icon-cell" title="CPU">
        <el-icon><Cpu /></el-icon>
        <span>{{ cpuLabel }}</span>
      </div>
      <div class="icon-cell" title="内存">
        <el-icon><Coin /></el-icon>
        <span>{{ memLabel }}</span>
      </div>
      <div class="icon-cell" title="报警">
        <el-icon :class="{ 'is-alarm': vehicle.isAlarmActive }"><Warning /></el-icon>
        <span>{{ vehicle.isAlarmActive ? '报警' : '正常' }}</span>
      </div>
      <div class="icon-cell" title="连接">
        <el-icon :class="{ 'is-down': vehicle.reachable === false }"><Connection /></el-icon>
        <span>{{ vehicle.reachable === false ? '不可达' : '可达' }}</span>
      </div>
    </div>

    <div class="card-foot">
      <span>电量 {{ batteryPct }}%</span>
      <span class="hint">双击打开车载界面</span>
    </div>
  </div>
</template>

<script setup lang="ts">
import { computed } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Van, Cpu, Coin, Warning, Connection, MoreFilled } from '@element-plus/icons-vue'
import type { VehicleCardModel } from '@/types/car'
import type { VehicleMaintenanceMode } from '@/api/vehicleOps'
import { openOnboardWeb, setVehicleMaintenance } from '@/api/vehicleOps'

const props = defineProps<{
  vehicle: VehicleCardModel
  selected?: boolean
  canWrite?: boolean
}>()

const emit = defineEmits<{
  select: [id: string]
  maintenanceChanged: []
}>()

const stateLabels: Record<string, string> = {
  idle: '空闲',
  running: '运行',
  charging: '充电',
  paused: '暂停',
  fault: '故障',
  offline: '离线'
}

const stateLabel = computed(() => stateLabels[props.vehicle.state] ?? props.vehicle.state)

const batteryPct = computed(() => {
  const raw = props.vehicle.batterySoc ?? 0
  const pct = raw > 1 ? raw : raw * 100
  return Math.max(0, Math.min(100, Math.round(pct)))
})

const batteryColor = computed(() => {
  const p = batteryPct.value
  if (p < 20) return '#f56c6c'
  if (p < 50) return '#e6a23c'
  return '#67c23a'
})

const switchOn = computed(() => props.vehicle.maintenanceMode === 'online')

const cardClass = computed(() => ({
  'is-selected': props.selected,
  'is-alarm': props.vehicle.isAlarmActive,
  'is-offline': props.vehicle.maintenanceMode === 'offline' || props.vehicle.state === 'offline',
  'is-maintenance': props.vehicle.maintenanceMode === 'repair' || props.vehicle.maintenanceMode === 'blown',
  'is-unreachable': props.vehicle.reachable === false
}))

const latencyLabel = computed(() => {
  const ms = props.vehicle.latencyMs
  if (ms == null) return '—'
  if (props.vehicle.reachable === false) return '超时'
  return `${ms} ms`
})

const latencyClass = computed(() => {
  const ms = props.vehicle.latencyMs
  if (props.vehicle.reachable === false) return 'danger'
  if (ms != null && ms > 80) return 'warn'
  return ''
})

const faultLabel = computed(() => {
  const v = props.vehicle.faultRatePercent
  if (v == null) return '—'
  return `${v.toFixed(2)}%`
})

const faultClass = computed(() => {
  const v = props.vehicle.faultRatePercent ?? 0
  if (v >= 5) return 'danger'
  if (v >= 1) return 'warn'
  return ''
})

const cpuLabel = computed(() => {
  const v = props.vehicle.cpuPercent
  return v != null ? `${Math.round(v)}%` : '—'
})

const memLabel = computed(() => {
  const v = props.vehicle.memPercent
  return v != null ? `${Math.round(v)}%` : '—'
})

function onCardClick() {
  emit('select', props.vehicle.id)
}

function onCardDblClick(e: MouseEvent) {
  const target = e.target as HTMLElement
  if (target.closest('.head-actions')) return
  openOnboardWeb(props.vehicle.onboardUrl, props.vehicle.ip)
}

async function applyMaintenance(mode: VehicleMaintenanceMode) {
  const rawId = props.vehicle.rawId ?? parseInt(props.vehicle.id.replace(/\D/g, ''), 10)
  if (!Number.isFinite(rawId)) return
  const ok = await setVehicleMaintenance(rawId, mode)
  if (ok) {
    ElMessage.success('维护状态已更新')
    emit('maintenanceChanged')
  } else {
    ElMessage.error('维护操作失败')
  }
}

async function onToggleMaintenance(on: boolean) {
  if (!props.canWrite) return
  const mode: VehicleMaintenanceMode = on ? 'online' : 'offline'
  try {
    await ElMessageBox.confirm(
      on ? '确认将车辆上线？' : '确认将车辆下线维护？',
      '维护确认',
      { type: 'warning', confirmButtonText: '确定', cancelButtonText: '取消' }
    )
    await applyMaintenance(mode)
  } catch {
    /* cancelled */
  }
}

async function onMaintenanceCommand(cmd: string) {
  if (!props.canWrite) return
  const mode = cmd as VehicleMaintenanceMode
  if (mode === 'blown') {
    try {
      await ElMessageBox.confirm('返厂检修将停止调度并清空站点，确认？', '危险操作', {
        type: 'error',
        confirmButtonText: '确定',
        cancelButtonText: '取消'
      })
      await applyMaintenance(mode)
    } catch {
      /* cancelled */
    }
    return
  }
  if (mode === 'repair') {
    try {
      await ElMessageBox.confirm('现场检修：不调度但仍刷新状态，确认？', '维护确认', {
        type: 'warning'
      })
      await applyMaintenance(mode)
    } catch {
      /* cancelled */
    }
    return
  }
  await applyMaintenance(mode)
}
</script>

<style scoped>
.vehicle-health-card {
  border: 1px solid var(--el-border-color-light);
  border-radius: 8px;
  background: var(--el-bg-color);
  overflow: hidden;
  cursor: pointer;
  transition: box-shadow 0.15s ease, border-color 0.15s ease;
}

.vehicle-health-card:hover {
  box-shadow: 0 2px 12px rgba(0, 0, 0, 0.08);
}

.vehicle-health-card.is-selected {
  border-color: var(--el-color-primary);
  box-shadow: 0 0 0 1px var(--el-color-primary-light-7);
}

.vehicle-health-card.is-alarm {
  border-color: var(--el-color-danger-light-5);
}

.vehicle-health-card.is-offline,
.vehicle-health-card.is-maintenance {
  border-color: var(--el-color-warning-light-5);
}

.vehicle-health-card.is-unreachable {
  opacity: 0.85;
}

.battery-strip {
  height: 4px;
}

.card-head {
  display: flex;
  align-items: center;
  justify-content: space-between;
  padding: 8px 10px 4px;
  gap: 8px;
}

.title-block {
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 2px;
}

.vid {
  font-size: 12px;
  color: var(--el-text-color-secondary);
  font-family: ui-monospace, monospace;
}

.vname {
  font-weight: 600;
  font-size: 14px;
  white-space: nowrap;
  overflow: hidden;
  text-overflow: ellipsis;
}

.head-actions {
  display: flex;
  align-items: center;
  gap: 4px;
  flex-shrink: 0;
}

.card-body {
  display: flex;
  gap: 10px;
  padding: 4px 10px 8px;
}

.thumb {
  width: 56px;
  height: 56px;
  border-radius: 6px;
  background: var(--el-fill-color-light);
  display: flex;
  align-items: center;
  justify-content: center;
  color: var(--el-text-color-secondary);
  flex-shrink: 0;
}

.metrics {
  flex: 1;
  min-width: 0;
  display: flex;
  flex-direction: column;
  gap: 4px;
  font-size: 12px;
}

.metric-row {
  display: flex;
  justify-content: space-between;
  gap: 8px;
}

.metric-row .label {
  color: var(--el-text-color-secondary);
}

.metric-row .value {
  font-weight: 500;
}

.metric-row .value.mono {
  font-family: ui-monospace, monospace;
}

.metric-row .value.danger {
  color: var(--el-color-danger);
}

.metric-row .value.warn {
  color: var(--el-color-warning);
}

.icon-grid {
  display: grid;
  grid-template-columns: repeat(4, 1fr);
  gap: 4px;
  padding: 0 10px 8px;
}

.icon-cell {
  display: flex;
  flex-direction: column;
  align-items: center;
  gap: 2px;
  font-size: 10px;
  color: var(--el-text-color-secondary);
}

.icon-cell .is-alarm {
  color: var(--el-color-danger);
}

.icon-cell .is-down {
  color: var(--el-color-info);
}

.card-foot {
  display: flex;
  justify-content: space-between;
  padding: 6px 10px;
  font-size: 11px;
  color: var(--el-text-color-secondary);
  background: var(--el-fill-color-lighter);
  border-top: 1px solid var(--el-border-color-lighter);
}

.card-foot .hint {
  opacity: 0.7;
}
</style>
