<template>
  <div class="vehicle-hub-page">
    <el-tabs v-model="activeTab" class="hub-tabs">
      <el-tab-pane name="overview" label="运维总览">
        <div class="overview-pane">
          <div class="hub-toolbar">
            <div class="stats-row">
              <div class="stat">
                <span class="num">{{ totalCount }}</span>
                <span class="label">总数</span>
              </div>
              <div class="stat online">
                <span class="num">{{ onlineCount }}</span>
                <span class="label">在线</span>
              </div>
              <div class="stat warn">
                <span class="num">{{ maintenanceCount }}</span>
                <span class="label">维护中</span>
              </div>
              <div class="stat danger">
                <span class="num">{{ alarmCount }}</span>
                <span class="label">报警</span>
              </div>
              <div class="stat muted">
                <span class="num">{{ unreachableCount }}</span>
                <span class="label">不可达</span>
              </div>
            </div>

            <div class="filters-row">
              <el-input
                v-model="search"
                size="small"
                clearable
                placeholder="搜索 ID / 名称 / IP"
                class="search-input"
                :prefix-icon="Search"
              />
              <el-select v-model="filterState" size="small" clearable placeholder="状态" class="filter-select">
                <el-option v-for="opt in stateOptions" :key="opt.value" :label="opt.label" :value="opt.value" />
              </el-select>
              <el-select v-model="filterFleet" size="small" clearable placeholder="车队" class="filter-select fleet-filter">
                <el-option v-for="g in fleetFilterOptions" :key="g.value" :label="g.label" :value="g.value" />
              </el-select>
              <el-dropdown :disabled="!canWrite || !selectedIds.length" @command="onBatchCommand">
                <el-button size="small" :disabled="!canWrite || !selectedIds.length">
                  批量维护
                  <el-icon class="el-icon--right"><ArrowDown /></el-icon>
                </el-button>
                <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-menu>
                </template>
              </el-dropdown>
              <el-button size="small" :icon="Refresh" :loading="loading || healthLoading" @click="refreshAll">
                刷新
              </el-button>
              <el-radio-group
                v-model="viewMode"
                size="small"
                class="view-toggle"
                @change="viewModeTouched = true"
              >
                <el-radio-button value="grid">卡片</el-radio-button>
                <el-radio-button value="list">列表</el-radio-button>
              </el-radio-group>
            </div>
          </div>

          <div
            v-loading="loading && !cardModels.length"
            class="vehicle-scroll"
            :class="viewMode === 'list' ? 'is-list' : 'is-grid'"
          >
            <div v-if="viewMode === 'list' && sortedCards.length" class="list-head">
              <span>车辆</span>
              <span>状态</span>
              <span>电量</span>
              <span>IP</span>
              <span>延迟</span>
              <span>故障率</span>
              <span>群组</span>
              <span class="head-actions">操作</span>
            </div>

            <template v-if="viewMode === 'grid'">
              <VehicleHealthCard
                v-for="v in sortedCards"
                :key="v.id"
                :vehicle="v"
                :selected="selectedId === v.id"
                :can-write="canWrite"
                @select="selectedId = $event"
                @maintenance-changed="refreshAll"
              />
            </template>
            <template v-else>
              <VehicleHealthRow
                v-for="v in sortedCards"
                :key="v.id"
                :vehicle="v"
                :selected="selectedId === v.id"
                :can-write="canWrite"
                @select="selectedId = $event"
                @maintenance-changed="refreshAll"
              />
            </template>

            <el-empty v-if="!sortedCards.length && !loading" description="无匹配车辆" />
          </div>

          <FleetAllocationPanel :cars="cardModels" :can-write="canWrite" @saved="onFleetSaved" />

          <p class="footnote">
            延迟 = 本机到车辆 WatchDog(:9776) 的 TCP 往返；故障率 = 报警占用时长 ÷ 自上线以来运行时长（SimpleLite 进程内累计）
          </p>
        </div>
      </el-tab-pane>

      <el-tab-pane name="ota" label="OTA" lazy>
        <div class="ota-pane">
          <OtaWorkbenchView :can-write="canWrite" />
        </div>
      </el-tab-pane>
    </el-tabs>
  </div>
</template>

<script setup lang="ts">
import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { ElMessage, ElMessageBox } from 'element-plus'
import { Search, Refresh, ArrowDown } from '@element-plus/icons-vue'
import VehicleHealthCard from '@/components/fleet/VehicleHealthCard.vue'
import VehicleHealthRow from '@/components/fleet/VehicleHealthRow.vue'
import FleetAllocationPanel from '@/components/fleet/FleetAllocationPanel.vue'
import OtaWorkbenchView from '@/views/shared/ota/OtaWorkbenchView.vue'
import { useVehicleHub } from '@/composables/useVehicleHub'
import { useFleetGroups } from '@/composables/useFleetGroups'
import { setVehicleMaintenance, type VehicleMaintenanceMode } from '@/api/vehicleOps'
import type { CarState, VehicleCardModel } from '@/types/car'
import { useAuthStore } from '@/stores/auth'

const auth = useAuthStore()
const canWrite = computed(() => {
  if (auth.scope === 'Platform') return true
  const ops = auth.effectivePermissions?.allowedOps ?? []
  return ops.includes('*') || ops.some((o) => o === 'ops.ota' || o.startsWith('ops.ota.'))
})

// Tab 与 URL ?tab= 同步，支持深链接（旧 /config/vehicle、/config/fleet 已下线，统一进车辆运维）。
const route = useRoute()
const router = useRouter()
const TAB_NAMES = ['overview', 'ota'] as const
type TabName = (typeof TAB_NAMES)[number]
const LEGACY_TABS = new Set(['maintenance', 'fleet'])
function readTab(): TabName {
  const q = route.query.tab
  if (typeof q === 'string' && LEGACY_TABS.has(q)) return 'ota'
  return typeof q === 'string' && (TAB_NAMES as readonly string[]).includes(q) ? (q as TabName) : 'overview'
}
const activeTab = ref<TabName>(readTab())
watch(
  activeTab,
  (t) => {
    if (route.query.tab !== t) router.replace({ query: { ...route.query, tab: t } })
  },
  { immediate: true }
)
watch(() => route.query.tab, () => {
  const next = readTab()
  if (next !== activeTab.value) activeTab.value = next
})

const {
  cardModels,
  loading,
  healthLoading,
  selectedId,
  totalCount,
  onlineCount,
  maintenanceCount,
  alarmCount,
  unreachableCount,
  refreshAll
} = useVehicleHub()

const { groups: fleetGroups, reload: reloadFleetGroups, fleetNameForCarId, regionForCarId } = useFleetGroups()
onMounted(() => void reloadFleetGroups())

const DENSE_THRESHOLD = 12
const viewMode = ref<'grid' | 'list'>('grid')
const viewModeTouched = ref(false)

const search = ref('')
const filterState = ref<CarState | ''>('')
const filterFleet = ref('')

const stateOptions: { value: CarState; label: string }[] = [
  { value: 'idle', label: '空闲' },
  { value: 'running', label: '运行' },
  { value: 'charging', label: '充电' },
  { value: 'paused', label: '暂停' },
  { value: 'fault', label: '故障' },
  { value: 'offline', label: '离线' }
]

const fleetFilterOptions = computed(() =>
  fleetGroups.value.map((g) => ({
    value: g.id,
    label: g.region ? `${g.name}（${g.region}）` : g.name || g.id
  }))
)

function onFleetSaved() {
  void reloadFleetGroups(true)
}

function matchesFleetFilter(carId: string): boolean {
  if (!filterFleet.value) return true
  const fleet = fleetGroups.value.find((g) => g.id === filterFleet.value)
  return fleet ? fleet.carIds.includes(carId) : false
}

const filteredCards = computed(() => {
  const q = search.value.trim().toLowerCase()
  const tokens = q ? q.split(/\s+/).filter(Boolean) : []
  return cardModels.value.filter((c) => {
    if (filterState.value && c.state !== filterState.value) return false
    if (!matchesFleetFilter(c.id)) return false
    if (!tokens.length) return true
    const fleetName = fleetNameForCarId(c.id)
    const region = regionForCarId(c.id)
    const hay = [c.id, c.name, c.ip, c.group, fleetName, region, c.lstatus].filter(Boolean).join(' ').toLowerCase()
    return tokens.every((t) => hay.includes(t))
  })
})

function vehicleSortPriority(v: VehicleCardModel): number {
  if (v.isAlarmActive) return 0
  if (v.reachable === false) return 1
  if (v.state === 'fault') return 2
  if (v.maintenanceMode && v.maintenanceMode !== 'online') return 3
  if (v.state === 'running') return 4
  if (v.state === 'charging') return 5
  return 6
}

const sortedCards = computed(() =>
  [...filteredCards.value].sort((a, b) => {
    const d = vehicleSortPriority(a) - vehicleSortPriority(b)
    return d !== 0 ? d : a.name.localeCompare(b.name, 'zh-CN')
  })
)

watch(
  () => sortedCards.value.length,
  (n) => {
    if (viewModeTouched.value) return
    viewMode.value = n > DENSE_THRESHOLD ? 'list' : 'grid'
  },
  { immediate: true }
)

const selectedIds = computed(() => (selectedId.value ? [selectedId.value] : []))

async function onBatchCommand(cmd: string) {
  const mode = cmd as VehicleMaintenanceMode
  const targets = sortedCards.value.filter((c) => selectedId.value ? c.id === selectedId.value : true)
  if (!targets.length) return
  try {
    await ElMessageBox.confirm(`对 ${targets.length} 辆车执行「${cmd}」？`, '批量维护', { type: 'warning' })
    for (const v of targets) {
      const rawId = v.rawId ?? parseInt(v.id.replace(/\D/g, ''), 10)
      if (Number.isFinite(rawId)) await setVehicleMaintenance(rawId, mode)
    }
    ElMessage.success('批量操作已提交')
    await refreshAll()
  } catch {
    /* cancelled */
  }
}
</script>

<style scoped>
.vehicle-hub-page {
  padding: 16px;
  height: 100%;
  display: flex;
  flex-direction: column;
  overflow: hidden;
}

.hub-tabs {
  flex: 1;
  min-height: 0;
  display: flex;
  flex-direction: column;
}

:deep(.el-tabs__content) {
  flex: 1;
  min-height: 0;
}

:deep(.el-tab-pane) {
  height: 100%;
}

:deep(.el-tabs__item) {
  color: var(--mg-text-muted, rgba(255, 255, 255, 0.65));
}
:deep(.el-tabs__item.is-active) {
  color: var(--mg-text-light, #fff);
}
:deep(.el-tabs__active-bar) {
  background-color: var(--mg-accent, var(--el-color-primary));
}
:deep(.el-tabs__nav-wrap::after) {
  background-color: rgba(255, 255, 255, 0.08);
}

.overview-pane {
  height: 100%;
  display: flex;
  flex-direction: column;
  gap: 12px;
  overflow: hidden;
}

.config-pane,
.ota-pane {
  height: 100%;
  overflow: auto;
}

.hub-toolbar {
  display: flex;
  flex-direction: column;
  gap: 12px;
  flex-shrink: 0;
}

.stats-row {
  display: flex;
  flex-wrap: wrap;
  gap: 16px;
}

.stat {
  display: flex;
  flex-direction: column;
  align-items: center;
  min-width: 64px;
}

.stat .num {
  font-size: 22px;
  font-weight: 700;
  line-height: 1.2;
}

.stat .label {
  font-size: 12px;
  color: var(--el-text-color-secondary);
}

.stat.online .num { color: var(--el-color-success); }
.stat.warn .num { color: var(--el-color-warning); }
.stat.danger .num { color: var(--el-color-danger); }
.stat.muted .num { color: var(--el-text-color-secondary); }

.filters-row {
  display: flex;
  flex-wrap: wrap;
  gap: 8px;
  align-items: center;
}

.search-input {
  width: 220px;
}

.filter-select {
  width: 120px;
}

.fleet-filter {
  width: 160px;
}

.view-toggle {
  margin-left: auto;
}

.vehicle-scroll {
  flex: 1;
  min-height: 0;
  overflow: auto;
  padding-bottom: 8px;
}

.vehicle-scroll.is-grid {
  display: grid;
  grid-template-columns: repeat(auto-fill, minmax(340px, 1fr));
  grid-auto-rows: max-content;
  gap: 14px;
  align-content: start;
}

.vehicle-scroll.is-list {
  display: flex;
  flex-direction: column;
  gap: 6px;
}

.list-head {
  display: grid;
  grid-template-columns: minmax(140px, 1.4fr) 72px 80px 100px 64px 64px 56px 88px;
  gap: 12px;
  align-items: center;
  padding: 4px 12px 4px 14px;
  font-size: 10px;
  font-weight: 600;
  color: var(--mg-text-muted, rgba(255, 255, 255, 0.45));
  letter-spacing: 0.3px;
  flex-shrink: 0;
  position: sticky;
  top: 0;
  z-index: 1;
  background: rgba(var(--mg-bg-card-darker-rgb, 20, 12, 48), 0.92);
  backdrop-filter: blur(8px);
  border-radius: 8px;
}

.list-head .head-actions {
  text-align: right;
}

@media (max-width: 900px) {
  .list-head { display: none; }
  .vehicle-scroll.is-grid {
    grid-template-columns: 1fr;
  }
}

.footnote {
  flex-shrink: 0;
  margin: 0;
  font-size: 11px;
  color: var(--el-text-color-placeholder);
}
</style>
