import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import type { Dispatch, ReactNode, SetStateAction } from 'react';
import { Button, Input, Tag } from '@douyinfe/semi-ui';
import {
  IconBarChartHStroked,
  IconBell,
  IconCopy,
  IconHistogram,
  IconHome,
  IconPulse,
  IconSearch,
  IconServer,
  IconSetting
} from '@douyinfe/semi-icons';
import {
  alertEvents,
  dataSources,
  fieldOptions,
  getVehiclePrimarySource,
  historyRecords,
  protocolMeta,
  sourceHealthLabel,
  statusLabel,
  trackPoints,
  vehicles
} from './prototype/mockData';
import {
  buildDataCapabilityRadar,
  buildHistoryQueryPreview,
  buildReplayRawLookupWindow,
  capabilityBoundaries,
  filterVehicles,
  formatNumber,
  getAlertEvidenceItems,
  getAlertRows,
  getCommandPriorityItems,
  getKpis,
  getMileageSourceDecisions,
  getRealtimeEvidence,
  getRealtimeSummary,
  getReplayEvidence,
  getReplaySegments,
  getReplaySummary,
  getSampleBoundaryCopy,
  getSourceConsistency,
  getSourceName,
  getStatsInterpretationItems,
  getVehicleDiagnosticSteps,
  getVehicleDetailDigest,
  getVehicleSourceResponsibilityRows,
  historyPageSizeOptions,
  includesQuery,
  protocolFilterOptions,
  sectionDataBoundaries,
  sectionTitle,
  statusFilterOptions
} from './prototype/viewModel';
import type { HistoryQueryPreview, ProtocolFilter, SectionKey, StatusFilter } from './prototype/viewModel';
import {
  loadPrototypeAlertSignals,
  loadPrototypeMapAddress,
  loadPrototypeRawFrames,
  loadPrototypeRealtimeVehicles,
  loadPrototypeSourceMonitor,
  loadPrototypeTrackPoints
} from './prototype/realData';
import { getAMapConfig, getApiBaseUrl, isAMapConfigured } from './config/appConfig';
import { buildAMapMarkerURL, isValidAMapCoordinate, loadAMap } from './integrations/amap';
import type {
  PrototypeAlertSignal,
  PrototypeAlertSignalState,
  PrototypeMapAddressState,
  PrototypeRawFrameState,
  PrototypeRealDataState,
  PrototypeSourceMonitorState,
  PrototypeTrackState
} from './prototype/realData';
import { rawCoordinateAddressEvidence, rawCoordinateEvidence, type RawCoordinateEvidence } from './prototype/rawEvidence';
import type {
  AlertEvent,
  DataSourceRecord,
  Protocol,
  SourceHealth,
  TrackPoint,
  VehicleRecord,
  VehicleSourceSnapshot
} from './prototype/types';
import { VehicleMap } from './components/VehicleMap';
import type { VehicleMapPoint } from './components/VehicleMap';
import './styles/prototype.css';

const navItems: Array<{ key: SectionKey; label: string; icon: ReactNode; metric: string }> = [
  { key: 'command', label: '实时指挥台', icon: <IconHome />, metric: '地图看车' },
  { key: 'replay', label: '轨迹回放', icon: <IconPulse />, metric: '证据链' },
  { key: 'history', label: '历史查询', icon: <IconHistogram />, metric: 'Raw/Fields' },
  { key: 'alerts', label: '告警中心', icon: <IconBell />, metric: '断链/异常' },
  { key: 'stats', label: '统计分析', icon: <IconBarChartHStroked />, metric: '里程/在线' },
  { key: 'sources', label: '数据源监控', icon: <IconServer />, metric: '平台质量' }
];

const protocolOrder: Protocol[] = ['GB32960', 'JT808', 'YUTONG_MQTT'];
const defaultHistoryFields = ['speed_kph', 'total_mileage_km', 'lat_lon'];

const sectionKeys = new Set<SectionKey>(navItems.map((item) => item.key));

type FreshnessFilter = 'ALL' | '10S' | '60S' | 'STALE';
type DetailTab = '概况' | '实时字段' | '来源' | '告警';
type StatsApiProbeStatus = 'checking' | 'ready' | 'missing' | 'error';
type RealtimeQualityTone = 'green' | 'blue' | 'orange' | 'red';
type DiagnosticTone = 'ok' | 'warn' | 'error' | 'idle';
type AMapRuntimeStatus = 'not-configured' | 'loading' | 'ready' | 'error';

type AMapRuntimeState = {
  status: AMapRuntimeStatus;
  label: string;
  detail: string;
  diagnosticValue: string;
  tagLabel: string;
  tone: DiagnosticTone;
  error?: string;
};

type RealtimeQualityBucket = {
  key: string;
  title: string;
  count: number;
  detail: string;
  tone: RealtimeQualityTone;
  vehicles: VehicleRecord[];
};

type StatsApiProbeDefinition = {
  key: string;
  label: string;
  capability: string;
  endpoint: string;
  required: boolean;
};

type StatsApiProbeResult = StatsApiProbeDefinition & {
  status: StatsApiProbeStatus;
  httpStatus?: number;
  detail: string;
  checkedAt?: string;
};

const compactViewportQuery = '(max-width: 720px)';
const statsDesktopRealtimeLimit = 20;
const statsCompactRealtimeLimit = 8;
const statsDesktopConsistencyLimit = 10;
const statsCompactConsistencyLimit = 6;
const sourceDesktopVisibleLimit = 12;
const sourceCompactVisibleLimit = 8;
const realtimeRefreshIntervalMs = 15_000;
const realtimeQueryLimit = 300;
const realtimeLocationQuerySource = `/api/realtime/locations?limit=${realtimeQueryLimit}&offset=0`;
const realtimeSnapshotQuerySource = `/api/realtime/snapshots?limit=${realtimeQueryLimit}&offset=0`;
const realtimeQuerySource = `${realtimeLocationQuerySource} + ${realtimeSnapshotQuerySource}`;

function isCompactViewportNow() {
  return typeof window !== 'undefined' && window.matchMedia(compactViewportQuery).matches;
}

function defaultStatsRealtimeLimit() {
  return isCompactViewportNow() ? statsCompactRealtimeLimit : statsDesktopRealtimeLimit;
}

function defaultStatsConsistencyLimit() {
  return isCompactViewportNow() ? statsCompactConsistencyLimit : statsDesktopConsistencyLimit;
}

function defaultSourceVisibleLimit() {
  return isCompactViewportNow() ? sourceCompactVisibleLimit : sourceDesktopVisibleLimit;
}

function useCompactViewport() {
  const [matches, setMatches] = useState(isCompactViewportNow);

  useEffect(() => {
    const media = window.matchMedia(compactViewportQuery);
    const sync = () => setMatches(media.matches);
    sync();
    media.addEventListener?.('change', sync);
    return () => {
      media.removeEventListener?.('change', sync);
    };
  }, []);

  return matches;
}

function amapRuntimeState(status: AMapRuntimeStatus, error?: string): AMapRuntimeState {
  if (status === 'not-configured') {
    return {
      status,
      label: '未配置',
      detail: '降级为坐标预览',
      diagnosticValue: '坐标预览',
      tagLabel: '坐标预览',
      tone: 'warn'
    };
  }
  if (status === 'loading') {
    return {
      status,
      label: '加载中',
      detail: '正在加载高德 Web JS SDK',
      diagnosticValue: 'SDK 加载中',
      tagLabel: 'AMap 加载中',
      tone: 'warn'
    };
  }
  if (status === 'ready') {
    return {
      status,
      label: '已加载',
      detail: '高德 Web JS SDK 可用',
      diagnosticValue: 'SDK 已加载',
      tagLabel: 'AMap 已加载',
      tone: 'ok'
    };
  }
  return {
    status,
    label: '加载失败',
    detail: error ? `高德 Web JS SDK 加载失败：${error}` : '高德 Web JS SDK 加载失败',
    diagnosticValue: 'SDK 失败',
    tagLabel: 'AMap 失败',
    tone: 'error',
    error
  };
}

function useAMapRuntimeProbe() {
  const config = getAMapConfig();
  const [state, setState] = useState<AMapRuntimeState>(() =>
    isAMapConfigured(config) ? amapRuntimeState('loading') : amapRuntimeState('not-configured')
  );

  useEffect(() => {
    let mounted = true;
    if (!isAMapConfigured(config)) {
      setState(amapRuntimeState('not-configured'));
      return () => {
        mounted = false;
      };
    }
    setState(amapRuntimeState('loading'));
    loadAMap(['AMap.Scale'])
      .then(() => {
        if (mounted) {
          setState(amapRuntimeState('ready'));
        }
      })
      .catch((error: unknown) => {
        if (mounted) {
          setState(amapRuntimeState('error', error instanceof Error ? error.message : String(error)));
        }
      });
    return () => {
      mounted = false;
    };
  }, [config.securityJsCode, config.securityServiceHost, config.webJsKey]);

  return state;
}

const freshnessFilterOptions: Array<{ value: FreshnessFilter; label: string }> = [
  { value: 'ALL', label: '全部新鲜度' },
  { value: '10S', label: '10秒内' },
  { value: '60S', label: '1分钟内' },
  { value: 'STALE', label: '超过1分钟' }
];

const detailTabs: DetailTab[] = ['概况', '实时字段', '来源', '告警'];
const detailTabURLValues: Record<DetailTab, string> = {
  概况: 'overview',
  实时字段: 'fields',
  来源: 'sources',
  告警: 'alerts'
};
const detailTabByURLValue = new Map<string, DetailTab>(
  Object.entries(detailTabURLValues).map(([label, value]) => [value, label as DetailTab])
);

const statsApiProbeDefinitions: StatsApiProbeDefinition[] = [
  {
    key: 'realtime-locations',
    label: '实时位置接口',
    capability: '在线、位置、速度、最新总里程',
    endpoint: '/api/realtime/locations?limit=1&offset=0',
    required: true
  },
  {
    key: 'realtime-snapshots',
    label: '实时快照接口',
    capability: '全量扁平 parsed_json 字段',
    endpoint: '/api/realtime/snapshots?limit=1&offset=0',
    required: true
  },
  {
    key: 'daily-mileage',
    label: '日里程聚合接口',
    capability: '日里程、趋势、排名',
    endpoint: '/api/mileage/daily?limit=1&offset=0',
    required: false
  }
];

type ChinaTimeRangePreset = {
  from: string;
  to: string;
  label: string;
};

type HistoryHintOrigin = 'realtime-field' | 'track-node';

type HistoryFieldHint = {
  protocol: Protocol;
  fieldKey: string;
  query: string;
  selectedField: string;
  origin?: HistoryHintOrigin;
};

type HistoryOpenContext = {
  dateFrom?: string;
  dateTo?: string;
  fields?: string[];
  hint?: HistoryFieldHint;
};

type AppURLState = {
  protocol?: ProtocolFilter;
  status?: StatusFilter;
  source?: string;
  freshness?: FreshnessFilter;
  detailTab?: DetailTab;
  query?: string;
  rawField?: string;
  rawQuery?: string;
  fieldPreset?: string;
  rawSource?: HistoryHintOrigin;
  dateFrom?: string;
  dateTo?: string;
};

function chinaDateParts(date = new Date()) {
  const formatter = new Intl.DateTimeFormat('en-CA', {
    timeZone: 'Asia/Shanghai',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit'
  });
  const parts = formatter.formatToParts(date);
  const value = (type: Intl.DateTimeFormatPartTypes) => parts.find((part) => part.type === type)?.value ?? '';
  return `${value('year')}-${value('month')}-${value('day')}`;
}

function chinaDateTime(date = new Date()) {
  const formatter = new Intl.DateTimeFormat('en-CA', {
    timeZone: 'Asia/Shanghai',
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
    hourCycle: 'h23'
  });
  const parts = formatter.formatToParts(date);
  const value = (type: Intl.DateTimeFormatPartTypes) => parts.find((part) => part.type === type)?.value ?? '00';
  return `${value('year')}-${value('month')}-${value('day')}T${value('hour')}:${value('minute')}:${value('second')}+08:00`;
}

function chinaShortDateTime(value?: string) {
  const timestamp = value ? Date.parse(value) : NaN;
  if (!Number.isFinite(timestamp)) {
    return '暂无';
  }
  return new Intl.DateTimeFormat('zh-CN', {
    timeZone: 'Asia/Shanghai',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
  }).format(new Date(timestamp));
}

function appApiURL(path: string) {
  const base = getApiBaseUrl();
  return base ? `${base}${path}` : path;
}

function payloadItemsCount(payload: unknown) {
  if (!payload || typeof payload !== 'object') {
    return undefined;
  }
  const root = payload as { data?: unknown; items?: unknown };
  if (Array.isArray(root.items)) {
    return root.items.length;
  }
  if (Array.isArray(root.data)) {
    return root.data.length;
  }
  if (root.data && typeof root.data === 'object') {
    const data = root.data as { items?: unknown };
    if (Array.isArray(data.items)) {
      return data.items.length;
    }
  }
  return undefined;
}

function payloadTotalCount(payload: unknown) {
  if (!payload || typeof payload !== 'object') {
    return undefined;
  }
  const root = payload as { data?: unknown; total?: unknown };
  const directTotal = Number(root.total);
  if (Number.isFinite(directTotal)) {
    return directTotal;
  }
  if (root.data && typeof root.data === 'object') {
    const dataTotal = Number((root.data as { total?: unknown }).total);
    if (Number.isFinite(dataTotal)) {
      return dataTotal;
    }
  }
  return undefined;
}

function initialStatsApiProbes(): StatsApiProbeResult[] {
  return statsApiProbeDefinitions.map((definition) => ({
    ...definition,
    status: 'checking',
    detail: '等待浏览器探测真实接口'
  }));
}

async function probeStatsApi(definition: StatsApiProbeDefinition): Promise<StatsApiProbeResult> {
  const controller = new AbortController();
  const timeout = window.setTimeout(() => controller.abort(), 4500);
  const checkedAt = chinaShortDateTime(new Date().toISOString());
  try {
    const response = await fetch(appApiURL(definition.endpoint), {
      method: 'GET',
      signal: controller.signal
    });
    if (!response.ok) {
      return {
        ...definition,
        status: response.status === 404 ? 'missing' : 'error',
        httpStatus: response.status,
        checkedAt,
        detail: `HTTP ${response.status}，${response.status === 404 ? '后端暂未提供该能力' : response.statusText || '接口异常'}`
      };
    }
    const text = await response.text();
    let payload: unknown;
    try {
      payload = text ? JSON.parse(text) : undefined;
    } catch {
      payload = undefined;
    }
    const sampleCount = payloadItemsCount(payload);
    const totalCount = payloadTotalCount(payload);
    const sampleText = sampleCount == null ? '已返回响应' : `样本 ${sampleCount} 条`;
    const totalText = totalCount != null && sampleCount != null && totalCount > sampleCount
      ? ` / 总计 ${formatNumber(totalCount, 0)} 条`
      : '';
    return {
      ...definition,
      status: 'ready',
      httpStatus: response.status,
      checkedAt,
      detail: `HTTP ${response.status}，${sampleText}${totalText}`
    };
  } catch (error) {
    const isAbort = error instanceof DOMException && error.name === 'AbortError';
    return {
      ...definition,
      status: 'error',
      checkedAt,
      detail: isAbort ? '探测超时，暂不能作为页面能力依据' : `探测失败：${error instanceof Error ? error.message : String(error)}`
    };
  } finally {
    window.clearTimeout(timeout);
  }
}

function statsApiProbeTag(probe: StatsApiProbeResult) {
  if (probe.status === 'ready') {
    return { color: 'green', label: '可用' } as const;
  }
  if (probe.status === 'missing') {
    return { color: 'orange', label: '未接入' } as const;
  }
  if (probe.status === 'error') {
    return { color: 'red', label: '异常' } as const;
  }
  return { color: 'blue', label: '探测中' } as const;
}

function StatsApiProbePanel({ probes }: { probes: StatsApiProbeResult[] }) {
  const readyCount = probes.filter((probe) => probe.status === 'ready').length;
  const checkingCount = probes.filter((probe) => probe.status === 'checking').length;
  const requiredBlocked = probes.some((probe) => probe.required && probe.status !== 'ready');
  const summaryColor = checkingCount > 0
    ? 'blue'
    : readyCount === probes.length
      ? 'green'
      : requiredBlocked
        ? 'red'
        : 'orange';
  return (
    <div className="vpc-stat-api-probe" aria-label="真实统计接口探测">
      <div className="vpc-stat-api-probe-head">
        <div>
          <strong>真实统计接口探测</strong>
          <span>浏览器直接请求后端，只展示源头已支撑的统计能力</span>
        </div>
        <Tag color={summaryColor}>
          {readyCount}/{probes.length} 可用
        </Tag>
      </div>
      <div className="vpc-stat-api-probe-grid">
        {probes.map((probe) => {
          const tag = statsApiProbeTag(probe);
          return (
            <article className={`vpc-stat-api-probe-card vpc-stat-api-probe-${probe.status}`} key={probe.key}>
              <div>
                <strong>{probe.label}</strong>
                <Tag color={tag.color}>{tag.label}</Tag>
              </div>
              <span>{probe.endpoint}</span>
              <em>{probe.capability}</em>
              <p>{probe.detail}</p>
              <small>{probe.required ? '页面核心依赖' : '接入后再开放展示'}{probe.checkedAt ? ` / ${probe.checkedAt}` : ''}</small>
            </article>
          );
        })}
      </div>
    </div>
  );
}

function getStatsProbe(probes: StatsApiProbeResult[], key: string) {
  return probes.find((probe) => probe.key === key);
}

function statsInterpretationTag(tone: ReturnType<typeof getStatsInterpretationItems>[number]['tone']) {
  if (tone === 'ready') return { color: 'green', label: '可用' } as const;
  if (tone === 'error') return { color: 'red', label: '阻塞' } as const;
  if (tone === 'waiting') return { color: 'blue', label: '等待' } as const;
  return { color: 'orange', label: '关注' } as const;
}

function StatsInterpretationPanel({
  items,
  dailyMileageReady
}: {
  items: ReturnType<typeof getStatsInterpretationItems>;
  dailyMileageReady: boolean;
}) {
  return (
    <section className="vpc-stats-interpretation" aria-label="统计判读">
      <div className="vpc-stats-interpretation-head">
        <div>
          <strong>统计判读</strong>
          <span>先判断真实数据是否足够可信，再开放日里程、趋势和排名；不把多协议里程简单相加。</span>
        </div>
        <Tag color={dailyMileageReady ? 'green' : 'orange'}>
          {dailyMileageReady ? '日里程可用' : '日里程待接入'}
        </Tag>
      </div>
      <div className="vpc-stats-interpretation-grid">
        {items.map((item) => {
          const tag = statsInterpretationTag(item.tone);
          return (
            <article className={`vpc-stats-interpretation-card vpc-stats-interpretation-${item.tone}`} key={item.key}>
              <div>
                <span>{item.title}</span>
                <Tag color={tag.color} size="small">{tag.label}</Tag>
              </div>
              <strong>{item.metric}</strong>
              <em>{item.detail}</em>
              <small>{item.evidence}</small>
            </article>
          );
        })}
      </div>
    </section>
  );
}

function StatsProductionReadiness({
  probes,
  realtimeRows,
  usingRealData
}: {
  probes: StatsApiProbeResult[];
  realtimeRows: number;
  usingRealData: boolean;
}) {
  const realtimeProbe = getStatsProbe(probes, 'realtime-locations');
  const snapshotProbe = getStatsProbe(probes, 'realtime-snapshots');
  const dailyMileageProbe = getStatsProbe(probes, 'daily-mileage');
  const realtimeReady = realtimeProbe?.status === 'ready' && snapshotProbe?.status === 'ready' && usingRealData && realtimeRows > 0;
  const snapshotReady = snapshotProbe?.status === 'ready';
  const dailyMileageReady = dailyMileageProbe?.status === 'ready';
  const tone = realtimeReady ? dailyMileageReady ? 'ready' : 'partial' : 'blocked';
  const title = realtimeReady
    ? dailyMileageReady
      ? '统计生产就绪'
      : '当前态统计可用，日里程待接入'
    : '统计真值暂不可用';
  const detail = realtimeReady
    ? dailyMileageReady
      ? '实时位置、实时快照和日里程聚合接口均可用，可展示当前态、日里程和趋势入口。'
      : '实时位置和快照接口已有真实来源行，只展示在线、速度、最新总里程和字段覆盖；日里程、趋势、排名继续收起。'
    : '实时位置或快照接口没有可用真实来源行，不展示日里程、趋势、排名或多源统计真值。';

  return (
    <section className={`vpc-stats-production vpc-stats-production-${tone}`} aria-label="统计生产就绪度">
      <div>
        <span>生产就绪度</span>
        <strong>{title}</strong>
        <em>{detail}</em>
      </div>
      <Metric label="当前态" value={realtimeReady ? `${realtimeRows} 行` : '未就绪'} />
      <Metric label="快照字段" value={snapshotReady ? '可用' : '未就绪'} />
      <Metric label="日里程" value={dailyMileageReady ? '可用' : '未接入'} />
      <Metric label="证据入口" value={usingRealData ? '轨迹/RAW' : '待 VIN'} />
    </section>
  );
}

function lastSeenSecondsFromText(value: string) {
  const matched = value.match(/(\d+(?:\.\d+)?)\s*(秒|分钟|小时)/);
  if (!matched) {
    return Number.POSITIVE_INFINITY;
  }
  const amount = Number(matched[1]);
  if (!Number.isFinite(amount)) {
    return Number.POSITIVE_INFINITY;
  }
  if (matched[2] === '小时') {
    return amount * 3600;
  }
  if (matched[2] === '分钟') {
    return amount * 60;
  }
  return amount;
}

function sourceLastSeenSeconds(source: VehicleSourceSnapshot) {
  const absoluteTimestamp = source.lastSeenAt ? Date.parse(source.lastSeenAt) : NaN;
  if (Number.isFinite(absoluteTimestamp)) {
    return Math.max(0, Math.round((Date.now() - absoluteTimestamp) / 1000));
  }
  return lastSeenSecondsFromText(source.lastSeen);
}

function vehicleMatchesFreshness(vehicle: VehicleRecord, freshnessFilter: FreshnessFilter) {
  if (freshnessFilter === 'ALL') {
    return true;
  }
  const seconds = sourceLastSeenSeconds(getVehiclePrimarySource(vehicle));
  if (freshnessFilter === '10S') {
    return seconds <= 10;
  }
  if (freshnessFilter === '60S') {
    return seconds <= 60;
  }
  return seconds > 60;
}

function vehicleHasRealtimeCoordinate(vehicle: VehicleRecord) {
  return isValidAMapCoordinate(vehicle.longitude, vehicle.latitude);
}

function firstVehicleWithUsableCoordinate(records: VehicleRecord[]) {
  return records.find(vehicleHasRealtimeCoordinate) ?? records[0];
}

function vehicleRealtimeFieldCount(vehicle: VehicleRecord) {
  return Object.values(vehicle.flatFields).reduce((sum, fields) => sum + Object.keys(fields).length, 0);
}

function buildRealtimeQualityBuckets(records: VehicleRecord[]): RealtimeQualityBucket[] {
  const fresh = records.filter((vehicle) => sourceLastSeenSeconds(getVehiclePrimarySource(vehicle)) <= 60);
  const stale = records.filter((vehicle) => sourceLastSeenSeconds(getVehiclePrimarySource(vehicle)) > 60);
  const missingCoordinate = records.filter((vehicle) => !vehicleHasRealtimeCoordinate(vehicle));
  const missingMileage = records.filter((vehicle) =>
    vehicle.sources.every((source) => source.totalMileageKm == null || source.totalMileageKm <= 0)
  );
  const thinFields = records.filter((vehicle) => vehicleRealtimeFieldCount(vehicle) < 6);

  return [
    {
      key: 'fresh',
      title: '1分钟内活跃',
      count: fresh.length,
      detail: '可直接进入地图和实时字段核验',
      tone: 'green',
      vehicles: fresh
    },
    {
      key: 'stale',
      title: '超过1分钟',
      count: stale.length,
      detail: '优先排查链路、平台转发或车辆断联',
      tone: stale.length > 0 ? 'orange' : 'blue',
      vehicles: stale
    },
    {
      key: 'coordinate',
      title: '坐标不可用',
      count: missingCoordinate.length,
      detail: '地图无法落点，需要回查 RAW 坐标字段',
      tone: missingCoordinate.length > 0 ? 'red' : 'green',
      vehicles: missingCoordinate
    },
    {
      key: 'mileage',
      title: '总里程缺失',
      count: missingMileage.length,
      detail: '影响里程统计，需要确认协议字段映射',
      tone: missingMileage.length > 0 ? 'orange' : 'green',
      vehicles: missingMileage
    },
    {
      key: 'fields',
      title: '字段偏少',
      count: thinFields.length,
      detail: '实时解析字段少于 6 个，适合查 RAW 对照',
      tone: thinFields.length > 0 ? 'orange' : 'green',
      vehicles: thinFields
    }
  ];
}

function chinaDayRange(offsetDays = 0): ChinaTimeRangePreset {
  const day = chinaDateParts(new Date(Date.now() + offsetDays * 24 * 60 * 60 * 1000));
  return {
    from: `${day}T00:00:00+08:00`,
    to: `${day}T23:59:59+08:00`,
    label: offsetDays === 0 ? '今日' : offsetDays === -1 ? '昨日' : day
  };
}

function chinaLastHourRange(): ChinaTimeRangePreset {
  const now = new Date();
  return {
    from: chinaDateTime(new Date(now.getTime() - 60 * 60 * 1000)),
    to: chinaDateTime(now),
    label: '近1小时'
  };
}

function initialChinaDayRange() {
  return chinaDayRange(0);
}

const timeRangePresets: Array<{ key: 'today' | 'yesterday' | 'lastHour'; label: string; range: () => ChinaTimeRangePreset }> = [
  { key: 'today', label: '今日', range: () => chinaDayRange(0) },
  { key: 'yesterday', label: '昨日', range: () => chinaDayRange(-1) },
  { key: 'lastHour', label: '近1小时', range: chinaLastHourRange }
];

function isSectionKey(value: string | null): value is SectionKey {
  return Boolean(value && sectionKeys.has(value as SectionKey));
}

function initialSectionFromURL(): SectionKey {
  const params = new URLSearchParams(window.location.search);
  const querySection = params.get('section');
  if (isSectionKey(querySection)) {
    return querySection;
  }
  const hashSection = window.location.hash.replace(/^#\/?/, '');
  if (isSectionKey(hashSection)) {
    return hashSection;
  }
  return 'command';
}

function initialVehicleKeyFromURL() {
  const params = new URLSearchParams(window.location.search);
  return (params.get('vin') || params.get('vehicle') || '').trim();
}

function initialQueryFromURL() {
  const params = new URLSearchParams(window.location.search);
  return (params.get('q') || '').trim();
}

function isProtocol(value: string | null): value is Protocol {
  return Boolean(value && protocolOrder.includes(value as Protocol));
}

function isStatusFilter(value: string | null): value is StatusFilter {
  return value === 'ALL' || value === 'online' || value === 'warning' || value === 'offline';
}

function initialStatusFromURL(): StatusFilter {
  const params = new URLSearchParams(window.location.search);
  const status = params.get('status');
  return isStatusFilter(status) ? status : 'ALL';
}

function initialSourceFromURL() {
  const params = new URLSearchParams(window.location.search);
  return (params.get('source') || 'ALL').trim() || 'ALL';
}

function isFreshnessFilter(value: string | null): value is FreshnessFilter {
  return value === 'ALL' || value === '10S' || value === '60S' || value === 'STALE';
}

function initialFreshnessFromURL(): FreshnessFilter {
  const params = new URLSearchParams(window.location.search);
  const freshness = params.get('freshness');
  return isFreshnessFilter(freshness) ? freshness : 'ALL';
}

function isDetailTab(value: string | null): value is DetailTab {
  return Boolean(value && detailTabs.includes(value as DetailTab));
}

function initialDetailTabFromURL(): DetailTab {
  const params = new URLSearchParams(window.location.search);
  const tab = params.get('tab');
  if (isDetailTab(tab)) {
    return tab;
  }
  return detailTabByURLValue.get(tab ?? '') ?? '概况';
}

function initialProtocolFromURL(): ProtocolFilter {
  const params = new URLSearchParams(window.location.search);
  const protocol = params.get('protocol');
  if (protocol === 'ALL') {
    return 'ALL';
  }
  const rawField = params.get('rawField');
  return isProtocol(protocol) ? protocol : rawField ? inferProtocolFromRealtimeField(rawField) ?? 'ALL' : 'ALL';
}

function inferProtocolFromRealtimeField(fieldKey: string): Protocol | undefined {
  const normalized = fieldKey.trim().toLowerCase();
  if (normalized.startsWith('gb32960.') || normalized.startsWith('gb.')) {
    return 'GB32960';
  }
  if (normalized.startsWith('jt808.') || normalized.startsWith('808.')) {
    return 'JT808';
  }
  if (normalized.startsWith('yutong_mqtt.') || normalized.startsWith('mqtt.')) {
    return 'YUTONG_MQTT';
  }
  return undefined;
}

function updateAppURL(section: SectionKey, vehicleKey?: string, state: AppURLState = {}) {
  const nextURL = new URL(window.location.href);
  nextURL.searchParams.set('section', section);
  if (vehicleKey) {
    nextURL.searchParams.set('vin', vehicleKey);
  } else {
    nextURL.searchParams.delete('vin');
  }
  if (state.protocol && state.protocol !== 'ALL') {
    nextURL.searchParams.set('protocol', state.protocol);
  } else {
    nextURL.searchParams.delete('protocol');
  }
  if (section === 'command') {
    if (state.status && state.status !== 'ALL') {
      nextURL.searchParams.set('status', state.status);
    } else {
      nextURL.searchParams.delete('status');
    }
    if (state.source && state.source !== 'ALL') {
      nextURL.searchParams.set('source', state.source);
    } else {
      nextURL.searchParams.delete('source');
    }
    if (state.freshness && state.freshness !== 'ALL') {
      nextURL.searchParams.set('freshness', state.freshness);
    } else {
      nextURL.searchParams.delete('freshness');
    }
    if (state.detailTab && state.detailTab !== '概况') {
      nextURL.searchParams.set('tab', detailTabURLValues[state.detailTab]);
    } else {
      nextURL.searchParams.delete('tab');
    }
    if (state.query) {
      nextURL.searchParams.set('q', state.query);
    } else {
      nextURL.searchParams.delete('q');
    }
  } else {
    nextURL.searchParams.delete('status');
    nextURL.searchParams.delete('source');
    nextURL.searchParams.delete('freshness');
    nextURL.searchParams.delete('tab');
    nextURL.searchParams.delete('q');
  }
  if (section === 'history' && state.rawField) {
    nextURL.searchParams.set('rawField', state.rawField);
    if (state.rawSource) {
      nextURL.searchParams.set('rawSource', state.rawSource);
    } else {
      nextURL.searchParams.delete('rawSource');
    }
    if (state.rawQuery) {
      nextURL.searchParams.set('rawQuery', state.rawQuery);
    } else {
      nextURL.searchParams.delete('rawQuery');
    }
    if (state.fieldPreset) {
      nextURL.searchParams.set('fieldPreset', state.fieldPreset);
    } else {
      nextURL.searchParams.delete('fieldPreset');
    }
  } else {
    nextURL.searchParams.delete('rawField');
    nextURL.searchParams.delete('rawQuery');
    nextURL.searchParams.delete('fieldPreset');
    nextURL.searchParams.delete('rawSource');
  }
  if (section === 'history') {
    if (state.dateFrom) {
      nextURL.searchParams.set('dateFrom', state.dateFrom);
    } else {
      nextURL.searchParams.delete('dateFrom');
    }
    if (state.dateTo) {
      nextURL.searchParams.set('dateTo', state.dateTo);
    } else {
      nextURL.searchParams.delete('dateTo');
    }
  } else {
    nextURL.searchParams.delete('dateFrom');
    nextURL.searchParams.delete('dateTo');
  }
  nextURL.hash = '';
  window.history.replaceState(null, '', nextURL);
}

function findVehicleByKey(records: VehicleRecord[], key: string) {
  const normalized = key.trim().toLowerCase();
  if (!normalized) {
    return undefined;
  }
  return records.find((vehicle) =>
    [vehicle.vin, vehicle.plate, vehicle.phone].some((value) => value?.toLowerCase() === normalized)
  );
}

function rawFieldQueryFromRealtimeKey(fieldKey: string) {
  const normalized = fieldKey.toLowerCase();
  if (normalized.includes('speed')) return 'speed';
  if (normalized.includes('total_mileage') || normalized.includes('mileage')) return 'total_mileage';
  if (normalized.includes('soc') || normalized.includes('battery_capacity')) return 'soc';
  if (normalized.includes('hydrogen') || normalized.includes('left_hydrogen')) return 'hydrogen';
  if (normalized.includes('latitude') || normalized.endsWith('.lat')) return 'latitude';
  if (normalized.includes('longitude') || normalized.endsWith('.lng')) return 'longitude';
  if (normalized.includes('direction')) return 'direction';
  if (normalized.includes('fc_stack') || normalized.includes('fuel_cell')) return 'fc_stack';
  if (normalized.includes('event_time') || normalized.includes('device_time') || normalized.includes('received_at')) return 'time';
  const parts = fieldKey.split('.').filter(Boolean);
  return parts.slice(-2).join('.') || fieldKey;
}

function selectedHistoryFieldFromRealtimeKey(fieldKey: string) {
  const normalized = fieldKey.toLowerCase();
  if (normalized.includes('speed')) return 'speed_kph';
  if (normalized.includes('total_mileage') || normalized.includes('mileage')) return 'total_mileage_km';
  if (normalized.includes('soc') || normalized.includes('battery_capacity')) return 'soc_pct';
  if (normalized.includes('hydrogen') || normalized.includes('left_hydrogen')) return 'left_hydrogen_kg';
  if (normalized.includes('latitude') || normalized.includes('longitude') || normalized.endsWith('.lat') || normalized.endsWith('.lng')) return 'lat_lon';
  if (normalized.includes('direction')) return 'direction_deg';
  if (normalized.includes('fc_stack') || normalized.includes('fuel_cell')) return 'fc_stack';
  if (normalized.includes('event_time') || normalized.includes('device_time') || normalized.includes('received_at')) return 'quality_delay';
  return fieldKey;
}

function historyFieldHintFromURL(): HistoryFieldHint | undefined {
  const params = new URLSearchParams(window.location.search);
  const fieldKey = (params.get('rawField') || '').trim();
  if (!fieldKey) {
    return undefined;
  }
  const protocolParam = params.get('protocol');
  const protocol = isProtocol(protocolParam)
    ? protocolParam
    : inferProtocolFromRealtimeField(fieldKey) ?? 'GB32960';
  const query = (params.get('rawQuery') || '').trim() || rawFieldQueryFromRealtimeKey(fieldKey);
  const selectedField = (params.get('fieldPreset') || '').trim() || selectedHistoryFieldFromRealtimeKey(fieldKey);
  return {
    protocol,
    fieldKey,
    query,
    selectedField,
    origin: params.get('rawSource') === 'track-node' ? 'track-node' : 'realtime-field'
  };
}

function initialHistoryDateFrom() {
  const params = new URLSearchParams(window.location.search);
  const range = initialChinaDayRange();
  return initialSectionFromURL() === 'history' ? params.get('dateFrom') || range.from : range.from;
}

function initialHistoryDateTo() {
  const params = new URLSearchParams(window.location.search);
  const range = initialChinaDayRange();
  return initialSectionFromURL() === 'history' ? params.get('dateTo') || range.to : range.to;
}

function historyVehicleFromKey(key: string, base: VehicleRecord): VehicleRecord {
  const normalized = key.trim();
  const sourceId = `history-source-${normalized}`;
  return {
    ...base,
    id: `history-vin-${normalized}`,
    plate: normalized,
    vin: normalized,
    phone: undefined,
    oem: '历史查询',
    status: 'offline',
    city: '--',
    address: '按 VIN 查询历史轨迹',
    primarySourceId: sourceId,
    sources: [{
      id: sourceId,
      protocol: 'GB32960',
      sourceName: 'TDengine 历史轨迹',
      endpoint: '/api/history/locations',
      platformAccount: 'vehicle_locations',
      status: 'offline',
      latencyMs: 0,
      lastSeen: '按时间窗查询',
      fieldCount: 0
    }],
    flatFields: {
      GB32960: {},
      JT808: {},
      YUTONG_MQTT: {}
    }
  };
}

function AppSelect<T extends string>({
  value,
  options,
  onChange,
  ariaLabel
}: {
  value: T;
  options: Array<{ value: T; label: string }>;
  onChange: (value: T) => void;
  ariaLabel: string;
}) {
  return (
    <select aria-label={ariaLabel} className="vpc-select" onChange={(event) => onChange(event.target.value as T)} value={value}>
      {options.map((option) => (
        <option key={option.value} value={option.value}>
          {option.label}
        </option>
      ))}
    </select>
  );
}

function TimeRangePresetButtons({
  onApply
}: {
  onApply: (range: ChinaTimeRangePreset) => void;
}) {
  return (
    <div className="vpc-time-preset-buttons" aria-label="时间范围快捷选择">
      {timeRangePresets.map((preset) => (
        <button
          key={preset.key}
          onClick={() => onApply(preset.range())}
          type="button"
        >
          {preset.label}
        </button>
      ))}
    </div>
  );
}

export default function PrototypeApp() {
  const [activeSection, setActiveSection] = useState<SectionKey>(() => initialSectionFromURL());
  const [query, setQuery] = useState(() => initialQueryFromURL());
  const [protocolFilter, setProtocolFilter] = useState<ProtocolFilter>(() => initialProtocolFromURL());
  const [statusFilter, setStatusFilter] = useState<StatusFilter>(() => initialStatusFromURL());
  const [sourceFilter, setSourceFilter] = useState(() => initialSourceFromURL());
  const [freshnessFilter, setFreshnessFilter] = useState<FreshnessFilter>(() => initialFreshnessFromURL());
  const [activeVehicleId, setActiveVehicleId] = useState(vehicles[0].id);
  const [detailTab, setDetailTab] = useState<DetailTab>(() => initialDetailTabFromURL());
  const [playbackIndex, setPlaybackIndex] = useState(0);
  const [isPlaying, setIsPlaying] = useState(false);
  const [historyQueried, setHistoryQueried] = useState(true);
  const [selectedFields, setSelectedFields] = useState(() => {
    const hint = initialSectionFromURL() === 'history' ? historyFieldHintFromURL() : undefined;
    return hint ? [hint.selectedField] : defaultHistoryFields;
  });
  const [historyPage, setHistoryPage] = useState(1);
  const [historyPageSize, setHistoryPageSize] = useState(3);
  const [historyDateFrom, setHistoryDateFrom] = useState(initialHistoryDateFrom);
  const [historyDateTo, setHistoryDateTo] = useState(initialHistoryDateTo);
  const [historyFieldHint, setHistoryFieldHint] = useState<HistoryFieldHint | undefined>(() =>
    initialSectionFromURL() === 'history' ? historyFieldHintFromURL() : undefined
  );
  const [realData, setRealData] = useState<PrototypeRealDataState>({
    vehicles: [],
    status: 'loading',
    source: realtimeQuerySource
  });
  const [autoRealtimeRefresh, setAutoRealtimeRefresh] = useState(true);
  const realtimeRequestId = useRef(0);
  const amapRuntime = useAMapRuntimeProbe();
  const refreshRealtimeData = useCallback((reason: 'initial' | 'manual' | 'auto' = 'manual') => {
    const requestId = realtimeRequestId.current + 1;
    realtimeRequestId.current = requestId;
    setRealData((current) => ({
      ...current,
      status: 'loading',
      source: realtimeQuerySource,
      error: reason === 'auto' ? current.error : undefined
    }));
    loadPrototypeRealtimeVehicles(realtimeQueryLimit).then((next) => {
      if (realtimeRequestId.current !== requestId) {
        return;
      }
      setRealData((current) => {
        if (next.status === 'error' && current.vehicles.length > 0) {
          return {
            ...next,
            status: 'stale',
            vehicles: current.vehicles,
            fetchedAt: current.fetchedAt,
            total: current.total ?? current.vehicles.length,
            source: `${next.source} / in-memory cache`,
            error: `live request failed: ${next.error ?? 'unknown error'}`
          };
        }
        return next;
      });
    });
  }, []);

  const realVehicles = realData.vehicles;
  const allowMockDataset = realData.status === 'disabled';
  const canQueryRealRaw = realData.status !== 'disabled';
  const canQueryRealTrack = realData.status !== 'disabled';
  const canQueryRealSources = realData.status !== 'disabled';
  const canQueryRealAlerts = realData.status !== 'disabled';
  const vehicleDataset = realVehicles.length > 0 ? realVehicles : allowMockDataset ? vehicles : [];
  const usingRealData = realVehicles.length > 0;
  const realtimeMode = realtimeModeSummary(realData, usingRealData);
  const sourceOptions = useMemo(() => {
    if (!allowMockDataset && realVehicles.length === 0) {
      return [];
    }
    const options = new Map<string, string>();
    if (allowMockDataset) {
      dataSources.forEach((source) => options.set(source.id, source.name));
    }
    vehicleDataset.forEach((vehicle) => {
      vehicle.sources.forEach((source) => options.set(source.id, source.sourceName));
    });
    return Array.from(options.entries()).map(([value, label]) => ({ value, label }));
  }, [allowMockDataset, realVehicles.length, vehicleDataset]);
  const baseFilteredVehicles = useMemo(
    () => filterVehicles(query, protocolFilter, statusFilter, sourceFilter, vehicleDataset),
    [protocolFilter, query, sourceFilter, statusFilter, vehicleDataset]
  );
  const filteredVehicles = useMemo(
    () => activeSection === 'command'
      ? baseFilteredVehicles.filter((vehicle) => vehicleMatchesFreshness(vehicle, freshnessFilter))
      : baseFilteredVehicles,
    [activeSection, baseFilteredVehicles, freshnessFilter]
  );
  const statsVehicles = useMemo(
    () => (query.trim() ? vehicleDataset.filter((vehicle) => includesQuery(vehicle, query)) : vehicleDataset),
    [query, vehicleDataset]
  );
  const routeVehicleKey = initialVehicleKeyFromURL();
  const routeVehicle = useMemo(
    () => findVehicleByKey(vehicleDataset, routeVehicleKey),
    [routeVehicleKey, vehicleDataset]
  );

  const activeVehicle = useMemo(() => {
    if (activeSection === 'replay' && routeVehicleKey) {
      return routeVehicle ?? historyVehicleFromKey(routeVehicleKey, vehicleDataset[0] ?? vehicles[0]);
    }
    const current = filteredVehicles.find((vehicle) => vehicle.id === activeVehicleId);
    return current && vehicleHasRealtimeCoordinate(current)
      ? current
      : firstVehicleWithUsableCoordinate(filteredVehicles) ?? firstVehicleWithUsableCoordinate(vehicleDataset) ?? vehicles[0];
  }, [activeSection, activeVehicleId, filteredVehicles, routeVehicle, routeVehicleKey, vehicleDataset]);

  const activeSource = getVehiclePrimarySource(activeVehicle);
  const commandURLState = (overrides: AppURLState = {}): AppURLState => ({
    protocol: protocolFilter,
    status: statusFilter,
    source: sourceFilter,
    freshness: freshnessFilter,
    detailTab,
    query,
    ...overrides
  });
  const syncCommandURL = (vehicleKey = activeVehicle.vin, overrides: AppURLState = {}) => {
    if (activeSection === 'command') {
      updateAppURL('command', vehicleKey, commandURLState(overrides));
    }
  };
  const setCommandQuery = (value: string) => {
    setQuery(value);
    syncCommandURL(activeVehicle.vin, { query: value });
  };
  const setCommandProtocolFilter = (value: ProtocolFilter) => {
    setProtocolFilter(value);
    syncCommandURL(activeVehicle.vin, { protocol: value });
  };
  const setCommandStatusFilter = (value: StatusFilter) => {
    setStatusFilter(value);
    syncCommandURL(activeVehicle.vin, { status: value });
  };
  const setCommandSourceFilter = (value: string) => {
    setSourceFilter(value);
    syncCommandURL(activeVehicle.vin, { source: value });
  };
  const setCommandFreshnessFilter = (value: FreshnessFilter) => {
    setFreshnessFilter(value);
    syncCommandURL(activeVehicle.vin, { freshness: value });
  };
  const setCommandDetailTab = (tab: DetailTab) => {
    setDetailTab(tab);
    syncCommandURL(activeVehicle.vin, { detailTab: tab });
  };
  const selectSection = (section: SectionKey) => {
    setActiveSection(section);
    updateAppURL(section, activeVehicle.vin, section === 'command' ? commandURLState() : {});
  };
  const selectVehicle = (vehicleId: string) => {
    setActiveVehicleId(vehicleId);
    const vehicle = vehicleDataset.find((item) => item.id === vehicleId);
    updateAppURL(activeSection, vehicle?.vin, activeSection === 'command' ? commandURLState() : {});
  };
  const openVehicleReplayForVin = (vin = activeVehicle.vin) => {
    const matchedVehicle = vehicleDataset.find((vehicle) => vehicle.vin === vin);
    if (matchedVehicle) {
      setActiveVehicleId(matchedVehicle.id);
    }
    setPlaybackIndex(0);
    setIsPlaying(false);
    setActiveSection('replay');
    updateAppURL('replay', matchedVehicle?.vin ?? vin);
  };
  const openVehicleCommandForVin = (vin = activeVehicle.vin) => {
    const matchedVehicle = vehicleDataset.find((vehicle) => vehicle.vin === vin);
    if (matchedVehicle) {
      setActiveVehicleId(matchedVehicle.id);
      setQuery(matchedVehicle.vin);
    }
    setProtocolFilter('ALL');
    setStatusFilter('ALL');
    setSourceFilter('ALL');
    setFreshnessFilter('ALL');
    setDetailTab('概况');
    setActiveSection('command');
    updateAppURL('command', matchedVehicle?.vin ?? vin);
  };
  const openVehicleHistoryForVin = (vin = activeVehicle.vin, protocol?: Protocol, context?: HistoryOpenContext) => {
    const matchedVehicle = vehicleDataset.find((vehicle) => vehicle.vin === vin);
    if (matchedVehicle) {
      setActiveVehicleId(matchedVehicle.id);
    }
    setHistoryFieldHint(context?.hint);
    if (context?.fields?.length) {
      setSelectedFields(context.fields);
    }
    if (context?.dateFrom) {
      setHistoryDateFrom(context.dateFrom);
    }
    if (context?.dateTo) {
      setHistoryDateTo(context.dateTo);
    }
    setQuery(matchedVehicle?.vin ?? vin);
    setProtocolFilter(protocol ?? 'ALL');
    setStatusFilter('ALL');
    setSourceFilter('ALL');
    setHistoryPage(1);
    setHistoryQueried(true);
    setActiveSection('history');
    updateAppURL('history', matchedVehicle?.vin ?? vin, {
      protocol: protocol ?? 'ALL',
      dateFrom: context?.dateFrom,
      dateTo: context?.dateTo,
      rawField: context?.hint?.fieldKey,
      rawQuery: context?.hint?.query,
      fieldPreset: context?.hint?.selectedField,
      rawSource: context?.hint?.origin
    });
  };
  const openVehicleHistoryForField = (vin: string, protocol: Protocol, fieldKey: string) => {
    const matchedVehicle = vehicleDataset.find((vehicle) => vehicle.vin === vin);
    const selectedField = selectedHistoryFieldFromRealtimeKey(fieldKey);
    const nextHint = {
      protocol,
      fieldKey,
      query: rawFieldQueryFromRealtimeKey(fieldKey),
      selectedField,
      origin: 'realtime-field' as const
    };
    if (matchedVehicle) {
      setActiveVehicleId(matchedVehicle.id);
    }
    setHistoryFieldHint(nextHint);
    setSelectedFields([selectedField]);
    setQuery(matchedVehicle?.vin ?? vin);
    setProtocolFilter(protocol);
    setStatusFilter('ALL');
    setSourceFilter('ALL');
    setHistoryPage(1);
    setHistoryQueried(true);
    setActiveSection('history');
    updateAppURL('history', matchedVehicle?.vin ?? vin, {
      protocol,
      rawField: nextHint.fieldKey,
      rawQuery: nextHint.query,
      fieldPreset: nextHint.selectedField,
      rawSource: nextHint.origin
    });
  };
  const openProtocolHistory = (protocol: Protocol) => {
    setHistoryFieldHint(undefined);
    setQuery('');
    setProtocolFilter(protocol);
    setStatusFilter('ALL');
    setSourceFilter('ALL');
    setHistoryPage(1);
    setHistoryQueried(true);
    setActiveSection('history');
    updateAppURL('history', undefined, { protocol });
  };
  const kpis = usingRealData
    ? getRealtimeKpisForVehicles(filteredVehicles, protocolFilter)
    : getKpis(filteredVehicles, protocolFilter);
  const activeTrack = trackPoints.filter((point) => point.vehicleId === activeVehicle.id);
  const activeAlerts = alertEvents.filter((alert) => alert.vehicleId === activeVehicle.id);
  const isEvidenceSection = activeSection === 'history' || activeSection === 'replay' || activeSection === 'alerts';
  const isCommandSection = activeSection === 'command';
  const isStatsSection = activeSection === 'stats';
  const isSourceSection = activeSection === 'sources';
  const showOperationalSummary = !isCommandSection && !isEvidenceSection && !isStatsSection && !isSourceSection;
  const visibleHistory = historyRecords.filter((record) => {
    const vehicle = vehicleDataset.find((item) => item.id === record.vehicleId);
    const protocolMatched = protocolFilter === 'ALL' || record.protocol === protocolFilter;
    const queryMatched = vehicle ? includesQuery(vehicle, query) : true;
    return protocolMatched && queryMatched;
  });
  const historyContextVehicle = query.trim() ? findVehicleByKey(vehicleDataset, query) : undefined;
  const historyQueryPreview = useMemo(
    () =>
      buildHistoryQueryPreview({
        keyword: query,
        protocolFilter,
        selectedFields,
        dateFrom: historyDateFrom,
        dateTo: historyDateTo,
        limit: historyPageSize,
        offset: (historyPage - 1) * historyPageSize
      }),
    [historyDateFrom, historyDateTo, historyPage, historyPageSize, protocolFilter, query, selectedFields]
  );

  useEffect(() => {
    refreshRealtimeData('initial');
  }, [refreshRealtimeData]);

  useEffect(() => {
    if (!autoRealtimeRefresh) {
      return undefined;
    }
    const timer = window.setInterval(() => {
      refreshRealtimeData('auto');
    }, realtimeRefreshIntervalMs);
    return () => {
      window.clearInterval(timer);
    };
  }, [autoRealtimeRefresh, refreshRealtimeData]);

  useEffect(() => {
    if (sourceFilter === 'ALL') {
      return;
    }
    if (!sourceOptions.some((option) => option.value === sourceFilter)) {
      setSourceFilter('ALL');
    }
  }, [sourceFilter, sourceOptions]);

  useEffect(() => {
    if (filteredVehicles.length > 0 && !filteredVehicles.some((vehicle) => vehicle.id === activeVehicleId)) {
      setActiveVehicleId(firstVehicleWithUsableCoordinate(filteredVehicles)?.id ?? filteredVehicles[0].id);
    }
  }, [activeVehicleId, filteredVehicles]);

  useEffect(() => {
    const vehicleKey = initialVehicleKeyFromURL().toLowerCase();
    if (!vehicleKey) {
      return;
    }
    const matchedVehicle = findVehicleByKey(vehicleDataset, vehicleKey);
    if (matchedVehicle && matchedVehicle.id !== activeVehicleId) {
      setActiveVehicleId(matchedVehicle.id);
    }
  }, [activeVehicleId, vehicleDataset]);

  useEffect(() => {
    const vehicleKey = initialVehicleKeyFromURL();
    if (activeSection !== 'history' || !vehicleKey || query === vehicleKey) {
      return;
    }
    setQuery(vehicleKey);
    setHistoryPage(1);
    setHistoryQueried(true);
  }, [activeSection, query]);

  useEffect(() => {
    setPlaybackIndex(0);
  }, [activeVehicle.id]);

  useEffect(() => {
    window.scrollTo({ top: 0, left: 0 });
  }, [activeSection]);

  useEffect(() => {
    const totalPages = Math.max(1, Math.ceil(visibleHistory.length / historyPageSize));
    if (historyPage > totalPages) {
      setHistoryPage(totalPages);
    }
  }, [historyPage, historyPageSize, visibleHistory.length]);

  return (
    <div className="vpc-app">
      <aside className="vpc-sidebar" aria-label="车辆数据中台导航">
        <div className="vpc-brand">
          <span className="vpc-brand-mark">V</span>
          <div>
            <strong>车辆数据中台</strong>
            <span>Vehicle Data Center</span>
          </div>
        </div>

        <nav className="vpc-nav">
          {navItems.map((item) => (
            <button
              className={`vpc-nav-item ${activeSection === item.key ? 'vpc-nav-item-active' : ''}`}
              key={item.key}
              onClick={() => selectSection(item.key)}
              type="button"
            >
              <span className="vpc-nav-icon">{item.icon}</span>
              <span className="vpc-nav-copy">
                <strong>{item.label}</strong>
                <em>{item.metric}</em>
              </span>
            </button>
          ))}
        </nav>

        <div className={`vpc-side-status vpc-side-status-${realtimeMode.tone}`} aria-label="生产链路实时口径">
          <span>生产链路</span>
          <strong>32960 / 808 / MQTT</strong>
          <em>{realtimeMode.sideLabel}</em>
          <small>{realtimeMode.sideDetail}</small>
        </div>
      </aside>

      <main className={`vpc-main vpc-main-${activeSection}`}>
        <header className="vpc-header">
          <div>
            <h1>{sectionTitle[activeSection].title}</h1>
            <p>{sectionTitle[activeSection].subtitle}</p>
          </div>
          <div className="vpc-header-actions">
            <Input prefix={<IconSearch />} placeholder="搜索车牌 / VIN / 手机号 / 城市" value={query} onChange={setCommandQuery} />
            <Button aria-label="打开告警中心" icon={<IconBell />} onClick={() => selectSection('alerts')} theme="borderless" />
            <Button aria-label="打开数据源监控" icon={<IconSetting />} onClick={() => selectSection('sources')} theme="borderless" />
          </div>
        </header>

        <GlobalFilters
          activeSection={activeSection}
          protocolFilter={protocolFilter}
          setProtocolFilter={setCommandProtocolFilter}
          freshnessFilter={freshnessFilter}
          sourceOptions={sourceOptions}
          setFreshnessFilter={setCommandFreshnessFilter}
          setSourceFilter={setCommandSourceFilter}
          setStatusFilter={setCommandStatusFilter}
          sourceFilter={sourceFilter}
          statusFilter={statusFilter}
        />

        <DataBoundary
          activeSection={activeSection}
          canQueryRealAlerts={canQueryRealAlerts}
          canQueryRealSources={canQueryRealSources}
          realtimeMode={realtimeMode}
          usingRealData={usingRealData}
        />
        {!isEvidenceSection && !isSourceSection && (
          <RealDataStatus
            amapRuntime={amapRuntime}
            autoRefresh={autoRealtimeRefresh}
            onAutoRefreshChange={setAutoRealtimeRefresh}
            onRefresh={() => refreshRealtimeData('manual')}
            realData={realData}
            usingRealData={usingRealData}
          />
        )}

        {showOperationalSummary && (
          <OperationFlow
            activeSource={activeSource}
            activeVehicle={activeVehicle}
            filteredVehicles={filteredVehicles}
            usingRealData={usingRealData}
          />
        )}

        {showOperationalSummary && (
          <section className="vpc-kpis" aria-label="核心指标">
            {kpis.map((kpi) => (
              <article className={`vpc-kpi vpc-kpi-${kpi.tone}`} key={kpi.label}>
                <span>{kpi.label}</span>
                <strong>{kpi.value}</strong>
                <em>{kpi.sub}</em>
              </article>
            ))}
          </section>
        )}

        {activeSection === 'command' && (
          <CommandCenter
            activeAlerts={activeAlerts}
            activeSource={activeSource}
            activeVehicle={activeVehicle}
            amapRuntime={amapRuntime}
            detailTab={detailTab}
            filteredVehicles={filteredVehicles}
            onOpenHistory={(protocol?: Protocol) => openVehicleHistoryForVin(activeVehicle.vin, protocol)}
            onOpenHistoryField={openVehicleHistoryForField}
            onOpenReplay={() => openVehicleReplayForVin()}
            onSelectVehicle={selectVehicle}
            realData={realData}
            setDetailTab={setCommandDetailTab}
          />
        )}

        {activeSection === 'replay' && (
          <ReplayPage
            activeTrack={activeTrack}
            activeVehicle={activeVehicle}
            isPlaying={isPlaying}
            onOpenHistory={openVehicleHistoryForVin}
            playbackIndex={playbackIndex}
            setIsPlaying={setIsPlaying}
            setPlaybackIndex={setPlaybackIndex}
            canQueryRealTrack={canQueryRealTrack}
            usingRealData={usingRealData}
          />
        )}

        {activeSection === 'history' && (
          <HistoryPage
            historyPage={historyPage}
            historyPageSize={historyPageSize}
            historyQueried={historyQueried}
            historyDateFrom={historyDateFrom}
            historyDateTo={historyDateTo}
            historyFieldHint={historyFieldHint}
            contextVehicle={historyContextVehicle}
            canQueryRealRaw={canQueryRealRaw}
            onClearHistoryFieldHint={() => {
              setHistoryFieldHint(undefined);
              setSelectedFields(defaultHistoryFields);
              setHistoryPage(1);
              updateAppURL('history', query || activeVehicle.vin, { protocol: protocolFilter });
            }}
            onOpenCommand={openVehicleCommandForVin}
            onOpenReplay={openVehicleReplayForVin}
            protocolFilter={protocolFilter}
            query={query}
            queryPreview={historyQueryPreview}
            records={visibleHistory}
            selectedFields={selectedFields}
            setHistoryDateFrom={setHistoryDateFrom}
            setHistoryDateTo={setHistoryDateTo}
            setHistoryPage={setHistoryPage}
            setHistoryPageSize={setHistoryPageSize}
            setHistoryQueried={setHistoryQueried}
            setSelectedFields={setSelectedFields}
          />
        )}

        {activeSection === 'alerts' && (
          <AlertsPage
            canQueryRealAlerts={canQueryRealAlerts}
            onOpenHistory={openVehicleHistoryForVin}
            onOpenReplay={openVehicleReplayForVin}
            protocolFilter={protocolFilter}
            query={query}
            sourceFilter={sourceFilter}
          />
        )}

        {activeSection === 'stats' && (
          <StatsPage
            protocolFilter={protocolFilter}
            realData={realData}
            onOpenHistory={openVehicleHistoryForVin}
            onOpenReplay={openVehicleReplayForVin}
            usingRealData={usingRealData}
            vehicles={statsVehicles}
          />
        )}

        {activeSection === 'sources' && (
          <SourcesPage
            canQueryRealSources={canQueryRealSources}
            onOpenRawHistory={openProtocolHistory}
            protocolFilter={protocolFilter}
            query={query}
          />
        )}
      </main>
    </div>
  );
}

type RealtimeModeSummary = {
  boundary: string;
  sideDetail: string;
  sideLabel: string;
  tone: 'ready' | 'loading' | 'stale' | 'error' | 'fallback' | 'disabled';
};

function realtimeModeSummary(realData: PrototypeRealDataState, usingRealData: boolean): RealtimeModeSummary {
  if (realData.status === 'ready' && usingRealData) {
    return {
      boundary: `真实实时 / ${realData.vehicles.length}/${realData.total ?? realData.vehicles.length} 条位置`,
      sideDetail: 'ECS 实时投影',
      sideLabel: '真实实时',
      tone: 'ready'
    };
  }
  if (realData.status === 'loading' && usingRealData) {
    return {
      boundary: '真实刷新中 / 保持上一批点位',
      sideDetail: '刷新中',
      sideLabel: '真实刷新中',
      tone: 'loading'
    };
  }
  if (realData.status === 'stale' && usingRealData) {
    return {
      boundary: '真实缓存 / 实时 API 当前失败',
      sideDetail: '最近一次真实快照',
      sideLabel: '真实缓存',
      tone: 'stale'
    };
  }
  if (realData.status === 'loading') {
    if (realData.error && realData.vehicles.length === 0) {
      return {
        boundary: '重试中 / 上次 realtime API 失败',
        sideDetail: '无生产车辆',
        sideLabel: '重试中',
        tone: 'loading'
      };
    }
    return {
      boundary: '读取中 / 等待 realtime API',
      sideDetail: '等待接口',
      sideLabel: '读取中',
      tone: 'loading'
    };
  }
  if (realData.status === 'error') {
    return {
      boundary: 'API 失败 / 不展示样例当前态',
      sideDetail: '无生产车辆',
      sideLabel: 'API 失败',
      tone: 'error'
    };
  }
  if (realData.status === 'fallback') {
    return {
      boundary: '真实为空 / 不展示样例当前态',
      sideDetail: '无真实车辆',
      sideLabel: '真实为空',
      tone: 'fallback'
    };
  }
  return {
    boundary: '真实数据未启用 / 当前为样例模式',
    sideDetail: '原型模式',
    sideLabel: '样例模式',
    tone: 'disabled'
  };
}

function DataBoundary({
  activeSection,
  canQueryRealAlerts,
  canQueryRealSources,
  realtimeMode,
  usingRealData
}: {
  activeSection: SectionKey;
  canQueryRealAlerts: boolean;
  canQueryRealSources: boolean;
  realtimeMode: RealtimeModeSummary;
  usingRealData: boolean;
}) {
  const currentBoundary = (() => {
    if (realtimeMode.tone === 'disabled') {
      return realtimeMode.boundary;
    }
    if (activeSection === 'history') {
      return '历史 RAW 独立查询 / 实时当前态不参与';
    }
    if (activeSection === 'replay') {
      return '历史轨迹独立查询 / 实时当前态不参与';
    }
    if (activeSection === 'stats') {
      return usingRealData
        ? '真实实时来源统计 / 统计 API 独立探测'
        : '统计 API 独立探测 / 不展示样例真值';
    }
    if (activeSection === 'alerts' && canQueryRealAlerts) {
      return '告警观测独立探测 / durable alert API 未接入';
    }
    if (activeSection === 'sources' && canQueryRealSources) {
      return '来源证据独立探测 / realtime 与 RAW 可部分成功';
    }
    return realtimeMode.boundary;
  })();
  const sourceBoundaries = activeSection === 'stats'
    ? usingRealData
      ? [
          { label: 'Realtime API', value: 'locations + snapshots 当前可用' },
          { label: '未接入', value: '/api/mileage/daily、/api/statistics 当前 404' }
        ]
      : [
          { label: 'Realtime API', value: 'locations + snapshots 等待返回真实来源行' },
          { label: '统计 API', value: '日里程、趋势、排名未接入前不展示真值' }
        ]
    : activeSection === 'alerts'
      ? canQueryRealAlerts
        ? [
            { label: '观测信号', value: '/api/realtime/locations 与 /api/history/locations 独立探测' },
            { label: '持久告警', value: 'durable alert 事件、通知、派单接口未接入' }
          ]
        : sectionDataBoundaries[activeSection]
    : activeSection === 'sources'
      ? canQueryRealSources
        ? [
            { label: '来源证据', value: '/api/realtime/locations 与 raw_frames/query 独立探测' },
            { label: '平台台账', value: 'vehicle_data_source / ops API 未接入前只展示端点证据' }
          ]
        : [
            { label: '来源证据', value: '等待 realtime locations 与 raw_frames 返回真实样本' },
            { label: '平台台账', value: 'vehicle_data_source / ops API 未接入前不展示真值' }
          ]
    : sectionDataBoundaries[activeSection];
  const boundaries = [
    { label: '当前口径', value: currentBoundary },
    ...sourceBoundaries
  ];
  return (
    <section className="vpc-data-boundary" aria-label="当前模块数据来源">
      <strong>当前模块数据来源</strong>
      <div>
        {boundaries.map((item) => (
          <span className="vpc-data-boundary-item" key={`${activeSection}-${item.label}`} title={`${item.label}: ${item.value}`}>
            <em>{item.label}</em>
            {' '}
            <b>{item.value}</b>
          </span>
        ))}
      </div>
    </section>
  );
}

function OperationFlow({
  filteredVehicles,
  activeVehicle,
  activeSource,
  usingRealData
}: {
  filteredVehicles: VehicleRecord[];
  activeVehicle: VehicleRecord;
  activeSource: ReturnType<typeof getVehiclePrimarySource>;
  usingRealData: boolean;
}) {
  const sourceCount = activeVehicle.sources.length;
  return (
    <section className="vpc-flow-strip" aria-label="数据流转与运营闭环">
      <div className="vpc-flow-step">
        <span>01</span>
        <strong>接收实时帧</strong>
        <em>{filteredVehicles.length} 台筛选车辆进入地图与列表</em>
      </div>
      <div className="vpc-flow-step">
        <span>02</span>
        <strong>解析扁平字段</strong>
        <em>{activeSource.sourceName} 当前 {activeSource.fieldCount} 个字段</em>
      </div>
      <div className="vpc-flow-step">
        <span>03</span>
        <strong>合并实时投影</strong>
        <em>{activeVehicle.plate} 关联 {sourceCount} 路来源</em>
      </div>
      <div className="vpc-flow-step vpc-flow-step-action">
        <span>04</span>
        <strong>证据与边界</strong>
        <em>{usingRealData ? '告警/质量 API 未接入，当前只输出观测信号' : `${alertEvents.length} 条本地样例事件，仅验证交互`}</em>
      </div>
    </section>
  );
}

function getRealtimeKpisForVehicles(filteredVehicles: VehicleRecord[], protocolFilter: ProtocolFilter = 'ALL') {
  const sources = filteredVehicles.flatMap((vehicle) =>
    vehicle.sources.filter((source) => protocolFilter === 'ALL' || source.protocol === protocolFilter)
  );
  const online = filteredVehicles.filter((vehicle) => vehicle.status === 'online').length;
  const movingSources = sources.filter((source) => (source.speedKph ?? 0) > 0).length;
  const totalMileage = sources.reduce((sum, source) => sum + (source.totalMileageKm ?? 0), 0);
  const fieldCount = sources.reduce((sum, source) => sum + source.fieldCount, 0);
  const avgLatency = Math.round(sources.reduce((sum, source) => sum + source.latencyMs, 0) / Math.max(sources.length, 1));
  return [
    { label: '筛选车辆', value: formatNumber(filteredVehicles.length), sub: `在线 ${online} / 来源行 ${sources.length}`, tone: 'blue' },
    { label: '实时行驶', value: String(movingSources), sub: '按来源车速 > 0 判断', tone: 'green' },
    { label: '最新总里程', value: `${formatNumber(totalMileage, 1)} km`, sub: '按当前来源行合计', tone: 'orange' },
    { label: '字段/延迟', value: `${formatNumber(fieldCount)}`, sub: `字段数 / 平均 ${avgLatency} ms`, tone: 'cyan' }
  ] as const;
}

function GlobalFilters({
  activeSection,
  protocolFilter,
  setProtocolFilter,
  freshnessFilter,
  setFreshnessFilter,
  statusFilter,
  setStatusFilter,
  sourceFilter,
  setSourceFilter,
  sourceOptions
}: {
  activeSection: SectionKey;
  protocolFilter: ProtocolFilter;
  setProtocolFilter: (value: ProtocolFilter) => void;
  freshnessFilter: FreshnessFilter;
  setFreshnessFilter: (value: FreshnessFilter) => void;
  statusFilter: StatusFilter;
  setStatusFilter: (value: StatusFilter) => void;
  sourceFilter: string;
  setSourceFilter: (value: string) => void;
  sourceOptions: Array<{ value: string; label: string }>;
}) {
  const isHistory = activeSection === 'history';
  const isReplay = activeSection === 'replay';
  const isStats = activeSection === 'stats';
  const isAlerts = activeSection === 'alerts';
  const isSources = activeSection === 'sources';
  const isEvidenceQuery = isHistory || isReplay;
  const onlyUsesProtocol = isEvidenceQuery || isStats || isAlerts || isSources;
  const sourceSelectOptions = [
    { value: 'ALL', label: sourceOptions.length === 0 ? '真实来源待读取' : '全部来源' },
    ...sourceOptions
  ];
  const sourceSelectValue = sourceSelectOptions.some((option) => option.value === sourceFilter) ? sourceFilter : 'ALL';
  return (
    <section className="vpc-filterbar" aria-label="全局筛选">
      <AppSelect ariaLabel="协议筛选" onChange={setProtocolFilter} options={protocolFilterOptions} value={protocolFilter} />
      {!onlyUsesProtocol && <AppSelect ariaLabel="状态筛选" onChange={setStatusFilter} options={statusFilterOptions} value={statusFilter} />}
      {!onlyUsesProtocol && (
        <AppSelect
          ariaLabel="来源筛选"
          onChange={setSourceFilter}
          options={sourceSelectOptions}
          value={sourceSelectValue}
        />
      )}
      {!onlyUsesProtocol && <AppSelect ariaLabel="新鲜度筛选" onChange={setFreshnessFilter} options={freshnessFilterOptions} value={freshnessFilter} />}
      <div className="vpc-filter-hint">
        {isHistory ? (
          <>
            <span>RAW 按 VIN / 协议 / 字段查询</span>
            <span>状态和来源不参与历史 RAW 请求</span>
          </>
        ) : isReplay ? (
          <>
            <span>轨迹按 VIN / 时间窗查询</span>
            <span>状态和来源不参与轨迹回放请求</span>
          </>
        ) : isStats ? (
          <>
            <span>统计按搜索车辆池 / 协议计算</span>
            <span>状态和来源筛选不参与统计快照</span>
          </>
        ) : isAlerts ? (
          <>
            <span>告警按观测信号 / 协议查询</span>
            <span>状态和来源筛选不参与告警观测</span>
          </>
        ) : isSources ? (
          <>
            <span>来源按搜索词 / 协议筛选</span>
            <span>状态和来源筛选不参与端点证据</span>
          </>
        ) : (
          <>
            <span>实时帧进入展示，支持最近上报时间筛选</span>
            <span>{sourceOptions.length === 0 ? '真实来源未返回，来源筛选等待 realtime 数据' : '登录/鉴权只进入接入审计'}</span>
          </>
        )}
      </div>
    </section>
  );
}

function realtimeErrorDetail(error?: string) {
  const message = String(error ?? '').trim();
  if (!message) {
    return '等待接口响应';
  }
  const normalized = message.toLowerCase();
  if (
    normalized.includes('request timeout') ||
    normalized.includes('abort') ||
    normalized.includes('signal is aborted')
  ) {
    const timeoutMatch = message.match(/after\s+(\d+)ms/i);
    const timeoutText = timeoutMatch ? `${Math.round(Number(timeoutMatch[1]) / 1000)} 秒` : '超时时间内';
    return `实时接口超时，后端未在 ${timeoutText}内返回`;
  }
  if (normalized.includes('http 500')) {
    return normalized.includes('empty response body')
      ? '实时接口返回 500 且响应体为空，需要检查 BFF 日志或数据库依赖'
      : '实时接口返回 500，需要检查 BFF 或数据库依赖';
  }
  if (normalized.includes('http 404')) {
    return '实时接口未部署或路径不匹配';
  }
  if (normalized.includes('failed to fetch') || normalized.includes('network')) {
    return '实时接口网络不可达或连接被关闭';
  }
  if (normalized.includes('empty')) {
    return '实时接口暂未返回车辆数据';
  }
  return `实时接口异常：${message}`;
}

function realtimeHTTPStatus(error?: string) {
  const match = String(error ?? '').match(/HTTP\s+(\d{3})/i);
  return match ? match[1] : undefined;
}

function realtimeHTTPBodyState(error?: string) {
  const message = String(error ?? '').trim();
  if (!message || !/HTTP\s+\d{3}/i.test(message)) {
    return undefined;
  }
  return message.toLowerCase().includes('empty response body') ? '空 body' : '有错误明细';
}

function firstRequestSource(source: string) {
  return String(source).split(' / ')[0].trim();
}

function absoluteRuntimeURL(source: string) {
  const requestSource = firstRequestSource(source);
  if (!requestSource) {
    return '';
  }
  if (/^https?:\/\//i.test(requestSource)) {
    return requestSource;
  }
  if (typeof window === 'undefined') {
    return requestSource;
  }
  const path = requestSource.startsWith('/') ? requestSource : `/${requestSource}`;
  return `${window.location.origin}${path}`;
}

function shellQuote(value: string) {
  return `'${value.replace(/'/g, `'\\''`)}'`;
}

function curlForRuntimeSource(source: string) {
  const url = absoluteRuntimeURL(source);
  return url ? `curl -i --max-time 12 ${shellQuote(url)}` : 'n/a';
}

function amapConfigDiagnostic() {
  const config = getAMapConfig();
  if (!config.webJsKey) {
    return 'web-js-key:missing, security:not-configured';
  }
  if (config.securityServiceHost) {
    return `web-js-key:configured, security-proxy:${config.securityServiceHost}`;
  }
  if (config.securityJsCode) {
    return 'web-js-key:configured, security:browser-js-code';
  }
  return 'web-js-key:configured, security:not-configured';
}

function realtimeDiagnosticText(
  realData: PrototypeRealDataState,
  usingRealData: boolean,
  amapRuntime: AMapRuntimeState
) {
  const httpStatus = realtimeHTTPStatus(realData.error);
  const httpBodyState = realtimeHTTPBodyState(realData.error);
  const diagnosticItems = realtimeDiagnosticItems(realData, usingRealData, amapRuntime);
  const realtimeURL = absoluteRuntimeURL(realData.source);
  return [
    '[车辆数据中台 realtime 诊断]',
    `time=${new Date().toLocaleString('zh-CN', { hour12: false })}`,
    `source=${realData.source}`,
    `request=${realtimeURL || firstRequestSource(realData.source) || 'n/a'}`,
    `curl=${curlForRuntimeSource(realData.source)}`,
    `status=${realData.status}`,
    `vehicles=${realData.vehicles.length}`,
    `total=${realData.total ?? realData.vehicles.length}`,
    `usingRealData=${usingRealData ? 'yes' : 'no'}`,
    `httpStatus=${httpStatus ?? 'n/a'}`,
    `responseBody=${httpBodyState ?? 'n/a'}`,
    `error=${realData.error ?? 'n/a'}`,
    `message=${realtimeErrorDetail(realData.error)}`,
    `amap=${amapRuntime.label} / ${amapRuntime.detail}`,
    `amapConfig=${amapConfigDiagnostic()}`,
    `diagnostics=${diagnosticItems.map((item) => `${item.label}:${item.value}`).join(', ')}`
  ].join('\n');
}

async function copyTextWithFallback(value: string) {
  try {
    await navigator.clipboard.writeText(value);
    return;
  } catch {
    // Some embedded/local browser contexts deny Clipboard API writes even after a click.
  }
  const textarea = document.createElement('textarea');
  textarea.value = value;
  textarea.setAttribute('readonly', 'true');
  textarea.style.position = 'fixed';
  textarea.style.left = '-9999px';
  textarea.style.top = '0';
  document.body.appendChild(textarea);
  textarea.select();
  const copied = document.execCommand('copy');
  document.body.removeChild(textarea);
  if (!copied) {
    throw new Error('copy command failed');
  }
}

function RealDataStatus({
  amapRuntime,
  realData,
  usingRealData,
  autoRefresh,
  onAutoRefreshChange,
  onRefresh
}: {
  amapRuntime: AMapRuntimeState;
  realData: PrototypeRealDataState;
  usingRealData: boolean;
  autoRefresh: boolean;
  onAutoRefreshChange: Dispatch<SetStateAction<boolean>>;
  onRefresh: () => void;
}) {
  const [copyState, setCopyState] = useState<'idle' | 'copied' | 'manual'>('idle');
  const diagnosticTextareaRef = useRef<HTMLTextAreaElement | null>(null);
  const retryingWithoutRealtime = realData.status === 'loading' && Boolean(realData.error) && realData.vehicles.length === 0;
  const statusText: Record<PrototypeRealDataState['status'], string> = {
    disabled: '真实数据未启用',
    loading: '读取真实数据中',
    ready: '真实数据已接入',
    stale: '真实缓存数据',
    fallback: '真实数据为空',
    error: '真实数据读取失败'
  };
  const statusTitle = retryingWithoutRealtime ? '真实接口重试中' : statusText[realData.status];
  const statusClass = realData.status;
  const statusDetail = realData.status === 'stale'
    ? `${realData.fetchedAt ? `缓存 ${realData.fetchedAt}` : '使用最近一次真实缓存'}${realData.error ? ` / ${realtimeErrorDetail(realData.error)}` : ''}`
    : realData.fetchedAt
      ? `刷新 ${realData.fetchedAt}`
      : realtimeErrorDetail(realData.error);
  const dataModeText = usingRealData
    ? `${realData.vehicles.length} 台车辆 / ${realData.total ?? realData.vehicles.length} 条实时记录`
    : realData.status === 'disabled'
      ? '当前展示本地样例数据'
      : '未展示生产车辆，等待真实接口';
  const diagnosticItems = realtimeDiagnosticItems(realData, usingRealData, amapRuntime);
  const diagnosticText = realtimeDiagnosticText(realData, usingRealData, amapRuntime);
  const selectDiagnosticText = useCallback(() => {
    const textarea = diagnosticTextareaRef.current;
    if (!textarea) {
      return;
    }
    textarea.focus();
    textarea.select();
    textarea.setSelectionRange(0, textarea.value.length);
  }, []);

  useEffect(() => {
    if (copyState !== 'manual') {
      return;
    }
    const timer = window.setTimeout(selectDiagnosticText, 0);
    return () => {
      window.clearTimeout(timer);
    };
  }, [copyState, diagnosticText, selectDiagnosticText]);

  const copyDiagnostics = async () => {
    if (copyState === 'manual') {
      selectDiagnosticText();
      return;
    }
    try {
      await copyTextWithFallback(diagnosticText);
      setCopyState('copied');
      window.setTimeout(() => setCopyState('idle'), 1600);
    } catch {
      setCopyState('manual');
    }
  };
  return (
    <section className={`vpc-real-data-status vpc-real-data-${statusClass}`} aria-label="真实数据接入状态">
      <div>
        <strong>{statusTitle}</strong>
        <span>{dataModeText}</span>
      </div>
      <em>{statusDetail}</em>
      <code>{realData.source}</code>
      <div className="vpc-real-data-diagnostics" aria-label="生产链路诊断">
        {diagnosticItems.map((item) => (
          <span className={`vpc-real-data-diagnostic vpc-real-data-diagnostic-${item.tone}`} key={item.label}>
            <em>{item.label}</em>
            <b>{item.value}</b>
          </span>
        ))}
      </div>
      <div className="vpc-real-data-status-actions" aria-label="真实数据刷新控制">
        <button
          aria-label="复制真实数据诊断"
          className={copyState === 'copied' ? 'vpc-real-data-copy-ok' : copyState === 'manual' ? 'vpc-real-data-copy-manual' : ''}
          onClick={copyDiagnostics}
          type="button"
        >
          <IconCopy />
          {copyState === 'copied' ? '已复制' : copyState === 'manual' ? '手动复制' : '复制诊断'}
        </button>
        <button
          disabled={realData.status === 'loading'}
          onClick={onRefresh}
          type="button"
        >
          {retryingWithoutRealtime ? '重试中' : realData.status === 'loading' ? '刷新中' : '立即刷新'}
        </button>
        <button
          className={autoRefresh ? 'vpc-real-data-auto-active' : ''}
          onClick={() => onAutoRefreshChange((value) => !value)}
          type="button"
        >
          {autoRefresh ? '15s 自动' : '自动关闭'}
        </button>
      </div>
      {copyState === 'manual' && (
        <div className="vpc-real-data-copy-panel" aria-label="真实数据诊断文本">
          <div className="vpc-real-data-copy-panel-head">
            <span>剪贴板受限，已选中诊断文本</span>
            <button
              aria-label="收起真实数据诊断文本"
              onClick={() => setCopyState('idle')}
              type="button"
            >
              收起
            </button>
          </div>
          <textarea
            aria-label="真实数据诊断文本"
            onFocus={selectDiagnosticText}
            readOnly
            ref={diagnosticTextareaRef}
            value={diagnosticText}
          />
        </div>
      )}
    </section>
  );
}

function realtimeDiagnosticItems(
  realData: PrototypeRealDataState,
  usingRealData: boolean,
  amapRuntime: AMapRuntimeState
): Array<{ label: string; value: string; tone: DiagnosticTone }> {
  const retryingWithoutRealtime = realData.status === 'loading' && Boolean(realData.error) && realData.vehicles.length === 0;
  const httpStatus = realtimeHTTPStatus(realData.error);
  const httpBodyState = realtimeHTTPBodyState(realData.error);
  const apiState: Record<PrototypeRealDataState['status'], { value: string; tone: 'ok' | 'warn' | 'error' | 'idle' }> = {
    disabled: { value: '未启用', tone: 'idle' },
    loading: retryingWithoutRealtime ? { value: httpStatus ? `重试中 HTTP ${httpStatus}` : '重试中', tone: 'warn' } : { value: '请求中', tone: 'warn' },
    ready: { value: '已返回', tone: 'ok' },
    stale: { value: '使用缓存', tone: 'warn' },
    fallback: { value: '空响应', tone: 'warn' },
    error: { value: httpStatus ? `HTTP ${httpStatus}` : '请求失败', tone: 'error' }
  };
  const items: Array<{ label: string; value: string; tone: DiagnosticTone }> = [
    { label: 'Realtime API', ...apiState[realData.status] },
    {
      label: 'Redis/MySQL',
      value: usingRealData ? '可展示' : realData.status === 'loading' ? '等待 API' : '无真实投影',
      tone: usingRealData ? 'ok' : realData.status === 'loading' ? 'warn' : 'error'
    },
    {
      label: 'AMap',
      value: amapRuntime.diagnosticValue,
      tone: amapRuntime.tone
    }
  ];
  if (httpBodyState) {
    items.splice(1, 0, {
      label: '响应体',
      value: httpBodyState,
      tone: httpBodyState === '空 body' ? 'warn' : 'idle'
    });
  }
  return items;
}

function CommandCenter({
  filteredVehicles,
  activeVehicle,
  activeSource,
  activeAlerts,
  amapRuntime,
  detailTab,
  setDetailTab,
  onSelectVehicle,
  onOpenReplay,
  onOpenHistoryField,
  onOpenHistory,
  realData
}: {
  filteredVehicles: VehicleRecord[];
  activeVehicle: VehicleRecord;
  activeSource: ReturnType<typeof getVehiclePrimarySource>;
  activeAlerts: AlertEvent[];
  amapRuntime: AMapRuntimeState;
  detailTab: DetailTab;
  setDetailTab: (tab: DetailTab) => void;
  onSelectVehicle: (id: string) => void;
  onOpenReplay: () => void;
  onOpenHistoryField: (vin: string, protocol: Protocol, fieldKey: string) => void;
  onOpenHistory: (protocol?: Protocol) => void;
  realData: PrototypeRealDataState;
}) {
  const realtimeSummary = getRealtimeSummary(filteredVehicles);
  const qualityBuckets = useMemo(() => buildRealtimeQualityBuckets(filteredVehicles), [filteredVehicles]);
  const commandPriorities = useMemo(() => getCommandPriorityItems(filteredVehicles), [filteredVehicles]);
  const capabilityRadar = useMemo(() => buildDataCapabilityRadar({
    vehicles: filteredVehicles,
    realtimeStatus: realData.status,
    realtimeTotal: realData.total,
    amapStatus: amapRuntime.status === 'not-configured' ? 'disabled' : amapRuntime.status,
    rawQueryEnabled: realData.status !== 'disabled',
    trackQueryEnabled: realData.status !== 'disabled'
  }), [amapRuntime.status, filteredVehicles, realData.status, realData.total]);
  const capabilityStateMeta = {
    ready: { label: '可用', color: 'green' as const },
    partial: { label: '部分', color: 'orange' as const },
    waiting: { label: '等待', color: 'blue' as const },
    unavailable: { label: '不可用', color: 'grey' as const }
  };
  return (
    <section className="vpc-command-stack">
      <CommandPriorityStrip
        activeVehicle={activeVehicle}
        items={commandPriorities}
        onSelectVehicle={onSelectVehicle}
      />
      <section className="vpc-command-grid">
        <MapPanel
          activeVehicle={activeVehicle}
          amapRuntime={amapRuntime}
          onOpenHistory={onOpenHistory}
          onOpenReplay={onOpenReplay}
          onSelectVehicle={onSelectVehicle}
          realData={realData}
          vehicles={filteredVehicles}
        />
        <VehicleList activeVehicle={activeVehicle} onSelectVehicle={onSelectVehicle} vehicles={filteredVehicles} />
        <RealtimeQualityQueue
          activeVehicle={activeVehicle}
          buckets={qualityBuckets}
          onSelectVehicle={onSelectVehicle}
        />
        {filteredVehicles.length > 0 ? (
          <VehicleDetail
            activeAlerts={activeAlerts}
            activeSource={activeSource}
            activeVehicle={activeVehicle}
            detailTab={detailTab}
            onOpenHistory={onOpenHistory}
            onOpenHistoryField={onOpenHistoryField}
            onOpenReplay={onOpenReplay}
            setDetailTab={setDetailTab}
          />
        ) : (
          <aside className="vpc-panel vpc-detail">
            <div className="vpc-empty">
              当前筛选条件下暂无实时车辆。可以放宽协议、状态、来源或新鲜度筛选。
            </div>
          </aside>
        )}
      </section>
      <section className="vpc-capability-radar" aria-label="数据能力雷达">
        <div className="vpc-capability-radar-head">
          <div>
            <strong>数据能力雷达</strong>
            <span>只根据当前真实链路和筛选车辆判断能力边界，不展示源头不能证明的功能。</span>
          </div>
          <Tag color={realData.status === 'ready' ? 'green' : realData.status === 'error' ? 'red' : 'orange'} size="small">
            {realData.status === 'ready' ? '真实已返回' : realData.status === 'error' ? '接口异常' : '链路观察'}
          </Tag>
        </div>
        <div className="vpc-capability-radar-grid">
          {capabilityRadar.map((item) => {
            const meta = capabilityStateMeta[item.state];
            return (
              <article className={`vpc-capability-card vpc-capability-${item.state}`} key={item.key}>
                <div className="vpc-capability-card-title">
                  <span>{item.title}</span>
                  <Tag color={meta.color} size="small">{meta.label}</Tag>
                </div>
                <strong>{item.metric}</strong>
                <em>{item.evidence}</em>
                <p>{item.boundary}</p>
              </article>
            );
          })}
        </div>
      </section>
      <RealtimeSummary items={realtimeSummary} />
    </section>
  );
}

function CommandPriorityStrip({
  activeVehicle,
  items,
  onSelectVehicle
}: {
  activeVehicle: VehicleRecord;
  items: ReturnType<typeof getCommandPriorityItems>;
  onSelectVehicle: (id: string) => void;
}) {
  return (
    <section className="vpc-command-priority-strip" aria-label="实时指挥优先级">
      <div className="vpc-command-priority-title">
        <span>指挥优先级</span>
        <strong>先处理会影响定位、在线和统计可信度的车辆</strong>
      </div>
      <div className="vpc-command-priority-items">
        {items.map((item) => {
          const targetId = item.vehicleIds[0];
          const active = Boolean(targetId && item.vehicleIds.includes(activeVehicle.id));
          return (
            <button
              aria-label={`${item.title} ${item.value} 台`}
              className={`vpc-command-priority-item vpc-command-priority-${item.tone} ${active ? 'vpc-command-priority-active' : ''}`}
              disabled={!targetId}
              key={item.key}
              onClick={() => targetId && onSelectVehicle(targetId)}
              type="button"
            >
              <span>{item.title}</span>
              <strong>{item.value}</strong>
              <em>{item.detail}</em>
            </button>
          );
        })}
      </div>
    </section>
  );
}

function RealtimeQualityQueue({
  buckets,
  activeVehicle,
  onSelectVehicle
}: {
  buckets: RealtimeQualityBucket[];
  activeVehicle: VehicleRecord;
  onSelectVehicle: (id: string) => void;
}) {
  return (
    <section className="vpc-realtime-quality" aria-label="实时数据质量队列">
      <div className="vpc-realtime-quality-head">
        <div>
          <strong>实时数据质量队列</strong>
          <span>从当前筛选车辆的实时投影派生，点击车辆可定位到地图与详情。</span>
        </div>
        <Tag color="blue" size="small">realtime locations</Tag>
      </div>
      <div className="vpc-realtime-quality-grid">
        {buckets.map((bucket) => (
          <article className={`vpc-quality-card vpc-quality-${bucket.tone}`} key={bucket.key}>
            <div className="vpc-quality-card-main">
              <span>{bucket.title}</span>
              <strong>{bucket.count}</strong>
              <em>{bucket.detail}</em>
            </div>
            <div className="vpc-quality-samples">
              {bucket.vehicles.slice(0, 2).map((vehicle) => (
                <button
                  className={activeVehicle.id === vehicle.id ? 'vpc-quality-sample-active' : ''}
                  key={`${bucket.key}-${vehicle.id}`}
                  onClick={() => onSelectVehicle(vehicle.id)}
                  type="button"
                >
                  <span>{vehicle.plate}</span>
                  <em>{getVehiclePrimarySource(vehicle).lastSeen}</em>
                </button>
              ))}
              {bucket.vehicles.length === 0 && <span className="vpc-quality-empty">暂无车辆</span>}
              {bucket.vehicles.length > 2 && <span className="vpc-quality-more">+{bucket.vehicles.length - 2} 台</span>}
            </div>
          </article>
        ))}
      </div>
    </section>
  );
}

function RealtimeSummary({ items }: { items: ReturnType<typeof getRealtimeSummary> }) {
  return (
    <section className="vpc-realtime-summary" aria-label="实时投影摘要">
      {items.map((item) => (
        <article className={`vpc-realtime-summary-card vpc-realtime-summary-${item.tone}`} key={item.label}>
          <span>{item.label}</span>
          <strong>{item.value}</strong>
          <em>{item.sub}</em>
        </article>
      ))}
    </section>
  );
}

function VehicleList({
  vehicles: visibleVehicles,
  activeVehicle,
  onSelectVehicle
}: {
  vehicles: VehicleRecord[];
  activeVehicle: VehicleRecord;
  onSelectVehicle: (id: string) => void;
}) {
  const activeRowRef = useRef<HTMLButtonElement | null>(null);

  useEffect(() => {
    const row = activeRowRef.current;
    const scroller = row?.closest<HTMLElement>('.vpc-list-scroll');
    if (!row || !scroller) {
      return;
    }
    const rowTop = row.offsetTop;
    const rowBottom = rowTop + row.offsetHeight;
    const visibleTop = scroller.scrollTop;
    const visibleBottom = visibleTop + scroller.clientHeight;
    if (rowTop < visibleTop) {
      scroller.scrollTop = rowTop;
    } else if (rowBottom > visibleBottom) {
      scroller.scrollTop = rowBottom - scroller.clientHeight;
    }
  }, [activeVehicle.id]);

  return (
    <aside className="vpc-panel vpc-vehicle-list">
      <div className="vpc-panel-head">
        <strong>车辆列表</strong>
        <Tag size="small">{visibleVehicles.length} 台</Tag>
      </div>
      <div className="vpc-list-scroll">
        {visibleVehicles.length === 0 ? (
          <div className="vpc-empty">当前筛选条件下暂无车辆</div>
        ) : visibleVehicles.map((vehicle) => {
          const source = getVehiclePrimarySource(vehicle);
          return (
            <button
              aria-current={activeVehicle.id === vehicle.id ? 'true' : undefined}
              className={`vpc-vehicle-row ${activeVehicle.id === vehicle.id ? 'vpc-vehicle-row-active' : ''}`}
              data-vehicle-row-id={vehicle.id}
              key={vehicle.id}
              onClick={() => onSelectVehicle(vehicle.id)}
              ref={activeVehicle.id === vehicle.id ? activeRowRef : undefined}
              type="button"
            >
              <span className={`vpc-dot vpc-dot-${vehicle.status}`} />
              <span className="vpc-vehicle-row-copy">
                <strong>{vehicle.plate}</strong>
                <em>{vehicle.vin}</em>
                <small>{source.sourceName}</small>
              </span>
              <span className="vpc-row-metric">
                <Tag color={protocolMeta[source.protocol].color} size="small">{protocolMeta[source.protocol].short}</Tag>
                {source.speedKph ?? 0} km/h
                <em>{source.lastSeen}</em>
              </span>
            </button>
          );
        })}
      </div>
    </aside>
  );
}

function amapSecurityMode(config: ReturnType<typeof getAMapConfig>) {
  if (config.securityServiceHost) {
    return { label: '安全代理', detail: config.securityServiceHost, color: 'green' as const };
  }
  if (config.securityJsCode) {
    return { label: '本地调试', detail: '前端安全码模式', color: 'orange' as const };
  }
  return { label: '未配置', detail: '未启用安全码或代理', color: 'grey' as const };
}

function mapAddressStatusLabel(state: PrototypeMapAddressState) {
  if (state.status === 'ready') {
    if (state.error && state.provider === 'AMap Web JS') return 'AMap Web JS 兜底';
    return state.provider ? `${state.provider} 已解析` : '已解析';
  }
  if (state.status === 'loading') return '解析中';
  if (state.status === 'unavailable') return '服务端未接入';
  if (state.status === 'error') return '解析失败';
  return '未启用';
}

function mapAddressStatusColor(state: PrototypeMapAddressState) {
  if (state.status === 'ready') return state.error ? 'orange' as const : 'green' as const;
  if (state.status === 'loading') return 'blue' as const;
  if (state.status === 'error') return 'red' as const;
  if (state.status === 'unavailable') return 'orange' as const;
  return 'grey' as const;
}

function mapAddressEvidenceTone(state: PrototypeMapAddressState): DiagnosticTone {
  if (state.status === 'ready') return state.error ? 'warn' : 'ok';
  if (state.status === 'loading') return 'warn';
  if (state.status === 'error') return 'error';
  return 'idle';
}

function mapAddressEvidenceDetail(state: PrototypeMapAddressState) {
  if (state.status === 'ready') {
    if (state.error) {
      return `${state.error}；已用 AMap Web JS 完成地址解析`;
    }
    return state.region || state.source;
  }
  return state.error ?? state.source;
}

function rawAddressToneColor(tone: ReturnType<typeof rawCoordinateAddressEvidence>['tone']) {
  if (tone === 'ready') return 'green' as const;
  if (tone === 'error') return 'red' as const;
  if (tone === 'warning') return 'orange' as const;
  return 'blue' as const;
}

function hasVehicleCoordinate(vehicle: VehicleRecord) {
  return isValidAMapCoordinate(vehicle.longitude, vehicle.latitude);
}

function hasTrackPointCoordinate(point?: TrackPoint) {
  return Boolean(
    point?.longitude != null &&
    point?.latitude != null &&
    isValidAMapCoordinate(point.longitude, point.latitude)
  );
}

function amapVehicleMarkerURL(vehicle: VehicleRecord) {
  return buildAMapMarkerURL({
    longitude: vehicle.longitude,
    latitude: vehicle.latitude,
    name: `${vehicle.plate || vehicle.vin} ${vehicle.vin}`
  });
}

function amapTrackPointMarkerURL(vehicle: VehicleRecord, point: TrackPoint) {
  if (!hasTrackPointCoordinate(point)) {
    return '';
  }
  return buildAMapMarkerURL({
    longitude: point.longitude ?? 0,
    latitude: point.latitude ?? 0,
    name: `${vehicle.plate || vehicle.vin} ${vehicle.vin} ${point.time}`
  });
}

type TrackQualityAudit = {
  status: 'ok' | 'warning' | 'empty';
  title: string;
  detail: string;
  pointCount: number;
  gpsDistanceKm: number;
  mileageDeltaKm: number;
  duplicateCoordinateSegments: number;
  stationarySegments: number;
  maxGapMinutes?: number;
  timeRange: string;
};

type TrackTimeWindowAudit = {
  status: 'ok' | 'warning' | 'empty';
  title: string;
  detail: string;
  queryRange: string;
  pointRange: string;
  outsidePointCount: number;
  pointCount: number;
};

function coordinateDistanceKm(left: TrackPoint, right: TrackPoint) {
  if (!hasTrackPointCoordinate(left) || !hasTrackPointCoordinate(right)) {
    return 0;
  }
  const earthRadiusKm = 6371;
  const toRad = (value: number) => (value * Math.PI) / 180;
  const lat1 = toRad(left.latitude ?? 0);
  const lat2 = toRad(right.latitude ?? 0);
  const deltaLat = toRad((right.latitude ?? 0) - (left.latitude ?? 0));
  const deltaLng = toRad((right.longitude ?? 0) - (left.longitude ?? 0));
  const a = Math.sin(deltaLat / 2) ** 2 + Math.cos(lat1) * Math.cos(lat2) * Math.sin(deltaLng / 2) ** 2;
  return 2 * earthRadiusKm * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
}

function trackPointTimeLabel(point?: TrackPoint) {
  if (!point) {
    return '--';
  }
  if (point.timestampMs && Number.isFinite(point.timestampMs)) {
    return chinaShortDateTime(new Date(point.timestampMs).toISOString());
  }
  return point.time || '--';
}

function buildTrackQualityAudit(points: TrackPoint[]): TrackQualityAudit {
  if (points.length === 0) {
    return {
      status: 'empty',
      title: '无轨迹点',
      detail: '当前查询窗口没有返回可计算的 vehicle_locations 点。',
      pointCount: 0,
      gpsDistanceKm: 0,
      mileageDeltaKm: 0,
      duplicateCoordinateSegments: 0,
      stationarySegments: 0,
      timeRange: '--'
    };
  }
  let gpsDistanceKm = 0;
  let duplicateCoordinateSegments = 0;
  let stationarySegments = 0;
  let maxGapMinutes = 0;
  for (let index = 1; index < points.length; index += 1) {
    const previous = points[index - 1];
    const current = points[index];
    const distance = coordinateDistanceKm(previous, current);
    gpsDistanceKm += distance;
    if (hasTrackPointCoordinate(previous) && hasTrackPointCoordinate(current) && distance < 0.01) {
      duplicateCoordinateSegments += 1;
    }
    if (distance < 0.02 && current.speedKph <= 1) {
      stationarySegments += 1;
    }
    if (
      previous.timestampMs &&
      current.timestampMs &&
      Number.isFinite(previous.timestampMs) &&
      Number.isFinite(current.timestampMs)
    ) {
      maxGapMinutes = Math.max(maxGapMinutes, Math.abs(current.timestampMs - previous.timestampMs) / 60000);
    }
  }
  const mileageDeltaKm = points.length > 1
    ? Math.max(0, points[points.length - 1].mileageKm - points[0].mileageKm)
    : 0;
  const duplicateRatio = points.length > 1 ? duplicateCoordinateSegments / (points.length - 1) : 0;
  const hasWarning = maxGapMinutes > 10 || duplicateRatio > 0.7 || points.length < 5;
  return {
    status: hasWarning ? 'warning' : 'ok',
    title: hasWarning ? '轨迹需关注' : '轨迹连续可用',
    detail: hasWarning
      ? '存在较大时间间隔、重复坐标比例过高或点数不足，回放时需结合 RAW/位置明细确认。'
      : '轨迹点、时间间隔和坐标变化在当前查询结果内可用于回放观察。',
    pointCount: points.length,
    gpsDistanceKm,
    mileageDeltaKm,
    duplicateCoordinateSegments,
    stationarySegments,
    maxGapMinutes,
    timeRange: `${trackPointTimeLabel(points[0])} - ${trackPointTimeLabel(points[points.length - 1])}`
  };
}

function buildTrackTimeWindowAudit({
  points,
  dateFrom,
  dateTo
}: {
  points: TrackPoint[];
  dateFrom: string;
  dateTo: string;
}): TrackTimeWindowAudit {
  const hasDateFrom = dateFrom.trim().length > 0;
  const hasDateTo = dateTo.trim().length > 0;
  const hasBoundedWindow = hasDateFrom || hasDateTo;
  const from = parsePrototypeDateTime(dateFrom);
  const to = parsePrototypeDateTime(dateTo);
  const pointTimes = points.map((point) => point.timestampMs ?? NaN);
  const validPointTimes = pointTimes.filter(Number.isFinite);
  const queryRange = hasBoundedWindow && Number.isFinite(from) && Number.isFinite(to)
    ? `${formatAuditDateTime(from)} - ${formatAuditDateTime(to)}`
    : hasBoundedWindow
      ? '--'
      : '未限定时间窗';
  const pointRange = rangeText(validPointTimes);

  if (points.length === 0) {
    return {
      status: 'empty',
      title: '等待返回点',
      detail: '当前查询还没有可核验的 vehicle_locations 时间点。',
      queryRange,
      pointRange,
      outsidePointCount: 0,
      pointCount: 0
    };
  }

  if (!hasBoundedWindow) {
    return {
      status: 'ok',
      title: '最新轨迹模式',
      detail: '当前未传 dateFrom/dateTo，服务端按最新位置点返回；适合确认车辆是否仍有实时轨迹写入。',
      queryRange,
      pointRange,
      outsidePointCount: 0,
      pointCount: points.length
    };
  }

  if (!Number.isFinite(from) || !Number.isFinite(to)) {
    return {
      status: 'warning',
      title: '查询时间不可解析',
      detail: '开始时间或结束时间无法解析，TDengine 查询结果不能做时间窗核验。',
      queryRange,
      pointRange,
      outsidePointCount: 0,
      pointCount: points.length
    };
  }

  if (validPointTimes.length === 0) {
    return {
      status: 'warning',
      title: '返回点缺少时间戳',
      detail: '轨迹点没有可解析的 ts/received_at，回放只能做坐标观察，不能证明时间窗正确。',
      queryRange,
      pointRange,
      outsidePointCount: 0,
      pointCount: points.length
    };
  }

  const outsidePointCount = validPointTimes.filter((time) => time < from || time > to).length;
  if (outsidePointCount > 0) {
    return {
      status: 'warning',
      title: '返回点超出查询窗',
      detail: `${outsidePointCount}/${validPointTimes.length} 个位置点不在当前查询时间窗内，需要核对 TDengine 查询使用的是设备时间、接收时间还是表 ts。`,
      queryRange,
      pointRange,
      outsidePointCount,
      pointCount: points.length
    };
  }

  return {
    status: 'ok',
    title: '查询窗核验通过',
    detail: 'TDengine 返回点时间落在当前查询窗内，可继续结合 AMap 底图做轨迹回放和 RAW 回查。',
    queryRange,
    pointRange,
    outsidePointCount,
    pointCount: points.length
  };
}

type RawTimeWindowAudit = {
  status: 'ok' | 'warning' | 'empty';
  title: string;
  detail: string;
  receiveRange: string;
  deviceRange: string;
  outsideReceiveCount: number;
  deviceSkewCount: number;
};

function rawFieldHitCount(records: PrototypeRawFrameState['records'], field: string) {
  const normalized = field.toLowerCase();
  return records.reduce((sum, record) => {
    return Object.keys(record.parsedFields).some((key) => key.toLowerCase() === normalized) ? sum + 1 : sum;
  }, 0);
}

function rawRecordEvidenceScore(record: PrototypeRawFrameState['records'][number]) {
  const coordinateScore = rawCoordinateEvidence(record.protocol, record.parsedFields) ? 1000 : 0;
  const fieldScore = record.fieldCount * 10;
  const realtimeFrameScore = /0x0?2|实时|位置|遥测/i.test(record.frameType) ? 5 : 0;
  return coordinateScore + fieldScore + realtimeFrameScore;
}

function pickPreferredRawRecord(records: PrototypeRawFrameState['records']) {
  return records.slice().sort((left, right) => rawRecordEvidenceScore(right) - rawRecordEvidenceScore(left))[0];
}

function amapRawMarkerURL(record: PrototypeRawFrameState['records'][number], evidence: RawCoordinateEvidence) {
  return buildAMapMarkerURL({
    longitude: evidence.longitude,
    latitude: evidence.latitude,
    name: `${record.vin} ${record.frameType} ${record.deviceTime || record.receiveTime}`
  });
}

function hasAlertSignalCoordinate(signal?: PrototypeAlertSignal) {
  return Boolean(
    signal?.longitude != null &&
    signal?.latitude != null &&
    isValidAMapCoordinate(signal.longitude, signal.latitude)
  );
}

function amapAlertSignalMarkerURL(signal: PrototypeAlertSignal) {
  if (!hasAlertSignalCoordinate(signal)) {
    return '';
  }
  return buildAMapMarkerURL({
    longitude: signal.longitude ?? 0,
    latitude: signal.latitude ?? 0,
    name: `${signal.plate || signal.vin || signal.title} ${signal.time}`
  });
}

function parsePrototypeDateTime(value?: string) {
  const normalized = String(value ?? '').trim();
  if (!normalized || normalized === '--') {
    return NaN;
  }
  const withDashDate = normalized.replace(/\//g, '-');
  const hasZone = /(?:Z|[+-]\d{2}:?\d{2})$/.test(withDashDate);
  const hasTime = withDashDate.includes('T') || withDashDate.includes(' ');
  const isoLike = withDashDate.includes('T') ? withDashDate : withDashDate.replace(' ', 'T');
  const candidate = hasTime && !hasZone ? `${isoLike}+08:00` : isoLike;
  return Date.parse(candidate);
}

function formatAuditDateTime(timestamp: number) {
  if (!Number.isFinite(timestamp)) {
    return '--';
  }
  return new Intl.DateTimeFormat('zh-CN', {
    timeZone: 'Asia/Shanghai',
    month: '2-digit',
    day: '2-digit',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false
  }).format(new Date(timestamp));
}

function rangeText(values: number[]) {
  const valid = values.filter(Number.isFinite).sort((left, right) => left - right);
  if (valid.length === 0) {
    return '--';
  }
  return `${formatAuditDateTime(valid[0])} - ${formatAuditDateTime(valid[valid.length - 1])}`;
}

function buildRawTimeWindowAudit({
  records,
  dateFrom,
  dateTo
}: {
  records: PrototypeRawFrameState['records'];
  dateFrom: string;
  dateTo: string;
}): RawTimeWindowAudit {
  if (records.length === 0) {
    return {
      status: 'empty',
      title: '等待 RAW 返回',
      detail: '当前页没有可核验的 RAW 记录。',
      receiveRange: '--',
      deviceRange: '--',
      outsideReceiveCount: 0,
      deviceSkewCount: 0
    };
  }
  const from = parsePrototypeDateTime(dateFrom);
  const to = parsePrototypeDateTime(dateTo);
  const receiveTimes = records.map((record) => parsePrototypeDateTime(record.receiveTime));
  const deviceTimes = records.map((record) => parsePrototypeDateTime(record.deviceTime));
  const outsideReceiveCount = receiveTimes.filter((time) =>
    Number.isFinite(time) &&
    Number.isFinite(from) &&
    Number.isFinite(to) &&
    (time < from || time > to)
  ).length;
  const deviceSkewCount = records.filter((record) => {
    const receive = parsePrototypeDateTime(record.receiveTime);
    const device = parsePrototypeDateTime(record.deviceTime);
    return Number.isFinite(receive) && Number.isFinite(device) && Math.abs(receive - device) > 60_000;
  }).length;
  if (outsideReceiveCount > 0) {
    return {
      status: 'warning',
      title: '接收时间与查询窗不一致',
      detail: `${outsideReceiveCount} 条 RAW 的接收时间不在当前查询时间窗内，需要核对后端 dateFrom/dateTo 使用的是接收时间、设备时间还是 TDengine ts。`,
      receiveRange: rangeText(receiveTimes),
      deviceRange: rangeText(deviceTimes),
      outsideReceiveCount,
      deviceSkewCount
    };
  }
  if (deviceSkewCount > 0) {
    return {
      status: 'warning',
      title: '设备时间与接收时间存在偏差',
      detail: `${deviceSkewCount} 条 RAW 的设备时间与接收时间相差超过 60 秒，统计或回放时需要确认采用哪个时间口径。`,
      receiveRange: rangeText(receiveTimes),
      deviceRange: rangeText(deviceTimes),
      outsideReceiveCount,
      deviceSkewCount
    };
  }
  return {
    status: 'ok',
    title: '时间窗核验通过',
    detail: '当前页 RAW 接收时间落在查询时间窗内，设备时间与接收时间未发现明显偏差。',
    receiveRange: rangeText(receiveTimes),
    deviceRange: rangeText(deviceTimes),
    outsideReceiveCount,
    deviceSkewCount
  };
}

function realtimeEvidenceMode(realData: PrototypeRealDataState) {
  if (realData.vehicles.length === 0) {
    if (realData.status === 'disabled') {
      return {
        label: '样例模式',
        detail: '非生产证据',
        subtitle: '当前接口没有可用真实车辆，地图显示本地样例点位',
        sourceTag: '本地样例',
        tone: 'orange' as const,
        sourceTone: 'grey' as const
      };
    }
    if (realData.status === 'loading') {
      return {
        label: '等待真实',
        detail: '未展示车辆',
        subtitle: '正在等待 realtime locations + snapshots，AMap 运行态见地图底座',
        sourceTag: '等待接口',
        tone: 'blue' as const,
        sourceTone: 'blue' as const
      };
    }
    if (realData.status === 'error') {
      return {
        label: '接口失败',
        detail: '无生产点位',
        subtitle: '真实 API 请求失败，AMap 保持空图并等待接口恢复',
        sourceTag: '接口异常',
        tone: 'red' as const,
        sourceTone: 'orange' as const
      };
    }
    return {
      label: '真实为空',
      detail: '无生产点位',
      subtitle: '实时接口没有返回车辆坐标，AMap 保持空图',
      sourceTag: '真实为空',
      tone: 'orange' as const,
      sourceTone: 'orange' as const
    };
  }
  if (realData.status === 'ready') {
    return {
      label: '真实实时',
      detail: 'ECS 实时投影',
      subtitle: '高德地图 / ECS 实时坐标',
      sourceTag: '实时位置',
      tone: 'green' as const,
      sourceTone: 'blue' as const
    };
  }
  if (realData.status === 'loading') {
    return {
      label: '真实刷新中',
      detail: '上一批真实数据',
      subtitle: '正在刷新 ECS 实时坐标，地图保持上一批真实点位',
      sourceTag: '刷新中',
      tone: 'blue' as const,
      sourceTone: 'blue' as const
    };
  }
  return {
    label: '真实缓存',
    detail: '最近一次真实快照',
    subtitle: '实时接口当前不可用，地图保持最近一次真实点位',
    sourceTag: realData.source.includes('session cache') ? '会话缓存' : '内存缓存',
    tone: 'orange' as const,
    sourceTone: 'orange' as const
  };
}

function diagnosticTagColor(tone: DiagnosticTone) {
  if (tone === 'ok') return 'green';
  if (tone === 'error') return 'red';
  if (tone === 'idle') return 'grey';
  return 'orange';
}

function emptyMapFallbackLabel(amapRuntime: AMapRuntimeState) {
  if (amapRuntime.status === 'ready') {
    return 'AMap SDK 已加载，等待真实车辆坐标';
  }
  if (amapRuntime.status === 'loading') {
    return 'AMap SDK 加载中，等待真实车辆坐标';
  }
  if (amapRuntime.status === 'error') {
    return 'AMap SDK 加载失败，等待真实车辆坐标';
  }
  return '高德地图未配置，等待真实车辆坐标';
}

function mapEmptyOverlayState({
  amapRuntime,
  realData,
  visibleVehicles
}: {
  amapRuntime: AMapRuntimeState;
  realData: PrototypeRealDataState;
  visibleVehicles: VehicleRecord[];
}) {
  const endpoint = firstRequestSource(realData.source) || realtimeQuerySource;
  if (visibleVehicles.length > 0) {
    return undefined;
  }
  if (realData.vehicles.length > 0) {
    return {
      tone: 'warn' as const,
      title: '当前筛选没有车辆坐标',
      detail: '真实实时数据已返回，但当前协议、状态、来源或新鲜度筛选下没有可投到地图的车辆。',
      hint: '放宽筛选条件后，地图会继续使用同一批真实实时坐标。',
      endpoint
    };
  }
  if (realData.status === 'disabled') {
    return {
      tone: 'idle' as const,
      title: '真实数据模式未启用',
      detail: '当前允许展示本地原型数据；这不是 Redis/MySQL 的生产实时坐标。',
      hint: '启用真实数据后，地图只接受 realtime locations 返回的生产车辆。',
      endpoint: '本地样例'
    };
  }
  if (realData.status === 'error') {
    return {
      tone: 'error' as const,
      title: '实时接口不可用',
      detail: realtimeErrorDetail(realData.error),
      hint: '请复制顶部诊断包，优先检查 realtime-api、MySQL 连接或 ECS 20200 反向代理。',
      endpoint
    };
  }
  if (realData.status === 'fallback') {
    return {
      tone: 'warn' as const,
      title: '真实响应没有车辆',
      detail: '实时接口已返回，但没有可展示的生产车辆坐标。',
      hint: '请核对 vehicle_realtime_location 是否有 VIN、经纬度和最近更新时间。',
      endpoint
    };
  }
  return {
    tone: realData.error ? 'warn' as const : 'idle' as const,
    title: realData.error ? '实时接口重试中' : '等待生产车辆坐标',
    detail: realData.error ? realtimeErrorDetail(realData.error) : '正在读取 realtime locations，地图不会使用本地样例点位冒充生产在线。',
    hint: amapRuntime.status === 'ready'
      ? 'AMap SDK 已加载，当前只差 realtime locations 返回生产坐标。'
      : `地图底座：${amapRuntime.label}；实时接口恢复后会自动渲染车辆点。`,
    endpoint
  };
}

function MapFoundationStrip({
  amapRuntime,
  security,
  realData,
  addressState,
  locatedCount,
  visibleCount
}: {
  amapRuntime: AMapRuntimeState;
  security: ReturnType<typeof amapSecurityMode>;
  realData: PrototypeRealDataState;
  addressState: PrototypeMapAddressState;
  locatedCount: number;
  visibleCount: number;
}) {
  const retryingWithoutRealtime = realData.status === 'loading' && Boolean(realData.error) && realData.vehicles.length === 0;
  const realtimeTone = realData.status === 'ready' || realData.status === 'stale'
    ? 'ok'
    : realData.status === 'error' || retryingWithoutRealtime
      ? 'error'
      : 'warn';
  const coordinateTone = visibleCount > 0 && locatedCount === visibleCount
    ? 'ok'
    : locatedCount > 0
      ? 'warn'
      : realData.status === 'error' || retryingWithoutRealtime
        ? 'error'
        : 'warn';
  const coordinateDetail = visibleCount > 0
    ? '来自实时位置投影'
    : retryingWithoutRealtime
      ? '实时接口重试中，暂无生产坐标'
      : realData.status === 'error'
      ? '实时接口失败，暂无生产坐标'
      : '等待实时接口返回车辆';
  return (
    <div className="vpc-map-foundation-strip" aria-label="地图与真实数据底座">
      <article className={`vpc-map-foundation-${realtimeTone}`}>
        <span>Realtime API</span>
        <strong>{realData.vehicles.length}/{realData.total ?? realData.vehicles.length} 条</strong>
        <em>{realData.source}</em>
      </article>
      <article className={`vpc-map-foundation-${coordinateTone}`}>
        <span>坐标落点</span>
        <strong>{locatedCount}/{visibleCount} 台</strong>
        <em>{coordinateDetail}</em>
      </article>
      <article className={`vpc-map-foundation-${amapRuntime.tone}`}>
        <span>AMap Web JS</span>
        <strong>{amapRuntime.label}</strong>
        <em>{amapRuntime.detail}</em>
      </article>
      <article>
        <span>地址解析</span>
        <strong>{mapAddressStatusLabel(addressState)}</strong>
        <em>{mapAddressEvidenceDetail(addressState)}</em>
      </article>
      <article>
        <span>安全策略</span>
        <strong>{security.label}</strong>
        <em>{security.detail}</em>
      </article>
    </div>
  );
}

function MapRealtimeAmapRail({
  activeSource,
  activeVehicle,
  addressState,
  amapRuntime,
  locatedCount,
  realData,
  visibleCount
}: {
  activeSource: VehicleSourceSnapshot;
  activeVehicle: VehicleRecord;
  addressState: PrototypeMapAddressState;
  amapRuntime: AMapRuntimeState;
  locatedCount: number;
  realData: PrototypeRealDataState;
  visibleCount: number;
}) {
  const realtimeTone: DiagnosticTone = realData.status === 'ready' || realData.status === 'stale'
    ? 'ok'
    : realData.status === 'error'
      ? 'error'
      : 'warn';
  const coordinateTone: DiagnosticTone = visibleCount > 0 && locatedCount === visibleCount
    ? 'ok'
    : locatedCount > 0
      ? 'warn'
      : 'error';
  const addressTone = mapAddressEvidenceTone(addressState);
  const selectedAddress = addressState.status === 'ready'
    ? addressState.address
    : activeVehicle.address;
  const evidenceItems = [
    {
      label: '实时投影',
      value: `${realData.vehicles.length}/${realData.total ?? realData.vehicles.length}`,
      detail: firstRequestSource(realData.source) || realtimeQuerySource,
      tone: realtimeTone
    },
    {
      label: '有效坐标',
      value: `${locatedCount}/${visibleCount}`,
      detail: visibleCount > 0 ? '只把有效经纬度投到高德' : '等待真实车辆坐标',
      tone: coordinateTone
    },
    {
      label: 'AMap 底图',
      value: amapRuntime.label,
      detail: amapRuntime.detail,
      tone: amapRuntime.tone
    },
    {
      label: '逆地理',
      value: mapAddressStatusLabel(addressState),
      detail: mapAddressEvidenceDetail(addressState),
      tone: addressTone
    }
  ];

  return (
    <div className="vpc-map-evidence-rail" aria-label="真实数据和高德地图证据链">
      <div className="vpc-map-evidence-copy">
        <span>真实数据 + AMap</span>
        <strong>{activeVehicle.plate} / {protocolMeta[activeSource.protocol].short}</strong>
        <em>{selectedAddress}</em>
      </div>
      <div className="vpc-map-evidence-items">
        {evidenceItems.map((item) => (
          <article className={`vpc-map-evidence-item vpc-map-evidence-${item.tone}`} key={item.label}>
            <span>{item.label}</span>
            <strong>{item.value}</strong>
            <em title={item.detail}>{item.detail}</em>
          </article>
        ))}
      </div>
    </div>
  );
}

function MapPanel({
  vehicles: visibleVehicles,
  activeVehicle,
  amapRuntime,
  onSelectVehicle,
  onOpenReplay,
  onOpenHistory,
  realData
}: {
  vehicles: VehicleRecord[];
  activeVehicle: VehicleRecord;
  amapRuntime: AMapRuntimeState;
  onSelectVehicle: (id: string) => void;
  onOpenReplay: () => void;
  onOpenHistory: (protocol?: Protocol) => void;
  realData: PrototypeRealDataState;
}) {
  const activeSource = getVehiclePrimarySource(activeVehicle);
  const amapConfig = getAMapConfig();
  const security = amapSecurityMode(amapConfig);
  const evidence = realtimeEvidenceMode(realData);
  const canOpenAmapMarker = hasVehicleCoordinate(activeVehicle);
  const [addressState, setAddressState] = useState<PrototypeMapAddressState>({
    status: realData.status === 'ready' ? 'loading' : 'disabled',
    source: '/api/map/reverse-geocode'
  });
  const locatedCount = visibleVehicles.filter(vehicleHasRealtimeCoordinate).length;
  const onlineCount = visibleVehicles.filter((vehicle) => vehicle.status === 'online').length;
  const visibleSources = visibleVehicles.flatMap((vehicle) => vehicle.sources);
  const onlineSourceCount = visibleSources.filter((source) => source.status === 'online').length;
  const warningSourceCount = visibleSources.filter((source) => source.status === 'warning').length;
  const offlineSourceCount = visibleSources.filter((source) => source.status === 'offline').length;
  const latestSourceSeenAt = visibleSources
    .map((source) => source.lastSeenAt)
    .filter((value): value is string => Boolean(value))
    .sort((left, right) => Date.parse(right) - Date.parse(left))[0];
  const protocolCounts = visibleVehicles.reduce<Record<Protocol, number>>((counts, vehicle) => {
    const protocols = new Set(vehicle.sources.map((source) => source.protocol));
    protocols.forEach((protocol) => {
      counts[protocol] += 1;
    });
    return counts;
  }, { GB32960: 0, JT808: 0, YUTONG_MQTT: 0 });
  const activeFieldCoverage = protocolOrder.map((protocol) => ({
    protocol,
    count: Object.keys(activeVehicle.flatFields[protocol] ?? {}).length,
    source: activeVehicle.sources.find((item) => item.protocol === protocol)
  }));
  const hasVisibleActiveVehicle = visibleVehicles.some((vehicle) => vehicle.id === activeVehicle.id);
  const mapPoints = useMemo<VehicleMapPoint[]>(() => visibleVehicles.map((vehicle) => ({
    id: vehicle.id,
    label: vehicle.plate,
    longitude: vehicle.longitude,
    latitude: vehicle.latitude,
    online: vehicle.status !== 'offline',
    title: `${vehicle.plate} / ${vehicle.vin} / ${getVehiclePrimarySource(vehicle).sourceName}`
  })), [visibleVehicles]);
  const emptyOverlay = mapEmptyOverlayState({
    amapRuntime,
    realData,
    visibleVehicles
  });
  const latestRefreshText = visibleSources.length > 0
    ? (latestSourceSeenAt ? chinaShortDateTime(latestSourceSeenAt) : activeSource.lastSeen)
    : '无匹配';
  const mapCoverageItems = [
    { label: '坐标覆盖', value: `${locatedCount}/${visibleVehicles.length}` },
    { label: '在线车辆', value: String(onlineCount) },
    {
      label: '来源健康',
      value: `${onlineSourceCount} 在线 / ${warningSourceCount} 关注 / ${offlineSourceCount} 离线`,
      compactValue: `${onlineSourceCount}/${warningSourceCount}/${offlineSourceCount}`
    },
    {
      label: '协议覆盖',
      value: `32960 ${protocolCounts.GB32960} / 808 ${protocolCounts.JT808} / MQTT ${protocolCounts.YUTONG_MQTT}`,
      compactValue: `${protocolCounts.GB32960}/${protocolCounts.JT808}/${protocolCounts.YUTONG_MQTT}`
    },
    { label: '最近刷新', value: latestRefreshText },
    { label: '证据模式', value: `${evidence.label} / ${amapRuntime.label}`, compactValue: `${evidence.label}/${amapRuntime.label}` }
  ];

  useEffect(() => {
    let mounted = true;
    if (realData.vehicles.length === 0 && realData.status !== 'ready') {
      setAddressState({
        status: 'disabled',
        source: '/api/map/reverse-geocode',
        error: '真实实时数据未就绪'
      });
      return () => {
        mounted = false;
      };
    }
    setAddressState({
      status: 'loading',
      source: '/api/map/reverse-geocode'
    });
    loadPrototypeMapAddress(activeVehicle.longitude, activeVehicle.latitude).then((next) => {
      if (mounted) {
        setAddressState(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [activeVehicle.latitude, activeVehicle.longitude, activeVehicle.vin, realData.status, realData.vehicles.length]);

  return (
    <section className="vpc-map-panel">
      <div className="vpc-map-toolbar">
        <div>
          <strong>车辆分布</strong>
          <span>{evidence.subtitle}</span>
        </div>
        <div className="vpc-map-tools">
          <Tag color={evidence.tone}>{evidence.label}</Tag>
          <Tag color={evidence.sourceTone}>{evidence.sourceTag}</Tag>
          <Tag color={diagnosticTagColor(amapRuntime.tone)}>{amapRuntime.tagLabel}</Tag>
        </div>
      </div>
      <MapRealtimeAmapRail
        activeSource={activeSource}
        activeVehicle={activeVehicle}
        addressState={addressState}
        amapRuntime={amapRuntime}
        locatedCount={locatedCount}
        realData={realData}
        visibleCount={visibleVehicles.length}
      />
      <div className="vpc-map-canvas vpc-map-canvas-amap">
        <VehicleMap
          fallbackLabel={visibleVehicles.length === 0
            ? emptyMapFallbackLabel(amapRuntime)
            : '高德地图未配置，显示真实坐标预览'}
          heightClassName="vpc-amap-monitor"
          maxFallbackPoints={160}
          onPointSelect={(point) => onSelectVehicle(point.id)}
          points={mapPoints}
          selectedId={activeVehicle.id}
        >
        <div className="vpc-map-data-strip" aria-label="地图真实数据覆盖">
          {mapCoverageItems.map((item) => (
            <div
              className="vpc-map-data-card"
              key={item.label}
              title={`${item.label}: ${item.value}`}
            >
              <span>{item.label}</span>
              <strong aria-label={item.value}>
                <span className="vpc-map-data-value-full">{item.value}</span>
                <span className="vpc-map-data-value-compact">{item.compactValue ?? item.value}</span>
              </strong>
            </div>
          ))}
        </div>
        <div className="vpc-map-legend">
          <span><i className="vpc-dot vpc-dot-online" /> 在线</span>
          <span><i className="vpc-dot vpc-dot-warning" /> 关注</span>
          <span><i className="vpc-dot vpc-dot-offline" /> 离线</span>
        </div>
        {emptyOverlay && (
          <div className={`vpc-map-empty-overlay vpc-map-empty-overlay-${emptyOverlay.tone}`} aria-label="地图空态说明">
            <span>{amapRuntime.tagLabel}</span>
            <strong>{emptyOverlay.title}</strong>
            <em>{emptyOverlay.detail}</em>
            <code>{emptyOverlay.endpoint}</code>
            <small>{emptyOverlay.hint}</small>
          </div>
        )}
        {hasVisibleActiveVehicle ? (
        <div className="vpc-map-focus">
          <span className={`vpc-status vpc-status-${activeVehicle.status}`}>{statusLabel[activeVehicle.status]}</span>
          <strong>{activeVehicle.plate}</strong>
          <em>{addressState.address ?? activeVehicle.address}</em>
          <div>
            <span>来源</span>
            <b>{activeSource.sourceName}</b>
          </div>
          <div>
            <span>最近上报</span>
            <b>{activeSource.lastSeen}</b>
          </div>
          <div>
            <span>坐标</span>
            <b>{activeVehicle.latitude.toFixed(5)}, {activeVehicle.longitude.toFixed(5)}</b>
          </div>
          <div>
            <span>坐标来源</span>
            <b>{protocolMeta[activeSource.protocol].short} / {activeSource.endpoint}</b>
          </div>
          <div>
            <span>数据口径</span>
            <b>{evidence.detail}</b>
          </div>
          <div>
            <span>地址解析</span>
            <b>
              <Tag color={mapAddressStatusColor(addressState)} size="small">{mapAddressStatusLabel(addressState)}</Tag>
              {addressState.region ? ` ${addressState.region}` : ''}
            </b>
          </div>
          <div className="vpc-map-focus-protocols" aria-label="选中车辆协议字段覆盖">
            {activeFieldCoverage.map((item) => (
              <span
                aria-label={`${protocolMeta[item.protocol].short} ${item.count} 项实时字段`}
                className={item.source ? `vpc-map-focus-protocol vpc-map-focus-protocol-${item.source.status}` : 'vpc-map-focus-protocol'}
                key={item.protocol}
              >
                <em>{protocolMeta[item.protocol].short}</em>
                <b>{item.count} 项</b>
              </span>
            ))}
          </div>
          <div className="vpc-map-focus-actions">
            <Button onClick={onOpenReplay} size="small" theme="borderless">
              轨迹
            </Button>
            <Button
              aria-label="打开高德坐标"
              data-amap-marker-url={canOpenAmapMarker ? amapVehicleMarkerURL(activeVehicle) : ''}
              disabled={!canOpenAmapMarker}
              onClick={() => window.open(amapVehicleMarkerURL(activeVehicle), '_blank', 'noopener,noreferrer')}
              size="small"
              theme="borderless"
            >
              高德
            </Button>
            <Button onClick={() => onOpenHistory(activeSource.protocol)} size="small" type="primary">
              RAW
            </Button>
          </div>
        </div>
        ) : visibleVehicles.length > 0 ? (
          <div className="vpc-map-focus vpc-map-focus-empty">
            <strong>暂无匹配车辆</strong>
            <em>{realData.vehicles.length === 0 && realData.status !== 'disabled' ? '真实实时接口暂未返回车辆，未展示本地样例。' : '当前实时筛选没有可展示点位。'}</em>
          </div>
        ) : null}
        </VehicleMap>
      </div>
      <MapFoundationStrip
        addressState={addressState}
        amapRuntime={amapRuntime}
        locatedCount={locatedCount}
        realData={realData}
        security={security}
        visibleCount={visibleVehicles.length}
      />
    </section>
  );
}

type FlatFieldValue = string | number | boolean | null;

type CoreFieldHighlight = {
  label: string;
  value: string;
  key: string;
  query: string;
  status: 'ready' | 'missing';
};

function flatFieldEntries(fields: VehicleRecord['flatFields'][Protocol]) {
  return Object.entries(fields) as Array<[string, FlatFieldValue]>;
}

function findFlatField(
  fields: VehicleRecord['flatFields'][Protocol],
  aliases: string[]
): [string, FlatFieldValue] | undefined {
  const normalizedAliases = aliases.map((alias) => alias.toLowerCase());
  return flatFieldEntries(fields).find(([key]) => {
    const normalizedKey = key.toLowerCase();
    const parts = normalizedKey.split('.');
    const tail = parts[parts.length - 1] ?? normalizedKey;
    return normalizedAliases.includes(tail) || normalizedAliases.some((alias) => normalizedKey.endsWith(`.${alias}`));
  });
}

function flatValueText(value: FlatFieldValue, unit = '') {
  if (value == null || value === '') {
    return '--';
  }
  if (typeof value === 'number') {
    const separator = unit === '%' ? '' : ' ';
    return `${formatNumber(value, Number.isInteger(value) ? 0 : 1)}${unit ? `${separator}${unit}` : ''}`;
  }
  return `${String(value)}${unit ? `${unit === '%' ? '' : ' '}${unit}` : ''}`;
}

function coordinateValueText(value: FlatFieldValue) {
  if (typeof value === 'number') {
    return value.toFixed(5);
  }
  return flatValueText(value);
}

function buildCoreFieldHighlight({
  label,
  fields,
  aliases,
  fallbackValue,
  fallbackKey,
  unit = ''
}: {
  label: string;
  fields: VehicleRecord['flatFields'][Protocol];
  aliases: string[];
  fallbackValue?: FlatFieldValue;
  fallbackKey?: string;
  unit?: string;
}): CoreFieldHighlight {
  const entry = findFlatField(fields, aliases);
  if (entry) {
    return {
      label,
      value: flatValueText(entry[1], unit),
      key: entry[0],
      query: entry[0],
      status: entry[1] == null || entry[1] === '' ? 'missing' : 'ready'
    };
  }
  if (fallbackValue != null && fallbackValue !== '') {
    return {
      label,
      value: flatValueText(fallbackValue, unit),
      key: fallbackKey ?? 'source snapshot',
      query: aliases[0],
      status: 'ready'
    };
  }
  return {
    label,
    value: '缺失',
    key: aliases[0],
    query: aliases[0],
    status: 'missing'
  };
}

function buildMileageHighlight(
  fields: VehicleRecord['flatFields'][Protocol],
  activeSource?: VehicleSourceSnapshot
): CoreFieldHighlight {
  const kmEntry = findFlatField(fields, ['totalMileageKm', 'total_mileage_km']);
  if (kmEntry) {
    return {
      label: '总里程',
      value: flatValueText(kmEntry[1], 'km'),
      key: kmEntry[0],
      query: kmEntry[0],
      status: kmEntry[1] == null || kmEntry[1] === '' ? 'missing' : 'ready'
    };
  }
  const meterEntry = findFlatField(fields, ['total_mileage', 'TOTAL_MILEAGE']);
  const sourceMileage = activeSource?.totalMileageKm;
  if (meterEntry && activeSource?.protocol === 'YUTONG_MQTT' && sourceMileage != null) {
    return {
      label: '总里程',
      value: flatValueText(sourceMileage, 'km'),
      key: `${meterEntry[0]} / meters->km`,
      query: meterEntry[0],
      status: 'ready'
    };
  }
  return buildCoreFieldHighlight({
    label: '总里程',
    fields,
    aliases: ['totalMileageKm', 'total_mileage_km', 'total_mileage', 'TOTAL_MILEAGE'],
    fallbackValue: sourceMileage,
    fallbackKey: 'source.totalMileageKm',
    unit: 'km'
  });
}

function buildCoordinateHighlight(fields: VehicleRecord['flatFields'][Protocol], activeVehicle: VehicleRecord): CoreFieldHighlight {
  const latitude = findFlatField(fields, ['latitude', 'lat']);
  const longitude = findFlatField(fields, ['longitude', 'lng', 'lon']);
  if (latitude && longitude && latitude[1] != null && longitude[1] != null) {
    return {
      label: '坐标',
      value: `${coordinateValueText(latitude[1])}, ${coordinateValueText(longitude[1])}`,
      key: `${latitude[0]} / ${longitude[0]}`,
      query: 'latitude',
      status: 'ready'
    };
  }
  if (Number.isFinite(activeVehicle.latitude) && Number.isFinite(activeVehicle.longitude)) {
    return {
      label: '坐标',
      value: `${activeVehicle.latitude.toFixed(5)}, ${activeVehicle.longitude.toFixed(5)}`,
      key: 'vehicle location projection',
      query: 'latitude',
      status: 'ready'
    };
  }
  return {
    label: '坐标',
    value: '缺失',
    key: 'latitude / longitude',
    query: 'latitude',
    status: 'missing'
  };
}

function getCoreFieldHighlights({
  fields,
  activeSource,
  activeVehicle
}: {
  fields: VehicleRecord['flatFields'][Protocol];
  activeSource?: VehicleSourceSnapshot;
  activeVehicle: VehicleRecord;
}) {
  return [
    buildCoreFieldHighlight({
      label: '车速',
      fields,
      aliases: ['speedKmh', 'speed_kmh', 'meter_speed', 'METER_SPEED'],
      fallbackValue: activeSource?.speedKph,
      fallbackKey: 'source.speedKph',
      unit: 'km/h'
    }),
    buildMileageHighlight(fields, activeSource),
    buildCoordinateHighlight(fields, activeVehicle),
    buildCoreFieldHighlight({
      label: 'SOC',
      fields,
      aliases: ['socPercent', 'soc_percent', 'battery_capacity_soc', 'BATTERY_CAPACITY_SOC'],
      fallbackValue: activeVehicle.soc,
      fallbackKey: 'vehicle.soc',
      unit: '%'
    }),
    buildCoreFieldHighlight({
      label: '方向',
      fields,
      aliases: ['directionDeg', 'direction_deg'],
      fallbackValue: activeVehicle.heading,
      fallbackKey: 'vehicle.heading',
      unit: 'deg'
    }),
    buildCoreFieldHighlight({
      label: '事件时间',
      fields,
      aliases: ['event_time', 'device_time', 'updated_at', 'received_at', 'lastSeen'],
      fallbackValue: activeSource?.lastSeen,
      fallbackKey: 'source.lastSeen'
    })
  ];
}

function VehicleDetail({
  activeVehicle,
  activeSource,
  activeAlerts,
  detailTab,
  setDetailTab,
  onOpenReplay,
  onOpenHistoryField,
  onOpenHistory
}: {
  activeVehicle: VehicleRecord;
  activeSource: ReturnType<typeof getVehiclePrimarySource>;
  activeAlerts: AlertEvent[];
  detailTab: DetailTab;
  setDetailTab: (tab: DetailTab) => void;
  onOpenReplay: () => void;
  onOpenHistoryField: (vin: string, protocol: Protocol, fieldKey: string) => void;
  onOpenHistory: (protocol?: Protocol) => void;
}) {
  const availableProtocols = (Object.keys(activeVehicle.flatFields) as Protocol[]).filter(
    (protocol) => Object.keys(activeVehicle.flatFields[protocol]).length > 0
  );
  const consistency = getSourceConsistency(activeVehicle);
  const [fieldProtocol, setFieldProtocol] = useState<Protocol>(activeSource.protocol);
  const [fieldQuery, setFieldQuery] = useState('');
  const fieldSource = activeVehicle.sources.find((source) => source.protocol === fieldProtocol);
  const realtimeEvidence = getRealtimeEvidence(activeVehicle, activeSource);
  const consistencyTone = consistency.severity === 'ok' ? 'green' : consistency.severity === 'error' ? 'red' : 'orange';
  const detailDigest = getVehicleDetailDigest(activeVehicle, activeSource);
  const diagnosticSteps = getVehicleDiagnosticSteps(activeVehicle, activeSource);
  const sourceResponsibilityRows = getVehicleSourceResponsibilityRows(activeVehicle, activeSource);
  const currentProtocolFields = activeVehicle.flatFields[fieldProtocol] ?? {};
  const allFieldRows = flatFieldEntries(currentProtocolFields);
  const fieldRows = allFieldRows.filter(([key, value]) => {
    const normalized = fieldQuery.trim().toLowerCase();
    if (!normalized) {
      return true;
    }
    return key.toLowerCase().includes(normalized) || String(value).toLowerCase().includes(normalized);
  });
  const coreFieldHighlights = getCoreFieldHighlights({
    activeSource: fieldSource,
    activeVehicle,
    fields: currentProtocolFields
  });
  const fieldGroups = fieldRows.reduce<Array<{ name: string; rows: Array<[string, string | number | boolean | null]> }>>(
    (groups, row) => {
      const [key] = row;
      const groupName = key.split('.').slice(0, 3).join('.');
      const group = groups.find((item) => item.name === groupName);
      if (group) {
        group.rows.push(row);
      } else {
        groups.push({ name: groupName, rows: [row] });
      }
      return groups;
    },
    []
  );

  useEffect(() => {
    const nextProtocol = availableProtocols.includes(activeSource.protocol)
      ? activeSource.protocol
      : availableProtocols[0] ?? activeSource.protocol;
    setFieldProtocol(nextProtocol);
    setFieldQuery('');
  }, [activeSource.protocol, activeVehicle.id]);

  return (
    <aside className="vpc-panel vpc-detail">
      <div className="vpc-detail-title">
        <div>
          <span className={`vpc-status vpc-status-${activeVehicle.status}`}>{statusLabel[activeVehicle.status]}</span>
          <h2>{activeVehicle.plate}</h2>
        </div>
        <Tag color={protocolMeta[activeSource.protocol].color}>{protocolMeta[activeSource.protocol].short}</Tag>
      </div>

      <div className="vpc-detail-digest" aria-label="车辆详情摘要">
        {detailDigest.map((item) => (
          <button
            aria-label={`查看${item.title}`}
            className={`vpc-detail-digest-card vpc-detail-digest-${item.tone}`}
            key={item.key}
            onClick={() => {
              if (item.key === 'trust') {
                setDetailTab('来源');
              } else if (item.key === 'traceability') {
                onOpenHistory(activeSource.protocol);
              } else {
                setDetailTab('概况');
              }
            }}
            type="button"
          >
            <span>{item.title}</span>
            <strong>{item.value}</strong>
            <em>{item.metric}</em>
            <small>{item.source}</small>
          </button>
        ))}
      </div>

      <div className="vpc-tabs">
        {detailTabs.map((tab) => (
          <button className={detailTab === tab ? 'vpc-tab-active' : ''} key={tab} onClick={() => setDetailTab(tab)} type="button">
            {tab}
          </button>
        ))}
      </div>

      <div className="vpc-active-source-strip">
        <div>
          <span>主展示来源</span>
          <strong>{activeSource.sourceName}</strong>
        </div>
        <div>
          <span>最近上报</span>
          <strong>{activeSource.lastSeen}</strong>
        </div>
        <div>
          <span>字段/延迟</span>
          <strong>{activeSource.fieldCount} / {activeSource.latencyMs} ms</strong>
        </div>
      </div>

      <div className="vpc-context-actions" aria-label="车辆证据快捷入口">
        <Button icon={<IconPulse />} onClick={onOpenReplay} size="small">
          看轨迹
        </Button>
        <Button icon={<IconHistogram />} onClick={() => onOpenHistory()} size="small" theme="solid" type="primary">
          查 RAW
        </Button>
      </div>

      {detailTab === '概况' && (
        <>
          <div className="vpc-diagnostic-path" aria-label="车辆排障路径">
            <div className="vpc-diagnostic-path-head">
              <span>排障路径</span>
              <strong>先确认当前态，再核来源，最后回查证据</strong>
            </div>
            <div className="vpc-diagnostic-path-steps">
              {diagnosticSteps.map((step, index) => (
                <button
                  className={`vpc-diagnostic-step vpc-diagnostic-step-${step.status}`}
                  key={step.key}
                  onClick={() => {
                    if (step.action === 'sources') {
                      setDetailTab('来源');
                    } else if (step.action === 'history') {
                      onOpenHistory(activeSource.protocol);
                    } else {
                      setDetailTab('概况');
                    }
                  }}
                  type="button"
                >
                  <span>{index + 1}. {step.title}</span>
                  <strong>{step.primary}</strong>
                  <em>{step.detail}</em>
                </button>
              ))}
            </div>
          </div>
          <div className={`vpc-confidence-card vpc-confidence-${consistency.severity}`} aria-label="车辆服务可信度">
            <div className="vpc-confidence-head">
              <div>
                <span>车辆服务可信度</span>
                <strong>{consistency.title}</strong>
              </div>
              <Tag color={consistencyTone}>{consistency.severity === 'ok' ? '正常' : consistency.severity === 'error' ? '异常' : '关注'}</Tag>
            </div>
            <p>{consistency.detail}</p>
            <div className="vpc-confidence-metrics">
              <span>
                <em>在线来源</em>
                <strong>{consistency.onlineSourceCount}/{consistency.sourceCount}</strong>
              </span>
              <span>
                <em>里程差</em>
                <strong>{formatNumber(consistency.mileageDeltaKm, 1)} km</strong>
              </span>
              <span>
                <em>时间差</em>
                <strong>{formatNumber(consistency.sourceTimeDeltaSeconds, 0)} s</strong>
              </span>
            </div>
            <div className="vpc-confidence-actions">
              <Button onClick={() => setDetailTab('来源')} size="small" theme="borderless">
                查看来源
              </Button>
              <Button onClick={() => onOpenHistory(activeSource.protocol)} size="small" type="primary">
                查 RAW
              </Button>
            </div>
          </div>
          <div className="vpc-info-card">
            <InfoLine label="VIN" value={activeVehicle.vin} />
            <InfoLine label="手机号" value={activeVehicle.phone ?? '--'} />
            <InfoLine label="OEM" value={activeVehicle.oem} />
            <InfoLine label="当前展示来源" value={activeSource.sourceName} />
            <InfoLine label="发送端" value={activeSource.endpoint} />
            <InfoLine label="当前位置" value={activeVehicle.address} />
          </div>
          <div className="vpc-live-grid">
            <Metric label="车速" value={`${activeSource.speedKph ?? 0} km/h`} />
            <Metric label="方向" value={`${activeVehicle.heading}°`} />
            <Metric label="总里程" value={`${formatNumber(activeSource.totalMileageKm ?? 0, 1)} km`} />
            <Metric label="今日里程" value={`${formatNumber(activeSource.todayMileageKm ?? 0, 1)} km`} />
            <Metric label="SOC" value={activeVehicle.soc == null ? '--' : `${activeVehicle.soc}%`} />
            <Metric label="剩余氢量" value={activeVehicle.hydrogenKg == null ? '--' : `${activeVehicle.hydrogenKg} kg`} />
          </div>
          <div className="vpc-realtime-evidence">
            {realtimeEvidence.map((item) => (
              <article key={item.label}>
                <span>{item.label}</span>
                <strong>{item.value}</strong>
                <em>{item.source}</em>
              </article>
            ))}
          </div>
        </>
      )}

      {detailTab === '实时字段' && (
        <div className="vpc-field-inspector">
          <div className="vpc-field-toolbar">
            <div className="vpc-field-protocols">
              {(['GB32960', 'JT808', 'YUTONG_MQTT'] as const).map((protocol) => {
                const count = Object.keys(activeVehicle.flatFields[protocol]).length;
                return (
                  <button
                    className={fieldProtocol === protocol ? 'vpc-field-protocol-active' : ''}
                    disabled={count === 0}
                    key={protocol}
                    onClick={() => setFieldProtocol(protocol)}
                    type="button"
                  >
                    {protocolMeta[protocol].short}
                    <em>{count}</em>
                  </button>
                );
              })}
            </div>
            <Input
              className="vpc-field-search"
              onChange={setFieldQuery}
              placeholder="搜索字段 key 或 value"
              prefix={<IconSearch />}
              value={fieldQuery}
            />
          </div>
          <div className="vpc-core-field-grid" aria-label="核心实时字段">
            {coreFieldHighlights.map((item) => (
              <button
                className={`vpc-core-field vpc-core-field-${item.status}`}
                disabled={item.status === 'missing'}
                key={item.label}
                onClick={() => setFieldQuery(item.query)}
                type="button"
              >
                <span>{item.label}</span>
                <strong>{item.value}</strong>
                <em>{item.key}</em>
              </button>
            ))}
          </div>
          <div className="vpc-field-summary">
            <span>{fieldSource?.sourceName ?? '无来源'} / 命中 {fieldRows.length} / 全量 {allFieldRows.length} 字段 / Redis realtime-raw</span>
            <strong>{fieldProtocol}</strong>
          </div>
          {fieldGroups.length === 0 ? (
            <div className="vpc-empty">当前协议暂无扁平字段</div>
          ) : (
            fieldGroups.map((group) => (
              <section className="vpc-field-group" key={group.name}>
                <div className="vpc-field-group-head">
                  <strong>{group.name}</strong>
                  <span>{group.rows.length}</span>
                </div>
                {group.rows.map(([key, value]) => (
                  <div className="vpc-field-row" key={key}>
                    <div>
                      <span>{key}</span>
                      <strong>{String(value)}</strong>
                    </div>
                    <button
                      aria-label={`按实时字段 ${key} 查询 RAW`}
                      onClick={() => onOpenHistoryField(activeVehicle.vin, fieldProtocol, key)}
                      type="button"
                    >
                      RAW
                    </button>
                  </div>
                ))}
              </section>
            ))
          )}
        </div>
      )}

      {detailTab === '来源' && (
        <div className="vpc-source-stack">
          <div className="vpc-source-decision">
            <div>
              <span>来源一致性</span>
              <strong>{consistency.title}</strong>
              <em>{consistency.detail}</em>
            </div>
            <div>
              <span>当前展示来源</span>
              <strong>{activeSource.sourceName}</strong>
              <em>来自 MySQL realtime snapshot/location 与 Redis online 的当前态。</em>
            </div>
          </div>
          <div className="vpc-consistency-metrics">
            <Metric label="来源" value={`${consistency.onlineSourceCount}/${consistency.sourceCount} 在线`} />
            <Metric label="定位来源" value={`${consistency.locatedSourceCount}`} />
            <Metric label="里程差" value={`${formatNumber(consistency.mileageDeltaKm, 1)} km`} />
            <Metric label="时间差" value={`${formatNumber(consistency.sourceTimeDeltaSeconds, 0)} s`} />
          </div>
          <div className="vpc-source-responsibility-table" aria-label="来源判责表">
            <div className="vpc-source-responsibility-head">
              <span>协议来源</span>
              <span>状态</span>
              <span>最近/延迟</span>
              <span>字段</span>
              <span>里程</span>
              <span>问题</span>
              <span>动作</span>
            </div>
            {sourceResponsibilityRows.map((row) => (
              <article className={`vpc-source-responsibility-row vpc-source-responsibility-${row.status}`} key={row.id}>
                <div className="vpc-source-responsibility-name">
                  <Tag color={protocolMeta[row.protocol].color}>{protocolMeta[row.protocol].short}</Tag>
                  <div>
                    <strong>{row.sourceName}</strong>
                    <em>{row.endpoint}</em>
                  </div>
                  {row.selected && <Tag color="blue" size="small">当前展示</Tag>}
                </div>
                <div>
                  <span>状态</span>
                  <strong>{row.statusLabel}</strong>
                </div>
                <div>
                  <span>最近/延迟</span>
                  <strong>{row.lastSeen} / {row.latencyMs} ms</strong>
                </div>
                <div>
                  <span>字段</span>
                  <strong>{row.fieldCount}</strong>
                </div>
                <div>
                  <span>里程</span>
                  <strong>{row.totalMileageKm == null ? '--' : `${formatNumber(row.totalMileageKm, 1)} km`}</strong>
                  <em>差异 {formatNumber(row.mileageDeltaKm, 1)} km</em>
                </div>
                <div>
                  <span>问题</span>
                  <strong>{row.issueSummary}</strong>
                </div>
                <div className="vpc-source-responsibility-actions">
                  <Button onClick={onOpenReplay} size="small" theme="borderless">轨迹</Button>
                  <Button onClick={() => onOpenHistory(row.protocol)} size="small" theme="borderless">RAW</Button>
                </div>
              </article>
            ))}
          </div>
        </div>
      )}

      {detailTab === '告警' && (
        <div className="vpc-source-stack">
          {activeAlerts.length === 0 ? (
            <div className="vpc-empty">当前车辆暂无告警</div>
          ) : (
            activeAlerts.map((alert) => (
              <article className="vpc-alert-mini" key={alert.id}>
                <Tag color={alert.level === 'P1' ? 'orange' : 'blue'}>{alert.level}</Tag>
                <strong>{alert.title}</strong>
                <span>{alert.detail}</span>
              </article>
            ))
          )}
        </div>
      )}
    </aside>
  );
}

function trackQueryStatusLabel(status: PrototypeTrackState['status']) {
  if (status === 'loading') return '查询中';
  if (status === 'ready') return '已连接';
  if (status === 'empty') return '无轨迹';
  if (status === 'error') return '查询失败';
  return '未启用';
}

function trackQueryTone(status: PrototypeTrackState['status']) {
  if (status === 'ready') return 'ready';
  if (status === 'loading') return 'loading';
  if (status === 'empty') return 'empty';
  if (status === 'error') return 'error';
  return 'disabled';
}

function rawFrameQueryStatusLabel(status: PrototypeRawFrameState['status']) {
  if (status === 'loading') return '查询中';
  if (status === 'ready') return '已连接';
  if (status === 'empty') return '无结果';
  if (status === 'error') return '查询失败';
  return '未启用';
}

function rawFrameQueryTone(status: PrototypeRawFrameState['status']) {
  if (status === 'ready') return 'ready';
  if (status === 'loading') return 'loading';
  if (status === 'empty') return 'empty';
  if (status === 'error') return 'error';
  return 'disabled';
}

function ReplayPage({
  activeVehicle,
  activeTrack,
  playbackIndex,
  setPlaybackIndex,
  isPlaying,
  setIsPlaying,
  onOpenHistory,
  canQueryRealTrack,
  usingRealData
}: {
  activeVehicle: VehicleRecord;
  activeTrack: TrackPoint[];
  playbackIndex: number;
  setPlaybackIndex: Dispatch<SetStateAction<number>>;
  isPlaying: boolean;
  setIsPlaying: Dispatch<SetStateAction<boolean>>;
  onOpenHistory: (vin: string, protocol?: Protocol, context?: HistoryOpenContext) => void;
  canQueryRealTrack: boolean;
  usingRealData: boolean;
}) {
  const [playbackSpeed, setPlaybackSpeed] = useState<1 | 2 | 4>(2);
  const [trackDateFrom, setTrackDateFrom] = useState(() => initialChinaDayRange().from);
  const [trackDateTo, setTrackDateTo] = useState(() => initialChinaDayRange().to);
  const [trackLimit, setTrackLimit] = useState(80);
  const [trackQueryTick, setTrackQueryTick] = useState(0);
  const [showAllTrackNodes, setShowAllTrackNodes] = useState(false);
  const [segmentVisibleLimit, setSegmentVisibleLimit] = useState(12);
  const [showReplaySamples, setShowReplaySamples] = useState(false);
  const [trackState, setTrackState] = useState<PrototypeTrackState>({
    points: [],
    status: canQueryRealTrack ? 'loading' : 'disabled',
    source: '/api/history/locations',
    total: 0
  });
  const points = canQueryRealTrack ? trackState.points : activeTrack;
  const replaySummary = getReplaySummary(points);
  const replaySegments = getReplaySegments(points);
  const replayEvidence = getReplayEvidence(activeVehicle, points);
  const replayEvidenceItems = canQueryRealTrack
    ? replayEvidence
    : [
        {
          title: '轨迹样例',
          source: '本地样例点',
          detail: `${activeVehicle.plate} 当前展示本地样例轨迹，只用于验证地图、时间轴和播放控件。`,
          status: 'warning'
        },
        {
          title: '轨迹查询蓝图',
          source: 'TDengine vehicle_locations',
          detail: '真实能力需要按 VIN + 时间窗查询位置点；未连接接口时不证明 TDengine 已返回轨迹。',
          status: 'warning'
        },
        {
          title: 'RAW 回溯蓝图',
          source: 'TDengine raw_frames / payload_chunks',
          detail: '真实上线后应按轨迹节点时间回查 RAW parsed_fields；样例节点不触发真实 RAW 回溯。',
          status: 'warning'
        },
        {
          title: 'AMap 证据',
          source: 'AMap JS / 坐标跳转',
          detail: '有坐标的样例点可验证地图交互；地址解析不代表生产轨迹证据。 ',
          status: 'ready'
        }
      ];
  const replayFallbackSummary = [
    { label: '真实轨迹', value: '待读取' },
    { label: '查询表', value: 'vehicle_locations' },
    { label: '样例验证', value: showReplaySamples ? '已展开' : '默认收起' },
    { label: 'AMap', value: isAMapConfigured() ? '已配置' : '未配置' }
  ];
  const replayFallbackBoundaries = [
    {
      title: '轨迹查询',
      source: 'TDengine vehicle_locations',
      detail: '真实能力需要 `/api/history/locations` 按 VIN + 时间窗返回位置点；当前失败态不访问 TDengine。'
    },
    {
      title: '播放与分段',
      source: '前端播放状态',
      detail: '播放、速度和分段列表使用当前点集计算；样例模式只验证交互，不参与真实里程判断。'
    },
    {
      title: '证据联动',
      source: 'RAW / AMap',
      detail: '真实轨迹可跳 RAW 和高德坐标；样例轨迹只验证入口形态和地图渲染。'
    }
  ];
  const trackQualityAudit = useMemo(() => buildTrackQualityAudit(points), [points]);
  const trackTimeWindowAudit = useMemo(
    () => buildTrackTimeWindowAudit({ points, dateFrom: trackDateFrom, dateTo: trackDateTo }),
    [points, trackDateFrom, trackDateTo]
  );
  const replaySource = getVehiclePrimarySource(activeVehicle);
  const timelineActiveRef = useRef<HTMLButtonElement | null>(null);
  const activeIndex = Math.min(playbackIndex, Math.max(points.length - 1, 0));
  const currentPoint = points[activeIndex];
  const canOpenTrackPointMarker = hasTrackPointCoordinate(currentPoint);
  const [trackAddressState, setTrackAddressState] = useState<PrototypeMapAddressState>({
    status: canQueryRealTrack ? 'loading' : 'disabled',
    source: '/api/map/reverse-geocode'
  });
  const trackQueryStatusTone = trackQueryTone(trackState.status);
  const trackQueryTitle = trackState.status === 'loading'
    ? '正在查询历史轨迹'
    : trackState.status === 'ready'
      ? '历史轨迹已返回'
      : trackState.status === 'empty'
        ? '历史轨迹无结果'
        : trackState.status === 'error'
          ? '历史轨迹查询失败'
          : '历史轨迹未启用';
  const trackQueryDetail = trackState.status === 'error'
    ? trackState.error ?? '接口异常'
    : trackState.status === 'ready'
      ? 'TDengine vehicle_locations 已返回真实位置点，可继续播放、分段并回查 RAW 证据。'
      : trackState.status === 'empty'
        ? '当前 VIN、时间窗或节点上限没有返回可回放的位置点。'
        : trackState.status === 'loading'
          ? '正在读取 TDengine vehicle_locations，结果不会回退到本地轨迹样例。'
          : '真实轨迹查询关闭时只展示回放蓝图和手动样例验证入口。';
  const trackQuerySourceLabel = trackState.source.includes('history/locations') ? 'history/locations' : trackState.source;
  const replayQueryStatus = canQueryRealTrack ? (
    <div className={`vpc-replay-query-status vpc-replay-query-status-${trackQueryStatusTone}`} aria-label="历史轨迹查询状态">
      <div className="vpc-replay-query-status-main">
        <span>轨迹查询状态</span>
        <strong>{trackQueryTitle}</strong>
        <em>{trackQueryDetail}</em>
      </div>
      <Metric label="状态" value={trackQueryStatusLabel(trackState.status)} />
      <Metric label="位置点" value={`${trackState.total}`} />
      <Metric label="上限" value={`${trackLimit}`} />
      <Metric label="来源" value={trackQuerySourceLabel.replace('/api/', '')} />
    </div>
  ) : null;

  useEffect(() => {
    if (canQueryRealTrack) {
      setShowReplaySamples(false);
    }
  }, [canQueryRealTrack]);

  useEffect(() => {
    if (!canQueryRealTrack) {
      return undefined;
    }
    let mounted = true;
    setPlaybackIndex(0);
    setTrackState((current) => ({
      ...current,
      status: 'loading',
      points: []
    }));
    loadPrototypeTrackPoints(activeVehicle.vin, activeVehicle.id, {
      dateFrom: trackDateFrom,
      dateTo: trackDateTo,
      limit: trackLimit
    }).then((next) => {
      if (mounted) {
        setTrackState(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [activeVehicle.id, activeVehicle.vin, canQueryRealTrack, setPlaybackIndex, trackQueryTick]);

  useEffect(() => {
    if (!isPlaying || points.length <= 1) {
      return undefined;
    }
    const timer = window.setInterval(() => {
      setPlaybackIndex((current) => {
        const safeCurrent = Math.min(current, points.length - 1);
        if (safeCurrent >= points.length - 1) {
          setIsPlaying(false);
          return points.length - 1;
        }
        return safeCurrent + 1;
      });
    }, Math.max(180, Math.round(1200 / playbackSpeed)));
    return () => window.clearInterval(timer);
  }, [isPlaying, playbackSpeed, points.length, setIsPlaying, setPlaybackIndex]);

  useEffect(() => {
    const activeNode = timelineActiveRef.current;
    const timelineNode = activeNode?.closest('.vpc-timeline') as HTMLElement | null;
    if (!activeNode || !timelineNode || timelineNode.scrollWidth <= timelineNode.clientWidth) {
      return;
    }

    const nodeLeft = activeNode.offsetLeft;
    const nodeRight = nodeLeft + activeNode.offsetWidth;
    const visibleLeft = timelineNode.scrollLeft;
    const visibleRight = visibleLeft + timelineNode.clientWidth;

    if (nodeLeft < visibleLeft) {
      timelineNode.scrollTo({ left: Math.max(0, nodeLeft - 8), behavior: 'smooth' });
      return;
    }
    if (nodeRight > visibleRight) {
      timelineNode.scrollTo({ left: nodeRight - timelineNode.clientWidth + 8, behavior: 'smooth' });
    }
  }, [activeIndex, currentPoint?.id]);

  useEffect(() => {
    setShowAllTrackNodes(false);
    setSegmentVisibleLimit(12);
  }, [activeVehicle.id, points.length, trackQueryTick]);

  useEffect(() => {
    let mounted = true;
    if (!canQueryRealTrack) {
      setTrackAddressState({
        status: 'disabled',
        source: '/api/map/reverse-geocode',
        error: '真实轨迹未启用'
      });
      return () => {
        mounted = false;
      };
    }
    if (!hasTrackPointCoordinate(currentPoint)) {
      setTrackAddressState({
        status: 'unavailable',
        source: '/api/map/reverse-geocode',
        error: '当前轨迹节点缺少经纬度'
      });
      return () => {
        mounted = false;
      };
    }
    setTrackAddressState({
      status: 'loading',
      source: '/api/map/reverse-geocode'
    });
    loadPrototypeMapAddress(currentPoint.longitude ?? 0, currentPoint.latitude ?? 0).then((next) => {
      if (mounted) {
        setTrackAddressState(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [canQueryRealTrack, currentPoint?.id, currentPoint?.latitude, currentPoint?.longitude]);

  const replayQueryPanel = canQueryRealTrack ? (
    <section className="vpc-panel vpc-replay-query-panel">
      <div className="vpc-panel-head">
        <strong>轨迹查询</strong>
        <span>TDengine vehicle_locations</span>
      </div>
      <div className="vpc-replay-query-grid">
        <label>
          <span>开始时间</span>
          <input
            aria-label="轨迹查询开始时间"
            className="vpc-input"
            onChange={(event) => setTrackDateFrom(event.target.value)}
            value={trackDateFrom}
          />
        </label>
        <label>
          <span>结束时间</span>
          <input
            aria-label="轨迹查询结束时间"
            className="vpc-input"
            onChange={(event) => setTrackDateTo(event.target.value)}
            value={trackDateTo}
          />
        </label>
        <label>
          <span>节点上限</span>
          <select
            aria-label="轨迹查询节点上限"
            className="vpc-select"
            onChange={(event) => setTrackLimit(Number(event.target.value))}
            value={trackLimit}
          >
            {[40, 80, 160, 300].map((limit) => (
              <option key={limit} value={limit}>
                {limit} 点
              </option>
            ))}
          </select>
        </label>
        <label>
          <span>快捷时间</span>
          <TimeRangePresetButtons
            onApply={(range) => {
              setTrackDateFrom(range.from);
              setTrackDateTo(range.to);
              setIsPlaying(false);
              setPlaybackIndex(0);
              setTrackQueryTick((value) => value + 1);
            }}
          />
        </label>
        <Button
          onClick={() => {
            setIsPlaying(false);
            setPlaybackIndex(0);
            setTrackQueryTick((value) => value + 1);
          }}
          type="primary"
        >
          查询轨迹
        </Button>
        <Button
          onClick={() => {
            setTrackDateFrom('');
            setTrackDateTo('');
            setIsPlaying(false);
            setPlaybackIndex(0);
            setTrackQueryTick((value) => value + 1);
          }}
          theme="borderless"
        >
          查最新轨迹
        </Button>
      </div>
      <div className="vpc-replay-query-source">
        <span>{trackQueryStatusLabel(trackState.status)}</span>
        <strong>{trackState.source}</strong>
        {trackState.error && <em>{trackState.error}</em>}
      </div>
    </section>
  ) : null;
  const trackTimeWindowNode = canQueryRealTrack ? (
    <div className={`vpc-track-window-audit vpc-track-window-${trackTimeWindowAudit.status}`} aria-label="轨迹查询时间窗核验">
      <div className="vpc-track-window-main">
        <span>时间窗核验</span>
        <strong>{trackTimeWindowAudit.title}</strong>
        <em>{trackTimeWindowAudit.detail}</em>
      </div>
      <Metric label="查询窗" value={trackTimeWindowAudit.queryRange} />
      <Metric label="返回点" value={trackTimeWindowAudit.pointRange} />
      <Metric label="窗外点" value={`${trackTimeWindowAudit.outsidePointCount}/${trackTimeWindowAudit.pointCount}`} />
      <Metric label="AMap 联动" value={points.some(hasTrackPointCoordinate) ? '可定位' : '无坐标'} />
    </div>
  ) : null;

  if (!canQueryRealTrack && !showReplaySamples) {
    return (
      <section className="vpc-page-stack vpc-replay-page">
        <ReplayVehicleContext
          activeSource={replaySource}
          activeVehicle={activeVehicle}
          canQueryRealTrack={canQueryRealTrack}
          usingRealData={usingRealData}
        />
        <div className="vpc-real-source-banner vpc-replay-blueprint-banner">
          <div>
            <strong>真实轨迹未读取，当前只展示轨迹回放蓝图</strong>
            <span>不会把本地样例轨迹当作 TDengine 轨迹；真实轨迹需要由 history locations 返回位置点后再计算分段和证据。</span>
          </div>
          {replayFallbackSummary.map((item) => (
            <Metric key={item.label} label={item.label} value={item.value} />
          ))}
        </div>
        <div className="vpc-source-evidence-layers vpc-replay-blueprint-layers" aria-label="轨迹回放蓝图边界">
          {replayFallbackBoundaries.map((item) => (
            <article key={item.title}>
              <span>{item.title}</span>
              <strong>{item.source}</strong>
              <em>{item.detail}</em>
            </article>
          ))}
        </div>
        <div className="vpc-panel">
          <div className="vpc-replay-sample-gate">
            <div>
              <strong>轨迹样例已收起</strong>
              <span>真实轨迹未返回前，不展示样例地图、播放控件和分段里程，避免误读为 TDengine vehicle_locations 结果。</span>
            </div>
            <Button onClick={() => setShowReplaySamples(true)} type="primary">
              展开轨迹样例
            </Button>
          </div>
          <div className="vpc-replay-sample-closed" aria-label="轨迹样例收起说明">
            <article>
              <span>不展示</span>
              <strong>样例轨迹地图</strong>
              <em>避免把本地轨迹当作 TDengine vehicle_locations 结果。</em>
            </article>
            <article>
              <span>保留</span>
              <strong>轨迹回放蓝图</strong>
              <em>查询口径、证据入口和 AMap 能力边界仍可评审。</em>
            </article>
            <article>
              <span>等待</span>
              <strong>真实位置点</strong>
              <em>接口返回后再展示轨迹节点、分段里程和质量审计。</em>
            </article>
          </div>
        </div>
      </section>
    );
  }

  if (points.length === 0) {
    return (
      <section className="vpc-page-stack vpc-replay-page">
        <ReplayVehicleContext
          activeSource={replaySource}
          activeVehicle={activeVehicle}
          canQueryRealTrack={canQueryRealTrack}
          usingRealData={usingRealData}
        />
        {!canQueryRealTrack && (
          <div className="vpc-real-source-banner vpc-replay-blueprint-banner">
            <div>
              <strong>真实轨迹未读取，当前只展示轨迹回放蓝图</strong>
              <span>不会把本地样例轨迹当作 TDengine 轨迹；真实轨迹需要由 history locations 返回位置点后再计算分段和证据。</span>
            </div>
            {replayFallbackSummary.map((item) => (
              <Metric key={item.label} label={item.label} value={item.value} />
            ))}
          </div>
        )}
        {replayQueryStatus}
        {replayQueryPanel}
        {trackTimeWindowNode}
        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>{activeVehicle.plate} 轨迹回放</strong>
            <span>{canQueryRealTrack ? 'TDengine vehicle_locations / 真实查询' : '样例时间窗 / 非生产轨迹'}</span>
          </div>
          <div className="vpc-empty">
            {canQueryRealTrack && trackState.status === 'loading'
              ? '正在查询真实轨迹点...'
              : canQueryRealTrack && trackState.status === 'error'
                ? `轨迹查询失败：${trackState.error ?? '接口异常'}`
                : canQueryRealTrack
                  ? `当前 VIN ${activeVehicle.vin} 暂无可回放位置点`
                : '当前车辆在样例时间窗内暂无轨迹点'}
          </div>
          {canQueryRealTrack && (
            <div className="vpc-history-note">
              <span>查询来源：{trackState.source}</span>
              {trackState.error && <span>边界：{trackState.error}</span>}
            </div>
          )}
        </div>
      </section>
    );
  }

  const replayFinished = activeIndex >= points.length - 1;
  const togglePlayback = () => {
    if (isPlaying) {
      setIsPlaying(false);
      return;
    }
    if (replayFinished) {
      setPlaybackIndex(0);
    }
    setIsPlaying(true);
  };
  const trackMapPoints: VehicleMapPoint[] = points.map((point, index) => ({
    id: point.id,
    label: point.time,
    longitude: point.longitude ?? activeVehicle.longitude + index * 0.012,
    latitude: point.latitude ?? activeVehicle.latitude + index * 0.008,
    online: point.state !== 'alert',
    title: `${point.time} ${point.address}`
  }));
  const timelineWindowSize = 12;
  const timelineStart = showAllTrackNodes
    ? 0
    : Math.min(
      Math.max(activeIndex - Math.floor(timelineWindowSize / 2), 0),
      Math.max(points.length - timelineWindowSize, 0)
    );
  const timelineEnd = showAllTrackNodes
    ? points.length
    : Math.min(points.length, timelineStart + timelineWindowSize);
  const displayedTimelinePoints = points.slice(timelineStart, timelineEnd).map((point, offset) => ({
    point,
    index: timelineStart + offset
  }));
  const displayedSegments = replaySegments.slice(0, segmentVisibleLimit);
  const openCurrentPointRaw = () => {
    if (!currentPoint.timestampMs || !Number.isFinite(currentPoint.timestampMs)) {
      onOpenHistory(activeVehicle.vin, replaySource.protocol);
      return;
    }
    const rawWindow = buildReplayRawLookupWindow(currentPoint.timestampMs);
    onOpenHistory(activeVehicle.vin, replaySource.protocol, {
      dateFrom: rawWindow.dateFrom,
      dateTo: rawWindow.dateTo,
      fields: ['lat_lon', 'speed_kph', 'total_mileage_km', 'quality_delay'],
      hint: {
        protocol: replaySource.protocol,
        fieldKey: 'vehicle_locations.ts',
        query: `${trackPointTimeLabel(currentPoint)} ±2 min`,
        selectedField: 'lat_lon',
        origin: 'track-node'
      }
    });
  };

  return (
      <section className="vpc-page-stack vpc-replay-page">
      <ReplayVehicleContext
        activeSource={replaySource}
        activeVehicle={activeVehicle}
        canQueryRealTrack={canQueryRealTrack}
        usingRealData={usingRealData}
      />
      {!canQueryRealTrack && (
        <div className="vpc-real-source-banner vpc-replay-blueprint-banner">
          <div>
            <strong>真实轨迹未读取，当前只展示轨迹回放蓝图</strong>
            <span>不会把本地样例轨迹当作 TDengine 轨迹；真实轨迹需要由 history locations 返回位置点后再计算分段和证据。</span>
          </div>
          {replayFallbackSummary.map((item) => (
            <Metric key={item.label} label={item.label} value={item.value} />
          ))}
        </div>
      )}
      {!canQueryRealTrack && (
        <div className="vpc-source-evidence-layers vpc-replay-blueprint-layers" aria-label="轨迹回放蓝图边界">
          {replayFallbackBoundaries.map((item) => (
            <article key={item.title}>
              <span>{item.title}</span>
              <strong>{item.source}</strong>
              <em>{item.detail}</em>
            </article>
          ))}
        </div>
      )}
      {!canQueryRealTrack && showReplaySamples && (
        <div className="vpc-replay-sample-gate">
          <div>
            <strong>正在展示轨迹样例</strong>
            <span>这些轨迹点只验证地图、时间轴、播放和分段布局，不代表 TDengine 查询结果。</span>
          </div>
          <Button
            onClick={() => {
              setIsPlaying(false);
              setShowReplaySamples(false);
            }}
            theme="borderless"
          >
            收起轨迹样例
          </Button>
        </div>
      )}
      {replayQueryStatus}
      {replayQueryPanel}
      {trackTimeWindowNode}
      <div className="vpc-replay-summary">
        {replaySummary.map((item) => (
          <article className={`vpc-replay-summary-card vpc-replay-summary-${item.tone}`} key={item.label}>
            <span>{item.label}</span>
            <strong>{item.value}</strong>
            <em>{item.sub}</em>
          </article>
        ))}
      </div>

      <div className={`vpc-track-quality-audit vpc-track-quality-${trackQualityAudit.status}`} aria-label="轨迹质量审计">
        <div className="vpc-track-quality-main">
          <span>轨迹质量审计</span>
          <strong>{trackQualityAudit.title}</strong>
          <em>{trackQualityAudit.detail}</em>
        </div>
        <Metric label="时间跨度" value={trackQualityAudit.timeRange} />
        <Metric label="GPS 距离" value={`${formatNumber(trackQualityAudit.gpsDistanceKm, 2)} km`} />
        <Metric label="总里程差" value={`${formatNumber(trackQualityAudit.mileageDeltaKm, 2)} km`} />
        <Metric label="最大间隔" value={trackQualityAudit.maxGapMinutes == null ? '--' : `${formatNumber(trackQualityAudit.maxGapMinutes, 1)} min`} />
        <div className="vpc-track-quality-flags">
          <span>重复坐标段 {trackQualityAudit.duplicateCoordinateSegments}/{Math.max(trackQualityAudit.pointCount - 1, 0)}</span>
          <span>低速停留段 {trackQualityAudit.stationarySegments}</span>
          <span>点数 {trackQualityAudit.pointCount}</span>
        </div>
      </div>

      <section className="vpc-replay-workbench">
        <div className="vpc-panel vpc-replay-map">
          <div className="vpc-panel-head">
            <strong>{activeVehicle.plate} {canQueryRealTrack ? '轨迹' : '轨迹样例'}</strong>
            <Tag color={canQueryRealTrack ? 'green' : 'grey'}>{canQueryRealTrack ? '真实轨迹' : '样例'}</Tag>
          </div>
          <div className="vpc-track-canvas vpc-track-canvas-amap">
            <VehicleMap
              fallbackLabel="高德地图未配置，显示轨迹坐标预览"
              heightClassName="vpc-amap-replay"
              mode="track"
              onPointSelect={(point) => {
                const nextIndex = points.findIndex((item) => item.id === point.id);
                if (nextIndex >= 0) {
                  setIsPlaying(false);
                  setPlaybackIndex(nextIndex);
                }
              }}
              points={trackMapPoints}
              selectedId={currentPoint.id}
            >
            <div className="vpc-replay-focus">
              <span>{currentPoint.state === 'alert' ? '异常节点' : currentPoint.state === 'stop' ? '停留节点' : '运行节点'}</span>
              <strong>{trackAddressState.address ?? currentPoint.address}</strong>
              <em>{currentPoint.note}</em>
              <div>
                <span>{currentPoint.speedKph} km/h</span>
                <span>{formatNumber(currentPoint.mileageKm, 1)} km</span>
              </div>
              <div className="vpc-replay-focus-address" aria-label="当前轨迹点地址解析">
                <Tag color={mapAddressStatusColor(trackAddressState)} size="small">{mapAddressStatusLabel(trackAddressState)}</Tag>
                {trackAddressState.region ? <span>{trackAddressState.region}</span> : null}
              </div>
            </div>
            </VehicleMap>
          </div>
          {canQueryRealTrack && (
            <div className="vpc-replay-source">
              <span>VIN {activeVehicle.vin}</span>
              <span>{trackState.total} 条位置记录</span>
              <span>{trackState.fetchedAt ? `刷新 ${trackState.fetchedAt}` : '实时查询'}</span>
            </div>
          )}
          <div className="vpc-current-node-evidence" aria-label="当前轨迹节点证据">
            <div>
              <span>当前节点</span>
              <strong>{currentPoint.time}</strong>
              <em>{currentPoint.state === 'alert' ? '异常节点' : currentPoint.state === 'stop' ? '停留节点' : '运行节点'}</em>
            </div>
            <Metric label="速度" value={`${currentPoint.speedKph} km/h`} />
            <Metric label="总里程" value={`${formatNumber(currentPoint.mileageKm, 1)} km`} />
            <div className="vpc-current-node-address">
              <span>地图地址</span>
              <strong>{trackAddressState.address ?? currentPoint.address}</strong>
              <em>{trackAddressState.provider ?? trackAddressState.error ?? trackAddressState.source}</em>
            </div>
            <Button
              aria-label="打开当前轨迹点高德坐标"
              data-amap-track-marker-url={canOpenTrackPointMarker ? amapTrackPointMarkerURL(activeVehicle, currentPoint) : ''}
              disabled={!canOpenTrackPointMarker}
              onClick={() => {
                const url = amapTrackPointMarkerURL(activeVehicle, currentPoint);
                if (url) {
                  window.open(url, '_blank', 'noopener,noreferrer');
                }
              }}
              size="small"
              theme="borderless"
            >
              高德坐标
            </Button>
            <Button
              data-replay-raw-window={currentPoint.timestampMs ? JSON.stringify(buildReplayRawLookupWindow(currentPoint.timestampMs)) : ''}
              onClick={openCurrentPointRaw}
              size="small"
              type="primary"
            >
              查节点 RAW
            </Button>
          </div>
          <div className="vpc-replay-controls">
            <Button disabled={points.length <= 1} onClick={togglePlayback} type="primary">
              {isPlaying ? '暂停' : replayFinished ? '重播' : '播放'}
            </Button>
            <input
              max={Math.max(points.length - 1, 0)}
              min={0}
              onChange={(event) => {
                setIsPlaying(false);
                setPlaybackIndex(Number(event.target.value));
              }}
              type="range"
              value={activeIndex}
            />
            <div className="vpc-replay-speed" aria-label="回放速度">
              {([1, 2, 4] as const).map((speed) => (
                <button
                  className={playbackSpeed === speed ? 'vpc-replay-speed-active' : ''}
                  key={speed}
                  onClick={() => setPlaybackSpeed(speed)}
                  type="button"
                >
                  {speed}x
                </button>
              ))}
            </div>
            <span className="vpc-replay-progress">
              节点 {activeIndex + 1}/{points.length} · {currentPoint.time}
            </span>
          </div>
        </div>

        <aside className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>轨迹节点</strong>
            <span>{displayedTimelinePoints.length} / {points.length} 个节点</span>
          </div>
          <div className="vpc-timeline-window-note">
            <span>
              {showAllTrackNodes
                ? `已展示全部${canQueryRealTrack ? '轨迹' : '样例'}节点。`
                : `当前展示节点 ${timelineStart + 1}-${timelineEnd}，播放和地图仍使用全部 ${points.length} 个${canQueryRealTrack ? '真实点' : '样例点'}。`}
            </span>
            {points.length > timelineWindowSize && (
              <Button
                onClick={() => setShowAllTrackNodes((value) => !value)}
                size="small"
                theme={showAllTrackNodes ? 'borderless' : 'solid'}
                type={showAllTrackNodes ? 'tertiary' : 'primary'}
              >
                {showAllTrackNodes ? '收起节点' : '查看全部'}
              </Button>
            )}
          </div>
          <div className="vpc-timeline">
            {displayedTimelinePoints.map(({ point, index }) => (
              <button
                className={`vpc-timeline-item ${index === activeIndex ? 'vpc-timeline-item-active' : ''}`}
                key={point.id}
                onClick={() => {
                  setIsPlaying(false);
                  setPlaybackIndex(index);
                }}
                ref={index === activeIndex ? timelineActiveRef : undefined}
                type="button"
              >
                <time>{point.time}</time>
                <strong>{point.address}</strong>
                <span>{point.note}</span>
                <em>{point.speedKph} km/h / {formatNumber(point.mileageKm, 1)} km</em>
              </button>
            ))}
          </div>
        </aside>
      </section>

      <section className="vpc-replay-bottom">
        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>分段里程</strong>
            <span>显示 {displayedSegments.length} / {replaySegments.length} 段</span>
          </div>
          <div className="vpc-segment-list">
            {displayedSegments.map((segment) => (
              <article className={`vpc-segment-row vpc-segment-${segment.state}`} key={segment.id}>
                <strong>{segment.from} - {segment.to}</strong>
                <span>{formatNumber(segment.distanceKm, 1)} km</span>
                <em>{segment.speedDeltaKph >= 0 ? '+' : ''}{segment.speedDeltaKph} km/h</em>
              </article>
            ))}
          </div>
          {replaySegments.length > 12 && (
            <div className="vpc-replay-row-load">
              <span>
                已显示 {displayedSegments.length} / {replaySegments.length} 个相邻位置分段，统计摘要仍基于全部{canQueryRealTrack ? '真实轨迹点' : '样例轨迹点'}。
              </span>
              <div>
                {segmentVisibleLimit < replaySegments.length && (
                  <Button onClick={() => setSegmentVisibleLimit((value) => Math.min(value + 12, replaySegments.length))} size="small" type="primary">
                    再显示 12 段
                  </Button>
                )}
                {segmentVisibleLimit > 12 && (
                  <Button onClick={() => setSegmentVisibleLimit(12)} size="small" theme="borderless">
                    收起
                  </Button>
                )}
              </div>
            </div>
          )}
        </div>

        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>回放证据</strong>
            <span>可查询来源</span>
          </div>
          <div className="vpc-replay-evidence-grid">
            {replayEvidenceItems.map((item) => (
              <article className={`vpc-replay-evidence-card vpc-replay-evidence-${item.status}`} key={item.title}>
                <div>
                  <strong>{item.title}</strong>
                  <Tag color={item.status === 'ready' ? 'green' : 'orange'}>{item.status === 'ready' ? '可查' : '关注'}</Tag>
                </div>
                <span>{item.source}</span>
                <p>{item.detail}</p>
              </article>
            ))}
          </div>
        </div>
      </section>
    </section>
  );
}

function ReplayVehicleContext({
  activeVehicle,
  activeSource,
  canQueryRealTrack,
  usingRealData
}: {
  activeVehicle: VehicleRecord;
  activeSource: ReturnType<typeof getVehiclePrimarySource>;
  canQueryRealTrack: boolean;
  usingRealData: boolean;
}) {
  const title = usingRealData
    ? '当前回放车辆'
    : canQueryRealTrack
      ? '当前回放车辆 / 历史轨迹查询'
      : '当前回放车辆 / 样例快照';
  const detail = usingRealData
    ? `${activeSource.sourceName} / ${activeSource.lastSeen}`
    : canQueryRealTrack
      ? `${activeSource.sourceName} / 按 VIN + 时间窗查询`
      : `${activeSource.sourceName} / 非生产实时状态`;
  return (
    <div className="vpc-history-context">
      <span>{title}</span>
      <strong>{activeVehicle.plate} / {activeVehicle.vin}</strong>
      <em>{detail}</em>
    </div>
  );
}

function HistoryVehicleContext({
  query,
  contextVehicle,
  protocolFilter,
  onOpenCommand,
  onOpenReplay
}: {
  query: string;
  contextVehicle?: VehicleRecord;
  protocolFilter: ProtocolFilter;
  onOpenCommand: (vin: string) => void;
  onOpenReplay: (vin: string) => void;
}) {
  const scopedSource = contextVehicle && protocolFilter !== 'ALL'
    ? contextVehicle.sources.find((source) => source.protocol === protocolFilter)
    : undefined;
  const primarySource = contextVehicle ? scopedSource ?? getVehiclePrimarySource(contextVehicle) : undefined;
  const protocols = contextVehicle
    ? Array.from(new Set(contextVehicle.sources.map((source) => source.protocol)))
    : [];
  const contextLabel = protocolFilter === 'ALL' ? '当前车辆上下文' : `当前车辆上下文 / ${protocolMeta[protocolFilter].short}`;
  return (
    <div className={`vpc-history-context ${contextVehicle ? 'vpc-history-context-linked' : 'vpc-history-context-unmatched'}`}>
      <div className="vpc-history-context-main">
        <span>{contextLabel}</span>
        <strong>{contextVehicle ? `${contextVehicle.plate} / ${contextVehicle.vin}` : query.trim()}</strong>
        <em>
          {contextVehicle && primarySource
            ? `${statusLabel[contextVehicle.status]} / ${primarySource.sourceName} / ${primarySource.lastSeen}`
            : '未匹配实时快照，仅按输入条件查询 RAW'}
        </em>
      </div>
      {contextVehicle ? (
        <div className="vpc-history-context-protocols" aria-label="该车辆实时来源协议">
          {protocols.map((protocol) => (
            <Tag color={protocolMeta[protocol].color} key={protocol} size="small">
              {protocolMeta[protocol].short}
            </Tag>
          ))}
        </div>
      ) : (
        <div className="vpc-history-context-protocols">
          <Tag color="grey" size="small">未匹配</Tag>
        </div>
      )}
      <div className="vpc-history-context-actions" aria-label="车辆上下文快捷入口">
        <Button
          disabled={!contextVehicle}
          onClick={() => contextVehicle && onOpenCommand(contextVehicle.vin)}
          size="small"
          theme="borderless"
        >
          实时地图
        </Button>
        <Button
          disabled={!contextVehicle}
          onClick={() => contextVehicle && onOpenReplay(contextVehicle.vin)}
          size="small"
          theme="solid"
          type="primary"
        >
          轨迹
        </Button>
      </div>
    </div>
  );
}

function HistoryPage({
  records,
  historyQueried,
  historyDateFrom,
  historyDateTo,
  historyFieldHint,
  contextVehicle,
  canQueryRealRaw,
  onClearHistoryFieldHint,
  onOpenCommand,
  onOpenReplay,
  setHistoryQueried,
  setHistoryDateFrom,
  setHistoryDateTo,
  selectedFields,
  setSelectedFields,
  historyPage,
  historyPageSize,
  setHistoryPage,
  setHistoryPageSize,
  queryPreview,
  query,
  protocolFilter
}: {
  records: typeof historyRecords;
  historyQueried: boolean;
  historyDateFrom: string;
  historyDateTo: string;
  historyFieldHint?: HistoryFieldHint;
  contextVehicle?: VehicleRecord;
  canQueryRealRaw: boolean;
  onClearHistoryFieldHint: () => void;
  onOpenCommand: (vin: string) => void;
  onOpenReplay: (vin: string) => void;
  setHistoryQueried: (value: boolean) => void;
  setHistoryDateFrom: Dispatch<SetStateAction<string>>;
  setHistoryDateTo: Dispatch<SetStateAction<string>>;
  selectedFields: string[];
  setSelectedFields: (value: string[]) => void;
  historyPage: number;
  historyPageSize: number;
  setHistoryPage: (value: number) => void;
  setHistoryPageSize: (value: number) => void;
  queryPreview: HistoryQueryPreview;
  query: string;
  protocolFilter: ProtocolFilter;
}) {
  const offset = (historyPage - 1) * historyPageSize;
  const pageRecords = records.slice(offset, offset + historyPageSize);
  const [queryTick, setQueryTick] = useState(0);
  const [rawFrameState, setRawFrameState] = useState<PrototypeRawFrameState>({
    records: [],
    status: canQueryRealRaw ? 'loading' : 'disabled',
    source: '/api/history/raw-frames/query',
    total: 0,
    limit: historyPageSize,
    offset
  });
  const [selectedRawId, setSelectedRawId] = useState('');
  const [rawFieldQuery, setRawFieldQuery] = useState('');
  const [queryCopyState, setQueryCopyState] = useState<'idle' | 'copied' | 'error'>('idle');
  const [showQueryPayload, setShowQueryPayload] = useState(false);
  const [showHistorySamples, setShowHistorySamples] = useState(false);
  const [rawAddressState, setRawAddressState] = useState<PrototypeMapAddressState>({
    status: 'disabled',
    source: '/api/map/reverse-geocode'
  });
  const historySampleCopy = getSampleBoundaryCopy('history-raw', showHistorySamples);
  const realRecords = canQueryRealRaw ? rawFrameState.records : [];
  const showHistoryTable = canQueryRealRaw || showHistorySamples;
  const displayRecords = canQueryRealRaw ? realRecords : showHistorySamples ? pageRecords : [];
  const totalRecords = canQueryRealRaw ? rawFrameState.total : showHistorySamples ? records.length : 0;
  const sampleRecordTotal = records.length;
  const totalPages = Math.max(1, Math.ceil(totalRecords / historyPageSize));
  const fieldSample = canQueryRealRaw ? Object.entries(realRecords[0]?.parsedFields ?? {}).slice(0, 6) : [];
  const historyFallbackSummary = [
    { label: '真实 RAW', value: '待读取' },
    { label: '查询方式', value: 'POST body' },
    { label: '字段裁剪', value: `${selectedFields.length}` },
    { label: '样例验证', value: showHistorySamples ? '已展开' : '默认收起' }
  ];
  const historyFallbackBoundaries = [
    {
      title: 'RAW 查询',
      source: 'TDengine raw_frames',
      detail: '真实能力需要 `/api/history/raw-frames/query` 返回 RAW 行和 parsed_fields；当前失败态不访问 TDengine。'
    },
    {
      title: '字段裁剪',
      source: 'POST body fields',
      detail: '字段选择只展示请求体设计，避免 URI 过长；未连接真实接口时不代表字段已命中。'
    },
    {
      title: '证据联动',
      source: 'RAW / 轨迹 / AMap',
      detail: '真实记录可跳转轨迹和高德坐标；样例记录只验证表格、分页和请求布局。'
    }
  ];
  const preferredRawRecord = useMemo(() => pickPreferredRawRecord(realRecords), [realRecords]);
  const selectedRawRecord = useMemo(
    () => realRecords.find((record) => record.id === selectedRawId) ?? preferredRawRecord ?? realRecords[0],
    [preferredRawRecord, realRecords, selectedRawId]
  );
  const selectedRawFields = useMemo(
    () => Object.entries(selectedRawRecord?.parsedFields ?? {}),
    [selectedRawRecord]
  );
  const selectedRawCoordinateEvidence = useMemo(
    () => selectedRawRecord ? rawCoordinateEvidence(selectedRawRecord.protocol, selectedRawRecord.parsedFields) : undefined,
    [selectedRawRecord]
  );
  const selectedRawAddressEvidence = useMemo(
    () => rawCoordinateAddressEvidence(selectedRawCoordinateEvidence, {
      status: rawAddressState.status,
      provider: rawAddressState.provider,
      address: rawAddressState.address,
      region: rawAddressState.region,
      error: rawAddressState.error
    }),
    [rawAddressState, selectedRawCoordinateEvidence]
  );
  const rawTimeWindowAudit = useMemo(
    () => buildRawTimeWindowAudit({
      records: realRecords,
      dateFrom: historyDateFrom,
      dateTo: historyDateTo
    }),
    [historyDateFrom, historyDateTo, realRecords]
  );
  const rawResponseAudit = useMemo(() => {
    const requestedFields = queryPreview.payload.fields;
    const fieldCoverage = requestedFields.map((field) => ({
      field,
      hitCount: rawFieldHitCount(realRecords, field)
    }));
    const hitFieldCount = fieldCoverage.filter((item) => item.hitCount > 0).length;
    return {
      requestedFields,
      fieldCoverage,
      hitFieldCount,
      emptyParsedRows: realRecords.filter((record) => record.fieldCount === 0).length,
      returnedFieldTotal: realRecords.reduce((sum, record) => sum + record.fieldCount, 0),
      rawSizeTotalBytes: realRecords.reduce((sum, record) => sum + record.rawSizeBytes, 0)
    };
  }, [queryPreview.payload.fields, realRecords]);
  const historyHintLabel = historyFieldHint?.origin === 'track-node' ? '来自轨迹节点回查' : '来自实时字段定位';
  const historyHintDetail = historyFieldHint?.origin === 'track-node'
    ? `${historyFieldHint.protocol} / ${historyFieldHint.fieldKey} / ${historyDateFrom} 至 ${historyDateTo}`
    : historyFieldHint
      ? `${historyFieldHint.protocol} / ${historyFieldHint.fieldKey}`
      : '';
  const normalizedRawFieldQuery = rawFieldQuery.trim().toLowerCase();
  const visibleRawFields = useMemo(() => {
    if (!normalizedRawFieldQuery) {
      return selectedRawFields;
    }
    return selectedRawFields.filter(([key, value]) =>
      key.toLowerCase().includes(normalizedRawFieldQuery) ||
      String(value ?? '').toLowerCase().includes(normalizedRawFieldQuery)
    );
  }, [normalizedRawFieldQuery, selectedRawFields]);
  const selectedRawFieldPreview = visibleRawFields.slice(0, 36);
  const queryEvidenceText = useMemo(() => JSON.stringify({
    method: queryPreview.method,
    endpoint: queryPreview.endpoint,
    storage: queryPreview.storage,
    source: canQueryRealRaw ? rawFrameState.source : queryPreview.endpoint,
    status: canQueryRealRaw ? rawFrameState.status : 'preview',
    total: canQueryRealRaw ? rawFrameState.total : totalRecords,
    payload: queryPreview.payload
  }, null, 2), [canQueryRealRaw, queryPreview.endpoint, queryPreview.method, queryPreview.payload, queryPreview.storage, rawFrameState.source, rawFrameState.status, rawFrameState.total, totalRecords]);
  const toggleField = (fieldKey: string) => {
    setHistoryPage(1);
    setSelectedFields(
      selectedFields.includes(fieldKey)
        ? selectedFields.filter((item) => item !== fieldKey)
        : [...selectedFields, fieldKey]
    );
  };
  const copyHistoryQueryEvidence = async () => {
    try {
      await navigator.clipboard.writeText(queryEvidenceText);
      setQueryCopyState('copied');
      window.setTimeout(() => setQueryCopyState('idle'), 1600);
    } catch {
      setQueryCopyState('error');
    }
  };

  useEffect(() => {
    if (!canQueryRealRaw || !historyQueried) {
      return undefined;
    }
    let mounted = true;
    const nextOffset = (historyPage - 1) * historyPageSize;
    setRawFrameState((current) => ({
      ...current,
      status: 'loading',
      limit: historyPageSize,
      offset: nextOffset
    }));
    loadPrototypeRawFrames({
      vin: query,
      protocol: protocolFilter === 'ALL' ? undefined : protocolFilter,
      fields: selectedFields,
      dateFrom: historyDateFrom,
      dateTo: historyDateTo,
      limit: historyPageSize,
      offset: nextOffset
    }).then((next) => {
      if (mounted) {
        setRawFrameState(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [
    historyDateFrom,
    historyDateTo,
    historyPage,
    historyPageSize,
    historyQueried,
    protocolFilter,
    query,
    queryTick,
    selectedFields,
    canQueryRealRaw
  ]);

  useEffect(() => {
    if (!canQueryRealRaw || realRecords.length === 0) {
      setSelectedRawId('');
      return;
    }
    setSelectedRawId((current) => {
      if (realRecords.some((record) => record.id === current)) {
        return current;
      }
      return pickPreferredRawRecord(realRecords)?.id ?? realRecords[0].id;
    });
  }, [canQueryRealRaw, realRecords]);

  useEffect(() => {
    if (!historyFieldHint) {
      setRawFieldQuery('');
    }
  }, [historyFieldHint, selectedRawRecord?.id]);

  useEffect(() => {
    if (canQueryRealRaw) {
      setShowHistorySamples(false);
    }
  }, [canQueryRealRaw]);

  useEffect(() => {
    if (historyFieldHint) {
      setRawFieldQuery(historyFieldHint.query);
    }
  }, [historyFieldHint?.fieldKey, historyFieldHint?.query]);

  useEffect(() => {
    let mounted = true;
    if (!selectedRawCoordinateEvidence) {
      setRawAddressState({
        status: 'disabled',
        source: '/api/map/reverse-geocode',
        error: '当前 RAW 无有效坐标'
      });
      return () => {
        mounted = false;
      };
    }
    setRawAddressState({
      status: 'loading',
      source: '/api/map/reverse-geocode'
    });
    loadPrototypeMapAddress(
      selectedRawCoordinateEvidence.longitude,
      selectedRawCoordinateEvidence.latitude
    ).then((next) => {
      if (mounted) {
        setRawAddressState(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [
    selectedRawCoordinateEvidence?.latitude,
    selectedRawCoordinateEvidence?.longitude,
    selectedRawRecord?.id
  ]);

  const customSelectedFields = selectedFields.filter((field) => !fieldOptions.some((option) => option.key === field));
  const rawQueryTone = rawFrameQueryTone(rawFrameState.status);
  const rawQueryTitle = rawFrameState.status === 'loading'
    ? '正在查询历史 RAW'
    : rawFrameState.status === 'ready'
      ? '历史 RAW 已返回'
      : rawFrameState.status === 'empty'
        ? '历史 RAW 无结果'
        : rawFrameState.status === 'error'
          ? '历史 RAW 查询失败'
          : '历史 RAW 未启用';
  const rawQueryDetail = rawFrameState.status === 'error'
    ? rawFrameState.error ?? '接口异常'
    : rawFrameState.status === 'ready'
      ? 'TDengine raw_frames/query 已返回真实记录，可继续查看字段命中和 RAW 证据。'
      : rawFrameState.status === 'empty'
        ? '当前 VIN、协议、时间窗或字段裁剪没有返回 RAW 记录。'
        : rawFrameState.status === 'loading'
          ? '正在读取 TDengine RAW 与 parsed_fields，结果不会回退到本地样例。'
          : '真实 RAW 查询关闭时只展示请求蓝图和样例验证入口。';

  return (
    <section className="vpc-page-stack">
      {!canQueryRealRaw && (
        <div className="vpc-real-source-banner vpc-history-blueprint-banner">
          <div>
            <strong>真实 RAW 查询未读取，当前只展示历史查询蓝图</strong>
            <span>不会把本地样例数据当作 TDengine 查询结果；真实 RAW 需要由 raw_frames/query 返回 parsed_fields 后再展示字段命中和定位证据。</span>
          </div>
          {historyFallbackSummary.map((item) => (
            <Metric key={item.label} label={item.label} value={item.value} />
          ))}
        </div>
      )}

      {!canQueryRealRaw && (
        <div className="vpc-source-evidence-layers vpc-history-blueprint-layers" aria-label="历史查询蓝图边界">
          {historyFallbackBoundaries.map((item) => (
            <article key={item.title}>
              <span>{item.title}</span>
              <strong>{item.source}</strong>
              <em>{item.detail}</em>
            </article>
          ))}
        </div>
      )}

      {canQueryRealRaw && (
        <div className={`vpc-history-query-status vpc-history-query-status-${rawQueryTone}`} aria-label="历史 RAW 查询状态">
          <div className="vpc-history-query-status-main">
            <span>RAW 查询状态</span>
            <strong>{rawQueryTitle}</strong>
            <em>{rawQueryDetail}</em>
          </div>
          <Metric label="状态" value={rawFrameQueryStatusLabel(rawFrameState.status)} />
          <Metric label="结果" value={`${rawFrameState.total}`} />
          <Metric label="字段" value={`${selectedFields.length}`} />
          <Metric label="来源" value={rawFrameState.source.replace('/api/history/', '')} />
        </div>
      )}

      <div className="vpc-history-workbench">
        <div className="vpc-panel vpc-query-panel">
          <div className="vpc-panel-head">
            <strong>查询条件</strong>
            <Button
              onClick={() => {
                setHistoryQueried(true);
                setHistoryPage(1);
                setQueryTick((value) => value + 1);
              }}
              type="primary"
            >
              查询
            </Button>
          </div>
          {query.trim() && (
            <HistoryVehicleContext
              contextVehicle={contextVehicle}
              onOpenCommand={onOpenCommand}
              onOpenReplay={onOpenReplay}
              protocolFilter={protocolFilter}
              query={query}
            />
          )}
          {historyFieldHint && (
            <div className="vpc-history-field-context" aria-label="RAW 查询定位上下文">
              <div>
                <span>{historyHintLabel}</span>
                <strong>{historyFieldHint.query}</strong>
                <em>{historyHintDetail}</em>
              </div>
              <Button onClick={onClearHistoryFieldHint} size="small" theme="borderless">
                清除
              </Button>
            </div>
          )}
          <div className="vpc-query-grid">
            <label>
              <span>时间范围</span>
              <div className="vpc-date-range-inputs">
                <input
                  aria-label="历史查询开始时间"
                  className="vpc-input"
                  onChange={(event) => {
                    setHistoryDateFrom(event.target.value);
                    setHistoryPage(1);
                  }}
                  value={historyDateFrom}
                />
                <input
                  aria-label="历史查询结束时间"
                  className="vpc-input"
                  onChange={(event) => {
                    setHistoryDateTo(event.target.value);
                    setHistoryPage(1);
                  }}
                  value={historyDateTo}
                />
              </div>
              <TimeRangePresetButtons
                onApply={(range) => {
                  setHistoryDateFrom(range.from);
                  setHistoryDateTo(range.to);
                  setHistoryPage(1);
                  setHistoryQueried(true);
                }}
              />
            </label>
            <label>
              <span>返回字段</span>
              <div className="vpc-field-options">
                {fieldOptions.map((field) => (
                  <button
                    aria-label={`切换历史字段 ${field.label}`}
                    className={selectedFields.includes(field.key) ? 'vpc-chip-active' : ''}
                    key={field.key}
                    onClick={() => toggleField(field.key)}
                    type="button"
                  >
                    {field.label}
                  </button>
                ))}
              </div>
              {customSelectedFields.length > 0 && (
                <div className="vpc-custom-field-options" aria-label="自定义返回字段">
                  {customSelectedFields.map((field) => (
                    <span key={field}>{field}</span>
                  ))}
                </div>
              )}
            </label>
            <label>
              <span>分页大小</span>
              <select
                aria-label="历史查询分页大小"
                className="vpc-select"
                onChange={(event) => {
                  setHistoryPage(1);
                  setHistoryPageSize(Number(event.target.value));
                }}
                value={historyPageSize}
              >
                {historyPageSizeOptions.map((size) => (
                  <option key={size} value={size}>
                    {size} 条 / 页
                  </option>
                ))}
              </select>
            </label>
          </div>
        </div>

        <aside className="vpc-panel vpc-query-preview">
          <div className="vpc-panel-head">
            <strong>查询证据</strong>
            <div className="vpc-query-preview-actions">
              <Tag color={canQueryRealRaw ? 'green' : 'grey'}>{canQueryRealRaw ? '真实 RAW' : '请求预览'}</Tag>
              <Button
                aria-label="复制历史 RAW 查询证据"
                data-query-evidence-status={queryCopyState}
                onClick={copyHistoryQueryEvidence}
                size="small"
                theme="borderless"
              >
                {queryCopyState === 'copied' ? '已复制' : queryCopyState === 'error' ? '复制失败' : '复制请求'}
              </Button>
            </div>
          </div>
          <div className="vpc-query-api">
            <strong>{queryPreview.endpoint}</strong>
            <span>{queryPreview.storage}</span>
          </div>
          <div className="vpc-query-summary">
            <article>
              <span>方法</span>
              <strong>{queryPreview.method}</strong>
              <em>POST body 查询</em>
            </article>
            <article>
              <span>请求字段</span>
              <strong>{queryPreview.payload.fields.length}</strong>
              <em>字段裁剪只影响响应体</em>
            </article>
            <article>
              <span>时间窗</span>
              <strong>{chinaShortDateTime(historyDateFrom)} - {chinaShortDateTime(historyDateTo)}</strong>
              <em>按东八区输入</em>
            </article>
          </div>
          <div className="vpc-query-metrics">
            <Metric label="字段" value={`${selectedFields.length}`} />
            <Metric label="Limit" value={`${queryPreview.payload.limit}`} />
            <Metric label="Offset" value={`${queryPreview.payload.offset}`} />
          </div>
          <div className="vpc-query-payload-toggle">
            <span>完整请求体默认收起，避免技术 JSON 抢占历史查询结果。</span>
            <Button
              aria-expanded={showQueryPayload}
              aria-label={showQueryPayload ? '收起历史 RAW 请求体' : '展开历史 RAW 请求体'}
              onClick={() => setShowQueryPayload((value) => !value)}
              size="small"
              theme="borderless"
            >
              {showQueryPayload ? '收起技术详情' : '展开技术详情'}
            </Button>
          </div>
          {showQueryPayload && (
            <pre>{JSON.stringify(queryPreview.payload, null, 2)}</pre>
          )}
          {canQueryRealRaw && (
            <div className="vpc-real-query-state">
              <span>状态：{rawFrameQueryStatusLabel(rawFrameState.status)}</span>
              <span>来源：{rawFrameState.source}</span>
              {rawFrameState.error && <span>边界：{rawFrameState.error}</span>}
            </div>
          )}
        </aside>
      </div>

      <div className="vpc-panel">
        <div className="vpc-panel-head">
          <strong>{canQueryRealRaw ? '历史 Raw / Fields' : 'Raw 样例记录'}</strong>
          <span>
            {canQueryRealRaw
              ? historyQueried ? `${totalRecords} 条结果 / 第 ${historyPage} 页` : '待查询'
              : showHistorySamples ? `${sampleRecordTotal} 条样例 / 第 ${historyPage} 页` : '样例默认收起，不展示本地记录'}
          </span>
        </div>
        {!canQueryRealRaw && (
          <div className="vpc-history-sample-gate">
            <div>
              <strong>{historySampleCopy.title}</strong>
              <span>{historySampleCopy.detail}</span>
            </div>
            <Button onClick={() => setShowHistorySamples((value) => !value)} theme={showHistorySamples ? 'borderless' : 'solid'} type={showHistorySamples ? 'tertiary' : 'primary'}>
              {historySampleCopy.actionLabel}
            </Button>
          </div>
        )}
        {!canQueryRealRaw && !showHistorySamples && (
          <div className="vpc-history-sample-closed" aria-label="Raw 样例记录收起说明">
            <article>
              <span>不展示</span>
              <strong>样例 RAW 表</strong>
              <em>避免把本地记录当作 TDengine raw_frames 结果。</em>
            </article>
            <article>
              <span>保留</span>
              <strong>POST 查询载荷</strong>
              <em>字段裁剪、分页和时间窗仍可评审。</em>
            </article>
            <article>
              <span>等待</span>
              <strong>真实 parsed_fields</strong>
              <em>接口返回后再展示字段命中、定位证据和 RAW 回溯。</em>
            </article>
          </div>
        )}
        {!canQueryRealRaw && showHistorySamples && (
          <div className="vpc-history-note vpc-history-mock-note">
            <span>以下记录来自本地样例数据，只用于验证分页、筛选和请求载荷布局。</span>
            <span>真实 RAW 字段、定位证据和字段命中率需等待 `/api/history/raw-frames/query` 返回后展示。</span>
          </div>
        )}
        {canQueryRealRaw && fieldSample.length > 0 && (
          <div className="vpc-field-sample">
            {fieldSample.map(([key, value]) => (
              <span key={key}>
                <strong>{key}</strong>
                <em>{String(value ?? '--')}</em>
              </span>
            ))}
          </div>
        )}
        {canQueryRealRaw && (
          <div className="vpc-raw-response-audit" aria-label="RAW 返回体控制与字段命中">
            <div className="vpc-raw-response-main">
              <span>返回体控制</span>
              <strong>{rawResponseAudit.requestedFields.length > 0 ? '字段裁剪查询' : '全量 parsed_fields'}</strong>
              <em>POST body 查询，避免 URL 过长；字段裁剪只影响响应体，不改变 RAW 存储。</em>
            </div>
            <Metric label="请求字段" value={rawResponseAudit.requestedFields.length > 0 ? `${rawResponseAudit.requestedFields.length}` : 'ALL'} />
            <Metric label="命中字段" value={rawResponseAudit.requestedFields.length > 0 ? `${rawResponseAudit.hitFieldCount}/${rawResponseAudit.requestedFields.length}` : `${rawResponseAudit.returnedFieldTotal}`} />
            <Metric label="空解析行" value={`${rawResponseAudit.emptyParsedRows}/${realRecords.length}`} />
            <Metric label="RAW 字节" value={`${formatNumber(rawResponseAudit.rawSizeTotalBytes, 0)} B`} />
            {rawResponseAudit.requestedFields.length > 0 && (
              <div className="vpc-raw-response-fields">
                {rawResponseAudit.fieldCoverage.slice(0, 9).map((item) => (
                  <span className={item.hitCount > 0 ? 'vpc-raw-response-field-hit' : ''} key={item.field}>
                    <strong>{item.field}</strong>
                    <em>{item.hitCount}/{realRecords.length}</em>
                  </span>
                ))}
                {rawResponseAudit.fieldCoverage.length > 9 && (
                  <span>
                    <strong>更多字段</strong>
                    <em>{rawResponseAudit.fieldCoverage.length - 9}</em>
                  </span>
                )}
              </div>
            )}
          </div>
        )}
        {canQueryRealRaw && rawResponseAudit.emptyParsedRows > 0 && realRecords.length > 0 && (
          <div className="vpc-raw-frame-split-note" aria-label="RAW 分帧字段提示">
            <strong>分帧字段提示</strong>
            <span>
              当前页有 {rawResponseAudit.emptyParsedRows}/{realRecords.length} 条 RAW 没有命中本次裁剪字段。32960 标准帧和 vendor 帧可能分开发送，
              页面已优先选中字段更完整或带坐标的记录；需要看全部字段时可减少字段裁剪或切换 RAW 行。
            </span>
          </div>
        )}
        {canQueryRealRaw && (
          <div className={`vpc-raw-time-audit vpc-raw-time-audit-${rawTimeWindowAudit.status}`} aria-label="历史 RAW 时间窗核验">
            <div>
              <span>时间窗核验</span>
              <strong>{rawTimeWindowAudit.title}</strong>
              <em>{rawTimeWindowAudit.detail}</em>
            </div>
            <Metric label="接收范围" value={rawTimeWindowAudit.receiveRange} />
            <Metric label="设备范围" value={rawTimeWindowAudit.deviceRange} />
            <Metric label="越界/偏差" value={`${rawTimeWindowAudit.outsideReceiveCount} / ${rawTimeWindowAudit.deviceSkewCount}`} />
          </div>
        )}
        {showHistoryTable && (
          <div className="vpc-table">
            <div className="vpc-table-head vpc-table-row">
              <span>Raw ID</span>
              <span>协议</span>
              <span>帧类型</span>
              <span>接收时间</span>
              <span>来源</span>
              <span>字段/延迟</span>
            </div>
            {historyQueried &&
              displayRecords.map((record) => (
                <div
                  aria-label={`查看 RAW 字段 ${record.id}`}
                  className={`vpc-table-row ${canQueryRealRaw ? '' : 'vpc-table-row-mock'} ${canQueryRealRaw && selectedRawRecord?.id === record.id ? 'vpc-table-row-active' : ''}`}
                  key={record.id}
                  onClick={() => canQueryRealRaw && setSelectedRawId(record.id)}
                  onKeyDown={(event) => {
                    if (!canQueryRealRaw || (event.key !== 'Enter' && event.key !== ' ')) {
                      return;
                    }
                    event.preventDefault();
                    setSelectedRawId(record.id);
                  }}
                  role={canQueryRealRaw ? 'button' : undefined}
                  tabIndex={canQueryRealRaw ? 0 : undefined}
                >
                  <strong data-label="Raw ID">{record.id}</strong>
                  <span data-label="协议"><Tag color={protocolMeta[record.protocol].color}>{protocolMeta[record.protocol].short}</Tag></span>
                  <span data-label="帧类型">{record.frameType}</span>
                  <span data-label="接收时间">{record.receiveTime}</span>
                  <span data-label="来源">{record.sourceName}</span>
                  <span data-label="字段/延迟">{record.fieldCount} / {record.latencyMs} ms</span>
                </div>
              ))}
          </div>
        )}
        {canQueryRealRaw && selectedRawRecord && (
          <section className="vpc-raw-inspector" aria-label="选中 RAW 解析字段">
            <div className="vpc-raw-inspector-head">
              <div>
                <span>选中 RAW</span>
                <strong>{selectedRawRecord.id}</strong>
                <em>{selectedRawRecord.frameType} / {selectedRawRecord.receiveTime}</em>
              </div>
              <div>
                <Metric label="返回字段" value={`${selectedRawFields.length}`} />
                <Metric label="延迟" value={`${selectedRawRecord.latencyMs} ms`} />
              </div>
            </div>
            {selectedRawCoordinateEvidence && (
              <div className="vpc-raw-location-evidence" aria-label="选中 RAW 定位证据">
                <div className="vpc-raw-location-main">
                  <span>RAW 定位证据</span>
                  <strong>{selectedRawCoordinateEvidence.latitude.toFixed(6)}, {selectedRawCoordinateEvidence.longitude.toFixed(6)}</strong>
                  <em>{selectedRawCoordinateEvidence.latitudeKey} / {selectedRawCoordinateEvidence.longitudeKey}</em>
                </div>
                <div className={`vpc-raw-address-evidence vpc-raw-address-${selectedRawAddressEvidence.tone}`}>
                  <span>地址解析</span>
                  <strong>{selectedRawAddressEvidence.label}</strong>
                  <em>{selectedRawAddressEvidence.detail}</em>
                  <small>{selectedRawAddressEvidence.evidence}</small>
                  <Tag color={rawAddressToneColor(selectedRawAddressEvidence.tone)} size="small">
                    {rawAddressState.source.includes('AMap Web JS') ? 'AMap 兜底' : '服务端优先'}
                  </Tag>
                </div>
                <Metric
                  label="速度"
                  value={selectedRawCoordinateEvidence.speedKmh == null ? '--' : `${formatNumber(selectedRawCoordinateEvidence.speedKmh, 1)} km/h`}
                />
                <Metric
                  label="总里程"
                  value={selectedRawCoordinateEvidence.totalMileageKm == null ? '--' : `${formatNumber(selectedRawCoordinateEvidence.totalMileageKm, 1)} km`}
                />
                <Metric
                  label="里程字段"
                  value={selectedRawCoordinateEvidence.totalMileageKey
                    ? `${selectedRawCoordinateEvidence.totalMileageUnitEvidence ?? 'km'}`
                    : '--'}
                />
                <Metric
                  label="方向/海拔"
                  value={`${selectedRawCoordinateEvidence.directionDeg == null ? '--' : `${formatNumber(selectedRawCoordinateEvidence.directionDeg, 0)}°`} / ${selectedRawCoordinateEvidence.altitudeM == null ? '--' : `${formatNumber(selectedRawCoordinateEvidence.altitudeM, 0)}m`}`}
                />
                <Button
                  aria-label="打开选中 RAW 高德坐标"
                  data-amap-raw-marker-url={amapRawMarkerURL(selectedRawRecord, selectedRawCoordinateEvidence)}
                  onClick={() => window.open(amapRawMarkerURL(selectedRawRecord, selectedRawCoordinateEvidence), '_blank', 'noopener,noreferrer')}
                  size="small"
                  theme="borderless"
                >
                  高德坐标
                </Button>
                <Button
                  disabled={!selectedRawRecord.vin || selectedRawRecord.vin === 'unknown'}
                  onClick={() => onOpenReplay(selectedRawRecord.vin)}
                  size="small"
                  type="primary"
                >
                  查轨迹
                </Button>
              </div>
            )}
            <div className="vpc-raw-inspector-tools">
              <Input
                aria-label="搜索 RAW 解析字段"
                placeholder="搜索字段 key / value，例如 total_mileage 或 latitude"
                prefix={<IconSearch />}
                value={rawFieldQuery}
                onChange={setRawFieldQuery}
              />
              <span>命中 {visibleRawFields.length} / 返回 {selectedRawFields.length}</span>
            </div>
            {selectedRawFieldPreview.length === 0 ? (
              <div className="vpc-empty">
                {selectedRawFields.length === 0
                  ? '当前 RAW 响应未返回 parsed_fields，请调整字段裁剪或查询条件。'
                  : '当前搜索条件没有命中字段，请换一个字段名或字段值。'}
              </div>
            ) : (
              <div className="vpc-raw-field-grid">
                {selectedRawFieldPreview.map(([key, value]) => (
                  <div className="vpc-raw-field" key={key}>
                    <span>{key}</span>
                    <strong>{String(value ?? '--')}</strong>
                  </div>
                ))}
              </div>
            )}
            {visibleRawFields.length > selectedRawFieldPreview.length && (
              <div className="vpc-history-note">
                <span>当前仅展示前 {selectedRawFieldPreview.length} 个命中字段，完整结果仍在本次 RAW 查询响应中。</span>
              </div>
            )}
          </section>
        )}
        {showHistoryTable && historyQueried && displayRecords.length === 0 && (
          <div className="vpc-empty">
            {canQueryRealRaw && rawFrameState.status === 'loading'
              ? '正在查询 TDengine RAW...'
              : canQueryRealRaw && rawFrameState.status === 'error'
                ? `历史 RAW 查询失败：${rawFrameState.error ?? '接口异常'}`
                : '当前条件没有历史 RAW 记录'}
          </div>
        )}
        {showHistoryTable && (
          <div className="vpc-pagination">
            <span>
              {totalRecords === 0 ? '0-0' : `${offset + 1}-${Math.min(offset + historyPageSize, totalRecords)}`} / {totalRecords}
            </span>
            <div>
              <Button disabled={historyPage <= 1} onClick={() => setHistoryPage(historyPage - 1)}>
                上一页
              </Button>
              <Button disabled={historyPage >= totalPages} onClick={() => setHistoryPage(historyPage + 1)}>
                下一页
              </Button>
            </div>
          </div>
        )}
        <div className="vpc-history-note">
          <span>{canQueryRealRaw ? '当前结果来自 TDengine raw_frames/query，字段名按三类协议映射为真实 parsed_fields。' : showHistorySamples ? '当前为查询蓝图和样例记录，不读取 TDengine，也不证明字段已命中。' : '当前为查询蓝图，样例记录默认收起，不读取 TDengine，也不证明字段已命中。'}</span>
          <span>{canQueryRealRaw ? '完整 payload 仍保留在 raw_frames / payload_chunks，可按 RAW ID 回溯。' : '真实上线后完整 payload 应保留在 raw_frames / payload_chunks，并按 RAW ID 回溯。'}</span>
        </div>
      </div>
    </section>
  );
}

type AlertSignalScope = 'ALL' | 'P1' | 'LATENCY' | 'MISSING' | 'ALARM' | 'CAPABILITY';
type AlertLatencyThresholdSec = 10 | 30 | 60;

function alertSignalLatencyMs(signal: PrototypeAlertSignal) {
  const latencyEvidence = signal.evidence.find((item) => item.label === '延迟');
  if (!latencyEvidence) {
    return undefined;
  }
  const match = latencyEvidence.value.match(/(\d+)/);
  return match ? Number(match[1]) : undefined;
}

function alertSignalMatchesThreshold(signal: PrototypeAlertSignal, latencyThresholdSec: AlertLatencyThresholdSec) {
  if (signal.type !== '链路延迟') {
    return true;
  }
  return (alertSignalLatencyMs(signal) ?? 0) >= latencyThresholdSec * 1000;
}

function alertSignalMatchesScope(signal: PrototypeAlertSignal, scope: AlertSignalScope) {
  if (scope === 'P1') {
    return signal.level === 'P1';
  }
  if (scope === 'LATENCY') {
    return signal.type === '链路延迟';
  }
  if (scope === 'MISSING') {
    return signal.type === '字段缺失';
  }
  if (scope === 'ALARM') {
    return signal.type === '协议告警位';
  }
  if (scope === 'CAPABILITY') {
    return signal.type === '能力缺口';
  }
  return true;
}

function AlertsPage({
  canQueryRealAlerts,
  query,
  protocolFilter,
  sourceFilter,
  onOpenHistory,
  onOpenReplay
}: {
  canQueryRealAlerts: boolean;
  query: string;
  protocolFilter: ProtocolFilter;
  sourceFilter: string;
  onOpenHistory: (vin: string, protocol?: Protocol) => void;
  onOpenReplay: (vin: string) => void;
}) {
  const [signalState, setSignalState] = useState<PrototypeAlertSignalState>({
    signals: [],
    status: canQueryRealAlerts ? 'loading' : 'disabled',
    source: '/api/realtime/locations + /api/history/locations',
    realtimeRows: 0,
    historyRows: 0,
    durableAlertApi: 'unknown'
  });
  const [selectedSignalId, setSelectedSignalId] = useState('');
  const [signalScope, setSignalScope] = useState<AlertSignalScope>('ALL');
  const [latencyThresholdSec, setLatencyThresholdSec] = useState<AlertLatencyThresholdSec>(10);
  const [signalVisibleLimit, setSignalVisibleLimit] = useState(12);
  const alerts = getAlertRows({ query, protocolFilter, sourceFilter });
  const [selectedAlertId, setSelectedAlertId] = useState(alerts[0]?.id ?? '');
  const [showAlertSamples, setShowAlertSamples] = useState(false);
  const alertSampleCopy = getSampleBoundaryCopy('alert-events', showAlertSamples);
  const baseSignals = useMemo(() => {
    const keyword = query.trim().toLowerCase();
    return signalState.signals.filter((signal) => {
      const protocolMatched = protocolFilter === 'ALL' || signal.protocol === protocolFilter || signal.type === '能力缺口';
      const queryMatched = !keyword || [signal.title, signal.detail, signal.vin, signal.plate, signal.source]
        .some((value) => String(value ?? '').toLowerCase().includes(keyword));
      return protocolMatched && queryMatched;
    });
  }, [protocolFilter, query, signalState.signals]);
  const thresholdedSignals = useMemo(
    () => baseSignals.filter((signal) => alertSignalMatchesThreshold(signal, latencyThresholdSec)),
    [baseSignals, latencyThresholdSec]
  );
  const signalScopeOptions = useMemo(
    () =>
      [
        { key: 'ALL' as const, label: '全部', value: thresholdedSignals.length },
        { key: 'P1' as const, label: 'P1', value: thresholdedSignals.filter((signal) => alertSignalMatchesScope(signal, 'P1')).length },
        { key: 'LATENCY' as const, label: '链路延迟', value: thresholdedSignals.filter((signal) => alertSignalMatchesScope(signal, 'LATENCY')).length },
        { key: 'MISSING' as const, label: '字段缺失', value: thresholdedSignals.filter((signal) => alertSignalMatchesScope(signal, 'MISSING')).length },
        { key: 'ALARM' as const, label: '协议告警位', value: thresholdedSignals.filter((signal) => alertSignalMatchesScope(signal, 'ALARM')).length },
        { key: 'CAPABILITY' as const, label: '能力缺口', value: thresholdedSignals.filter((signal) => alertSignalMatchesScope(signal, 'CAPABILITY')).length }
      ],
    [thresholdedSignals]
  );
  const signals = useMemo(
    () => thresholdedSignals.filter((signal) => alertSignalMatchesScope(signal, signalScope)),
    [signalScope, thresholdedSignals]
  );
  const displayedSignals = signals.slice(0, signalVisibleLimit);
  const signalSummary = useMemo(() => {
    const p1 = signals.filter((signal) => signal.level === 'P1').length;
    const vehicleCount = new Set(signals.map((signal) => signal.vin).filter(Boolean)).size;
    const types = new Set(signals.map((signal) => signal.type)).size;
    return [
      { label: '观测信号', value: String(signals.length), sub: '由实时/历史证据生成', tone: 'orange' },
      { label: 'P1 信号', value: String(p1), sub: '能力缺口或高风险观测', tone: 'blue' },
      { label: '涉及车辆', value: String(vehicleCount), sub: '按 VIN 去重', tone: 'green' },
      { label: '信号类型', value: String(types), sub: '非 durable 告警事件', tone: 'cyan' }
    ] satisfies Array<{ label: string; value: string; sub: string; tone: 'orange' | 'blue' | 'green' | 'cyan' }>;
  }, [signals]);
  const durableAlertUnavailable = signalState.durableAlertApi === 'unavailable';
  const alertBannerTone = signalState.status === 'ready' && durableAlertUnavailable ? 'partial' : signalState.status;
  const alertSignalTitle = signalState.status === 'loading'
    ? '正在读取观测信号'
    : signalState.status === 'partial'
      ? '观测信号部分可用，告警闭环未接入'
      : signalState.status === 'error'
        ? '真实观测信号读取失败'
        : signalState.status === 'empty'
          ? durableAlertUnavailable ? '真实观测信号为空，告警闭环未接入' : '真实观测信号为空'
          : durableAlertUnavailable ? '观测信号已接入，告警闭环未接入' : '真实观测信号已接入';
  const alertSignalBoundary = durableAlertUnavailable
    ? '当前只由 realtime / history 证据生成观测信号；确认、关闭、派单、通知需要 durable alert API。'
    : '观测信号和 durable alert API 均已可用。';

  useEffect(() => {
    if (alerts.length > 0 && !alerts.some((alert) => alert.id === selectedAlertId)) {
      setSelectedAlertId(alerts[0].id);
    }
  }, [alerts, selectedAlertId]);

  useEffect(() => {
    if (!canQueryRealAlerts) {
      return undefined;
    }
    setShowAlertSamples(false);
    let mounted = true;
    setSignalState((current) => ({ ...current, status: 'loading' }));
    loadPrototypeAlertSignals().then((next) => {
      if (mounted) {
        setSignalState(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [canQueryRealAlerts]);

  useEffect(() => {
    if (signals.length > 0 && !signals.some((signal) => signal.id === selectedSignalId)) {
      setSelectedSignalId(signals.find(hasAlertSignalCoordinate)?.id ?? signals[0].id);
    }
  }, [selectedSignalId, signals]);

  useEffect(() => {
    setSignalVisibleLimit(12);
  }, [latencyThresholdSec, protocolFilter, query, signalScope]);

  if (canQueryRealAlerts) {
    const selectedSignal = signals.find((signal) => signal.id === selectedSignalId) ?? signals[0];
    const selectedSignalHasCoordinate = hasAlertSignalCoordinate(selectedSignal);
    return (
      <section className="vpc-page-stack">
        <div className={`vpc-real-alert-banner vpc-real-alert-banner-${alertBannerTone}`}>
          <div>
            <strong>{alertSignalTitle}</strong>
            <span>{signalState.source}</span>
            <em>{alertSignalBoundary}</em>
            {signalState.error && <em>{signalState.error}</em>}
          </div>
          <Metric label="实时行" value={`${signalState.realtimeRows}`} />
          <Metric label="历史位置" value={`${signalState.historyRows}`} />
          <Metric label="闭环 API" value={durableAlertUnavailable ? '未接入' : '可用'} />
          <Metric label="刷新" value={signalState.fetchedAt ?? '--'} />
        </div>

        <div className="vpc-alert-summary">
          {signalSummary.map((item) => (
            <article className={`vpc-alert-summary-card vpc-alert-summary-${item.tone}`} key={item.label}>
              <span>{item.label}</span>
              <strong>{item.value}</strong>
              <em>{item.sub}</em>
            </article>
          ))}
        </div>

        <section className="vpc-panel vpc-alert-threshold-panel">
          <div className="vpc-panel-head">
            <strong>观测阈值</strong>
            <span>只影响当前页筛选，不写入告警规则</span>
          </div>
          <div className="vpc-alert-threshold-grid">
            <div>
              <span>链路延迟阈值</span>
              <div className="vpc-alert-threshold-options" aria-label="链路延迟观测阈值">
                {([10, 30, 60] as const).map((seconds) => (
                  <button
                    className={latencyThresholdSec === seconds ? 'vpc-alert-threshold-active' : ''}
                    key={seconds}
                    onClick={() => setLatencyThresholdSec(seconds)}
                    type="button"
                  >
                    {seconds}s
                  </button>
                ))}
              </div>
            </div>
            <article>
              <strong>P1 标准</strong>
              <span>链路延迟 &gt; 60s 或平台能力缺口</span>
            </article>
            <article>
              <strong>字段缺失</strong>
              <span>经纬度、总里程；32960 额外检查 SOC</span>
            </article>
            <article>
              <strong>协议告警位</strong>
              <span>alarm_flag &gt; 0，来自 realtime/history 位置证据</span>
            </article>
          </div>
        </section>

        <div className="vpc-alert-scope-filter" aria-label="观测信号范围">
          {signalScopeOptions.map((item) => (
            <button
              className={signalScope === item.key ? 'vpc-alert-scope-filter-active' : ''}
              key={item.key}
              onClick={() => setSignalScope(item.key)}
              type="button"
            >
              <span>{item.label}</span>
              <strong>{item.value}</strong>
            </button>
          ))}
        </div>

        <section className="vpc-alert-workbench">
          <div className="vpc-panel">
            <div className="vpc-panel-head">
              <strong>观测信号</strong>
              <span>realtime / locations</span>
            </div>
            {signals.length === 0 ? (
              <div className="vpc-empty">
                {signalState.status === 'loading' ? '正在生成观测信号...' : '当前筛选条件下暂无观测信号'}
              </div>
            ) : (
              <div className="vpc-alert-list">
                {displayedSignals.map((signal) => (
                  <button
                    className={`vpc-alert-row ${selectedSignal?.id === signal.id ? 'vpc-alert-row-active' : ''}`}
                    key={signal.id}
                    onClick={() => setSelectedSignalId(signal.id)}
                    type="button"
                  >
                    <span className="vpc-alert-row-level">
                      <Tag color={signal.level === 'P1' ? 'orange' : 'blue'}>{signal.level}</Tag>
                      <em>{signal.type}</em>
                    </span>
                    <strong>{signal.title}</strong>
                    <span>{signal.detail}</span>
                    <div>
                      <span>{signal.plate || '--'}</span>
                      <span>{signal.protocol ? protocolMeta[signal.protocol].short : 'BFF'}</span>
                      <span>{signal.source}</span>
                      <span>{signal.time}</span>
                    </div>
                  </button>
                ))}
              </div>
            )}
            {signals.length > 12 && (
              <div className="vpc-alert-row-load">
                <span>已显示 {displayedSignals.length} / {signals.length} 条观测信号，摘要和范围计数仍基于全部真实样本。</span>
                <div>
                  {signalVisibleLimit < signals.length && (
                    <Button onClick={() => setSignalVisibleLimit((value) => Math.min(value + 12, signals.length))} size="small" type="primary">
                      再显示 12 条
                    </Button>
                  )}
                  {signalVisibleLimit > 12 && (
                    <Button onClick={() => setSignalVisibleLimit(12)} size="small" theme="borderless">
                      收起
                    </Button>
                  )}
                </div>
              </div>
            )}
          </div>

          <aside className="vpc-panel vpc-alert-side">
            <div className="vpc-panel-head">
              <strong>告警边界</strong>
              <span>durable alert API 未接入</span>
            </div>
            <div className="vpc-plan-focus">
              <span>当前信号</span>
              <strong>{selectedSignal?.title ?? '无信号'}</strong>
              <em>{selectedSignal?.vin ? `${selectedSignal.plate || '--'} / ${selectedSignal.vin}` : '平台能力缺口或筛选为空'}</em>
            </div>
            <div className="vpc-signal-actions" aria-label="告警证据快捷入口">
              <Button disabled={!selectedSignal?.vin} onClick={() => selectedSignal?.vin && onOpenReplay(selectedSignal.vin)} type="primary">
                轨迹
              </Button>
              <Button disabled={!selectedSignal?.vin} onClick={() => selectedSignal?.vin && onOpenHistory(selectedSignal.vin, selectedSignal.protocol)} theme="borderless">
                RAW
              </Button>
            </div>
            <div className={`vpc-alert-location-evidence ${selectedSignalHasCoordinate ? '' : 'vpc-alert-location-empty'}`}>
              <div>
                <strong>定位证据</strong>
                <Tag color={selectedSignalHasCoordinate ? 'green' : 'grey'}>
                  {selectedSignalHasCoordinate ? '有坐标' : '无坐标'}
                </Tag>
              </div>
              {selectedSignalHasCoordinate && selectedSignal ? (
                <>
                  <span>{formatNumber(selectedSignal.latitude ?? 0, 6)}, {formatNumber(selectedSignal.longitude ?? 0, 6)}</span>
                  <em>
                    速度 {selectedSignal.speedKph == null ? '--' : `${formatNumber(selectedSignal.speedKph, 1)} km/h`}
                    {' / '}
                    总里程 {selectedSignal.totalMileageKm == null ? '--' : `${formatNumber(selectedSignal.totalMileageKm, 1)} km`}
                  </em>
                  <Button
                    aria-label="打开告警信号高德坐标"
                    data-amap-alert-marker-url={amapAlertSignalMarkerURL(selectedSignal)}
                    onClick={() => {
                      const url = amapAlertSignalMarkerURL(selectedSignal);
                      if (url) {
                        window.open(url, '_blank', 'noopener,noreferrer');
                      }
                    }}
                    size="small"
                    theme="borderless"
                  >
                    高德坐标
                  </Button>
                </>
              ) : (
                <span>平台能力缺口或非车辆信号没有经纬度，需从 RAW/轨迹证据继续定位。</span>
              )}
            </div>
            <div className="vpc-alert-boundary-list">
              <article>
                <strong>不自动通知</strong>
                <span>缺少 `/api/alert-events/notification-plan`，本页不提供派单、关闭、升级状态。</span>
              </article>
              <article>
                <strong>不持久化事件</strong>
                <span>当前信号由前端读取实时/历史证据生成，不代表后端 durable incident。</span>
              </article>
              <article>
                <strong>可回溯证据</strong>
                <span>需要确认时按 VIN + 时间窗回查 RAW 和 vehicle_locations。</span>
              </article>
            </div>
          </aside>
        </section>

        {selectedSignal && (
          <section className="vpc-panel">
            <div className="vpc-panel-head">
              <strong>信号证据</strong>
              <span>{selectedSignal.source}</span>
            </div>
            <div className="vpc-evidence-strip">
              {selectedSignal.evidence.map((item) => (
                <article key={item.label}>
                  <span>{item.label}</span>
                  <strong>{item.value}</strong>
                  <em>观测字段</em>
                </article>
              ))}
            </div>
            <div className="vpc-history-note">
              <span>/api/alert-events 当前不可用，因此这里只做观测信号，不做告警闭环。</span>
              <span>真实通知、确认、关闭和升级需要 durable alert 后端接口上线后再接入。</span>
            </div>
          </section>
        )}
      </section>
    );
  }

  const selectedAlert = alerts.find((alert) => alert.id === selectedAlertId) ?? alerts[0];
  const selectedVehicle = selectedAlert ? vehicles.find((item) => item.id === selectedAlert.vehicleId) : undefined;
  const selectedSource = selectedAlert ? dataSources.find((item) => item.id === selectedAlert.sourceId) : undefined;
  const evidenceItems = selectedAlert ? getAlertEvidenceItems(selectedAlert) : [];
  const fallbackSummary = [
    { label: '真实告警事件', value: '未接入', sub: '/api/alert-events 不可用', tone: 'orange' },
    { label: '观测信号', value: '待实时 API', sub: '依赖 realtime/history 证据', tone: 'blue' },
    { label: 'AMap 证据', value: isAMapConfigured() ? '已配置' : '未配置', sub: '只用于坐标定位跳转', tone: 'green' },
    { label: '样例验证', value: showAlertSamples ? '已展开' : '默认收起', sub: '仅验证交互蓝图', tone: 'cyan' }
  ] satisfies Array<{ label: string; value: string; sub: string; tone: 'orange' | 'blue' | 'green' | 'cyan' }>;
  const fallbackCapabilities = [
    {
      title: '断链观测',
      status: '可加工',
      detail: 'Redis 在线态、vehicle:last_seen 和历史位置可推导在线/离线/恢复时间。',
      evidence: 'Redis + TDengine'
    },
    {
      title: '字段质量',
      status: '可加工',
      detail: 'RAW parsed_fields 已有协议扁平字段，可检查经纬度、总里程、SOC、告警位缺失。',
      evidence: 'TDengine raw_frames'
    },
    {
      title: '持久告警',
      status: '待后端',
      detail: '缺少 durable alert 事件表/API，暂不展示确认、关闭、派单和通知链路。',
      evidence: 'MySQL alert_events'
    },
    {
      title: '地图定位',
      status: isAMapConfigured() ? '可跳转' : '待配置',
      detail: '有经纬度的信号可跳转高德坐标；无坐标信号只保留 RAW/轨迹证据入口。',
      evidence: 'AMap JS / URI'
    }
  ];

  return (
    <section className="vpc-page-stack">
      <div className="vpc-alert-summary">
        {fallbackSummary.map((item) => (
          <article className={`vpc-alert-summary-card vpc-alert-summary-${item.tone}`} key={item.label}>
            <span>{item.label}</span>
            <strong>{item.value}</strong>
            <em>{item.sub}</em>
          </article>
        ))}
      </div>

      <div className="vpc-real-alert-banner vpc-alert-blueprint-banner">
        <div>
          <strong>真实告警接口未接入，当前只展示能力蓝图</strong>
          <span>不会把本地样例事件当作生产告警；真实能力应从 realtime、raw_frames、vehicle_locations 和后续 alert_events 生成。</span>
        </div>
        <Metric label="实时证据" value="等待 API" />
        <Metric label="持久事件" value="未接入" />
        <Metric label="通知闭环" value="未接入" />
        <Metric label="样例验证" value={showAlertSamples ? '已展开' : '已收起'} />
      </div>

      <section className="vpc-alert-workbench">
        <div className="vpc-alert-fallback-main">
          <div className="vpc-panel">
            <div className="vpc-panel-head">
              <strong>可实现能力</strong>
              <span>按现有 Redis / TDengine / MySQL 边界拆分</span>
            </div>
            <div className="vpc-alert-capability-grid">
              {fallbackCapabilities.map((item) => (
                <article className="vpc-alert-capability-card" key={item.title}>
                  <div>
                    <strong>{item.title}</strong>
                    <Tag color={item.status.includes('待') ? 'orange' : 'green'}>{item.status}</Tag>
                  </div>
                  <span>{item.evidence}</span>
                  <p>{item.detail}</p>
                </article>
              ))}
            </div>
          </div>

          <div className="vpc-panel">
            <div className="vpc-panel-head">
              <strong>样例事件</strong>
              <span>{showAlertSamples ? '仅用于检查列表、筛选和证据布局' : '默认收起，不作为生产告警展示'}</span>
            </div>
            <div className="vpc-alert-sample-gate">
              <div>
                <strong>{alertSampleCopy.title}</strong>
                <span>{alertSampleCopy.detail}</span>
              </div>
              <Button onClick={() => setShowAlertSamples((value) => !value)} theme={showAlertSamples ? 'borderless' : 'solid'} type={showAlertSamples ? 'tertiary' : 'primary'}>
                {alertSampleCopy.actionLabel}
              </Button>
            </div>
            {!showAlertSamples ? (
              <div className="vpc-alert-sample-closed" aria-label="样例事件收起说明">
                <article>
                  <span>不展示</span>
                  <strong>样例告警列表</strong>
                  <em>避免把本地样例当作生产告警队列。</em>
                </article>
                <article>
                  <span>等待</span>
                  <strong>durable alert API</strong>
                  <em>上线后再展示确认、关闭、派单和通知闭环。</em>
                </article>
                <article>
                  <span>保留</span>
                  <strong>证据设计</strong>
                  <em>需要评审列表、轨迹和 RAW 入口时可手动展开。</em>
                </article>
              </div>
            ) : alerts.length === 0 ? (
              <div className="vpc-empty">当前筛选条件下暂无样例事件</div>
            ) : (
              <div className="vpc-alert-list">
                {alerts.map((alert) => {
                  const vehicle = vehicles.find((item) => item.id === alert.vehicleId);
                  const source = dataSources.find((item) => item.id === alert.sourceId);
                  return (
                    <button
                      className={`vpc-alert-row vpc-alert-row-mock ${selectedAlert?.id === alert.id ? 'vpc-alert-row-active' : ''}`}
                      key={alert.id}
                      onClick={() => setSelectedAlertId(alert.id)}
                      type="button"
                    >
                      <span className="vpc-alert-row-level">
                        <Tag color="grey">样例</Tag>
                        <Tag color={alert.level === 'P1' ? 'orange' : alert.level === 'P0' ? 'red' : 'blue'}>{alert.level}</Tag>
                        <em>{alert.type}</em>
                      </span>
                      <strong>{alert.title}</strong>
                      <span>{alert.detail}</span>
                      <div>
                        <span>{vehicle?.plate ?? '--'}</span>
                        <span>{source ? protocolMeta[source.protocol].short : '--'}</span>
                        <span>{getSourceName(alert.sourceId)}</span>
                        <span>{alert.time}</span>
                      </div>
                    </button>
                  );
                })}
              </div>
            )}
          </div>
        </div>

        <aside className="vpc-panel vpc-alert-side">
          <div className="vpc-panel-head">
            <strong>告警边界</strong>
            <span>durable alert API 未接入</span>
          </div>
          <div className="vpc-plan-focus">
            <span>{showAlertSamples ? '当前样例事件' : '样例事件状态'}</span>
            <strong>{showAlertSamples ? selectedAlert?.title ?? '无事件' : '默认收起'}</strong>
            <em>{showAlertSamples ? selectedVehicle ? `${selectedVehicle.plate} / ${selectedVehicle.vin}` : '等待筛选结果' : '真实告警接口未接入前只展示能力边界。'}</em>
          </div>
          <div className="vpc-signal-actions" aria-label="告警证据快捷入口">
            <Button disabled={!showAlertSamples || !selectedVehicle?.vin} onClick={() => selectedVehicle?.vin && onOpenReplay(selectedVehicle.vin)} type="primary">
              轨迹
            </Button>
            <Button disabled={!showAlertSamples || !selectedVehicle?.vin} onClick={() => selectedVehicle?.vin && onOpenHistory(selectedVehicle.vin, selectedSource?.protocol)} theme="borderless">
              RAW
            </Button>
          </div>
          <div className="vpc-alert-boundary-list">
            <article>
              <strong>不展示通知预案</strong>
              <span>`/api/alert-events/notification-plan` 未接入，原型不模拟企业微信、邮件、短信升级链路。</span>
            </article>
            <article>
              <strong>不做人工状态</strong>
              <span>确认、派单、关闭、升级需要 durable alert 后端接口上线后再接入。</span>
            </article>
            <article>
              <strong>只保留证据入口</strong>
              <span>当前可跳到轨迹和 RAW 记录，便于定位字段缺失、链路延迟或协议告警位。</span>
            </article>
          </div>
        </aside>
      </section>

      {selectedAlert && showAlertSamples && (
        <section className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>样例证据链</strong>
            <span>{selectedSource ? `${selectedSource.name} / ${selectedSource.endpoint}` : '按事件来源查询'}</span>
          </div>
          <div className="vpc-evidence-strip">
            <article>
              <span>车辆</span>
              <strong>{selectedVehicle?.plate ?? '--'}</strong>
              <em>{selectedVehicle?.vin ?? selectedAlert.vehicleId}</em>
            </article>
            <article>
              <span>来源</span>
              <strong>{selectedSource?.name ?? selectedAlert.sourceId}</strong>
              <em>{selectedSource?.platformAccount ?? '平台账号按来源台账维护'}</em>
            </article>
            <article>
              <span>事件时间</span>
              <strong>{selectedAlert.time}</strong>
              <em>东八区业务时间</em>
            </article>
          </div>
          <div className="vpc-evidence-grid">
            {evidenceItems.map((item) => (
              <article className={`vpc-evidence-card vpc-evidence-${item.status}`} key={item.title}>
                <div>
                  <strong>{item.title}</strong>
                  <Tag color={item.status === 'ready' ? 'green' : 'orange'}>{item.status === 'ready' ? '可查询' : '需关注'}</Tag>
                </div>
                <span>{item.source}</span>
                <p>{item.detail}</p>
              </article>
            ))}
          </div>
        </section>
      )}
    </section>
  );
}

type RealtimeStatsRow = {
  id: string;
  plate: string;
  vin: string;
  protocol: Protocol;
  sourceName: string;
  speedKph: number;
  totalMileageKm: number;
  lastSeen: string;
  online: boolean;
  fieldCount: number;
};

type SourceConsistencyStatsRow = {
  id: string;
  plate: string;
  vin: string;
  protocols: Protocol[];
  trustedProtocol: Protocol;
  trustedSourceName: string;
  sourceCount: number;
  onlineSourceCount: number;
  title: string;
  detail: string;
  severity: 'ok' | 'warning' | 'error';
  mileageDeltaKm: number;
  sourceTimeDeltaSeconds: number;
};

function statsRowState(row: RealtimeStatsRow) {
  if (!row.online) {
    return { label: '离线', color: 'grey' as const };
  }
  if (row.fieldCount === 0 || row.totalMileageKm <= 0) {
    return { label: '字段不足', color: 'orange' as const };
  }
  if (row.speedKph > 0) {
    return { label: '行驶', color: 'green' as const };
  }
  return { label: '在线', color: 'blue' as const };
}

function mileageDecisionStatusMeta(status: ReturnType<typeof getMileageSourceDecisions>[number]['status']) {
  if (status === 'ready') {
    return { label: '已选择', color: 'green' as const };
  }
  if (status === 'conflict') {
    return { label: '冲突', color: 'red' as const };
  }
  if (status === 'warning') {
    return { label: '关注', color: 'orange' as const };
  }
  return { label: '缺失', color: 'grey' as const };
}

function sourceLastSeenScore(source: VehicleSourceSnapshot) {
  if (source.lastSeenAt) {
    const normalized = source.lastSeenAt.includes('T') ? source.lastSeenAt : `${source.lastSeenAt.replace(' ', 'T')}+08:00`;
    const timestamp = new Date(normalized).getTime();
    if (Number.isFinite(timestamp)) {
      return Math.max(0, Math.round((Date.now() - timestamp) / 1000));
    }
  }
  if (!/[秒分钟小时]/.test(source.lastSeen)) {
    const normalized = source.lastSeen.includes('T') ? source.lastSeen : `${source.lastSeen.replace(' ', 'T')}+08:00`;
    const timestamp = new Date(normalized).getTime();
    if (Number.isFinite(timestamp)) {
      return Math.max(0, Math.round((Date.now() - timestamp) / 1000));
    }
  }
  const match = source.lastSeen.match(/(\d+)/);
  if (!match) {
    return Number.MAX_SAFE_INTEGER;
  }
  const value = Number(match[1]);
  if (source.lastSeen.includes('分钟')) {
    return value * 60;
  }
  if (source.lastSeen.includes('小时')) {
    return value * 3600;
  }
  return value;
}

function pickTrustedRealtimeSource(sources: VehicleRecord['sources']) {
  return [...sources].sort((left, right) => {
    const onlineDelta = Number(right.status === 'online') - Number(left.status === 'online');
    if (onlineDelta !== 0) return onlineDelta;
    const mileageDelta = Number((right.totalMileageKm ?? 0) > 0) - Number((left.totalMileageKm ?? 0) > 0);
    if (mileageDelta !== 0) return mileageDelta;
    const fieldDelta = right.fieldCount - left.fieldCount;
    if (fieldDelta !== 0) return fieldDelta;
    return sourceLastSeenScore(left) - sourceLastSeenScore(right);
  })[0];
}

function statsConsistencyConclusion(consistency: ReturnType<typeof getSourceConsistency>) {
  if (consistency.sourceCount <= 1) {
    return {
      severity: 'warning' as const,
      title: '单一来源',
      detail: '当前车辆没有足够来源做交叉校验。'
    };
  }
  if (consistency.onlineSourceCount <= 0) {
    return {
      severity: 'error' as const,
      title: '全部离线',
      detail: `${consistency.onlineSourceCount}/${consistency.sourceCount} 个来源在线，无法做实时交叉校验。`
    };
  }
  if (consistency.onlineSourceCount < consistency.sourceCount) {
    return {
      severity: 'warning' as const,
      title: '来源离线',
      detail: `${consistency.onlineSourceCount}/${consistency.sourceCount} 个来源在线，需关注离线来源。`
    };
  }
  if (consistency.mileageDeltaKm > 5) {
    return {
      severity: 'warning' as const,
      title: '里程差异偏大',
      detail: '多个来源的实时总里程差异超过 5 km，请核对解析单位和上报时间。'
    };
  }
  if (consistency.sourceTimeDeltaSeconds > 300) {
    return {
      severity: 'warning' as const,
      title: '来源时间差异',
      detail: '多个来源的最近上报时间差异超过 5 分钟，请关注链路延迟。'
    };
  }
  return {
    severity: 'ok' as const,
    title: '可交叉校验',
    detail: `${consistency.onlineSourceCount}/${consistency.sourceCount} 个来源在线，里程和时间差异在当前阈值内。`
  };
}

function getRealtimeStatsRows(records: VehicleRecord[], protocolFilter: ProtocolFilter): RealtimeStatsRow[] {
  return records.flatMap((vehicle) =>
    vehicle.sources
      .filter((source) => protocolFilter === 'ALL' || source.protocol === protocolFilter)
      .map((source) => ({
        id: `${vehicle.id}-${source.id}`,
        plate: vehicle.plate,
        vin: vehicle.vin,
        protocol: source.protocol,
        sourceName: source.sourceName,
        speedKph: source.speedKph ?? 0,
        totalMileageKm: source.totalMileageKm ?? 0,
        lastSeen: source.lastSeen,
        online: source.status === 'online',
        fieldCount: source.fieldCount
      }))
  );
}

function getSourceConsistencyStatsRows(records: VehicleRecord[], protocolFilter: ProtocolFilter): SourceConsistencyStatsRow[] {
  return records
    .map((vehicle) => {
      const scopedSources = vehicle.sources.filter((source) => protocolFilter === 'ALL' || source.protocol === protocolFilter);
      const trustedSource = pickTrustedRealtimeSource(scopedSources);
      if (!trustedSource) {
        return undefined;
      }
      const scopedVehicle: VehicleRecord = {
        ...vehicle,
        primarySourceId: trustedSource.id,
        sources: scopedSources
      };
      const consistency = getSourceConsistency(scopedVehicle);
      const conclusion = statsConsistencyConclusion(consistency);
      return {
        id: `${vehicle.id}-source-consistency`,
        plate: vehicle.plate,
        vin: vehicle.vin,
        protocols: Array.from(new Set(scopedSources.map((source) => source.protocol))),
        trustedProtocol: trustedSource.protocol,
        trustedSourceName: trustedSource.sourceName,
        sourceCount: consistency.sourceCount,
        onlineSourceCount: consistency.onlineSourceCount,
        title: conclusion.title,
        detail: conclusion.detail,
        severity: conclusion.severity,
        mileageDeltaKm: consistency.mileageDeltaKm,
        sourceTimeDeltaSeconds: consistency.sourceTimeDeltaSeconds
      };
    })
    .filter((row): row is SourceConsistencyStatsRow => Boolean(row))
    .sort((left, right) => {
      const severityRank = { error: 3, warning: 2, ok: 1 };
      const severityDelta = severityRank[right.severity] - severityRank[left.severity];
      if (severityDelta !== 0) return severityDelta;
      const sourceDelta = right.sourceCount - left.sourceCount;
      if (sourceDelta !== 0) return sourceDelta;
      return right.mileageDeltaKm - left.mileageDeltaKm;
    });
}

function getRealtimeProtocolStats(rows: RealtimeStatsRow[]) {
  return (['GB32960', 'JT808', 'YUTONG_MQTT'] as const)
    .map((protocol) => {
      const protocolRows = rows.filter((row) => row.protocol === protocol);
      const movingRows = protocolRows.filter((row) => row.speedKph > 0);
      const avgSpeedKph = protocolRows.reduce((sum, row) => sum + row.speedKph, 0) / Math.max(protocolRows.length, 1);
      return {
        protocol,
        label: protocolMeta[protocol].label,
        rowCount: protocolRows.length,
        onlineCount: protocolRows.filter((row) => row.online).length,
        movingCount: movingRows.length,
        mileageReadyCount: protocolRows.filter((row) => row.totalMileageKm > 0).length,
        avgSpeedKph,
        fieldCount: protocolRows.reduce((sum, row) => sum + row.fieldCount, 0)
      };
    })
    .filter((item) => item.rowCount > 0);
}

function StatsPage({
  protocolFilter,
  vehicles: statsVehicles,
  usingRealData,
  realData,
  onOpenHistory,
  onOpenReplay
}: {
  protocolFilter: ProtocolFilter;
  vehicles: VehicleRecord[];
  usingRealData: boolean;
  realData: PrototypeRealDataState;
  onOpenHistory: (vin: string, protocol?: Protocol) => void;
  onOpenReplay: (vin: string) => void;
}) {
  const [statsRowFilter, setStatsRowFilter] = useState<'ALL' | 'ATTENTION' | 'MOVING' | 'MILEAGE_READY'>('ALL');
  const [statsApiProbes, setStatsApiProbes] = useState<StatsApiProbeResult[]>(() => initialStatsApiProbes());
  const isStatsCompactViewport = useCompactViewport();
  const statsDefaultRealtimeLimit = isStatsCompactViewport ? statsCompactRealtimeLimit : statsDesktopRealtimeLimit;
  const statsDefaultConsistencyLimit = isStatsCompactViewport ? statsCompactConsistencyLimit : statsDesktopConsistencyLimit;
  const statsDefaultMileageDecisionLimit = isStatsCompactViewport ? 6 : 8;
  const [statsVisibleLimit, setStatsVisibleLimit] = useState(defaultStatsRealtimeLimit);
  const [statsConsistencyLimit, setStatsConsistencyLimit] = useState(defaultStatsConsistencyLimit);
  const [statsMileageDecisionLimit, setStatsMileageDecisionLimit] = useState(() => statsDefaultMileageDecisionLimit);

  useEffect(() => {
    let ignore = false;
    if (realData.status === 'disabled') {
      setStatsApiProbes(initialStatsApiProbes());
      return () => {
        ignore = true;
      };
    }
    setStatsApiProbes(initialStatsApiProbes());
    Promise.all(statsApiProbeDefinitions.map((definition) => probeStatsApi(definition))).then((results) => {
      if (!ignore) {
        setStatsApiProbes(results);
      }
    });
    return () => {
      ignore = true;
    };
  }, [realData.status]);

  useEffect(() => {
    setStatsVisibleLimit(statsDefaultRealtimeLimit);
    setStatsConsistencyLimit(statsDefaultConsistencyLimit);
    setStatsMileageDecisionLimit(statsDefaultMileageDecisionLimit);
  }, [protocolFilter, statsDefaultConsistencyLimit, statsDefaultMileageDecisionLimit, statsDefaultRealtimeLimit, statsRowFilter]);

  if (usingRealData) {
    const realtimeRows = getRealtimeStatsRows(statsVehicles, protocolFilter);
    const visibleRealtimeRows = realtimeRows.filter((row) => {
      if (statsRowFilter === 'ATTENTION') {
        return !row.online || row.fieldCount === 0 || row.totalMileageKm <= 0;
      }
      if (statsRowFilter === 'MOVING') {
        return row.speedKph > 0;
      }
      if (statsRowFilter === 'MILEAGE_READY') {
        return row.totalMileageKm > 0;
      }
      return true;
    });
    const displayedRealtimeRows = visibleRealtimeRows.slice(0, statsVisibleLimit);
    const byRealtimeProtocol = getRealtimeProtocolStats(realtimeRows);
    const consistencyRows = getSourceConsistencyStatsRows(statsVehicles, protocolFilter);
    const multiSourceConsistencyRows = consistencyRows.filter((row) => row.sourceCount > 1);
    const displayedConsistencyRows = multiSourceConsistencyRows.slice(0, statsConsistencyLimit);
    const consistencyAttentionCount = multiSourceConsistencyRows.filter((row) => row.severity !== 'ok').length;
    const selectedProtocolText = protocolFilter === 'ALL' ? '全部协议' : protocolMeta[protocolFilter].label;
    const selectedOnlineCount = realtimeRows.filter((row) => row.online).length;
    const selectedMovingCount = realtimeRows.filter((row) => row.speedKph > 0).length;
    const mileageReadyCount = realtimeRows.filter((row) => row.totalMileageKm > 0).length;
    const selectedFieldCount = realtimeRows.reduce((sum, row) => sum + row.fieldCount, 0);
    const attentionRows = realtimeRows.filter((row) => !row.online || row.fieldCount === 0 || row.totalMileageKm <= 0).length;
    const maxRealtimeFields = Math.max(...byRealtimeProtocol.map((item) => item.fieldCount), 1);
    const mileageDecisions = getMileageSourceDecisions(statsVehicles, protocolFilter);
    const displayedMileageDecisions = mileageDecisions.slice(0, statsMileageDecisionLimit);
    const mileageDecisionReadyCount = mileageDecisions.filter((decision) => decision.status === 'ready').length;
    const mileageDecisionIssueCount = mileageDecisions.filter((decision) => decision.status !== 'ready').length;
    const selectedDailyMileageKm = mileageDecisions.reduce((sum, decision) => sum + decision.selectedDailyMileageKm, 0);
    const dailyMileageReady = getStatsProbe(statsApiProbes, 'daily-mileage')?.status === 'ready';
    const statsInterpretationItems = getStatsInterpretationItems(statsVehicles, protocolFilter, dailyMileageReady);

    return (
      <section className="vpc-page-stack vpc-stats-page">
        <StatsProductionReadiness probes={statsApiProbes} realtimeRows={realtimeRows.length} usingRealData={usingRealData} />

        <div className="vpc-stat-readiness-grid" aria-label="统计能力状态">
          <article className="vpc-stat-readiness-card vpc-stat-readiness-ready">
            <span>当前可用</span>
            <strong>实时在线 / 速度 / 最新总里程</strong>
            <em>来源：locations 坐标 + snapshots 字段，适合做当前态监控和字段覆盖统计。</em>
          </article>
          <article className="vpc-stat-readiness-card vpc-stat-readiness-ready">
            <span>可回溯</span>
            <strong>轨迹 / RAW 字段证据</strong>
            <em>来源：TDengine vehicle_locations 与 raw_frames，可按 VIN 进入证据页。</em>
          </article>
          <article className="vpc-stat-readiness-card vpc-stat-readiness-pending">
            <span>未接入</span>
            <strong>日里程聚合 / 趋势统计</strong>
            <em>当前不展示假日里程；需等待 vehicle_daily_mileage 或统计 API 接入。</em>
          </article>
        </div>

        <StatsApiProbePanel probes={statsApiProbes} />

        <StatsInterpretationPanel dailyMileageReady={dailyMileageReady} items={statsInterpretationItems} />

        <div className="vpc-stat-summary">
          <article>
            <span>当前筛选</span>
            <strong>{selectedProtocolText}</strong>
            <em>来自真实位置与快照</em>
          </article>
          <article>
            <span>实时来源行</span>
            <strong>{realtimeRows.length}</strong>
            <em>{realData.total ?? realtimeRows.length} 条位置样本</em>
          </article>
          <article>
            <span>在线/行驶</span>
            <strong>{selectedOnlineCount}/{selectedMovingCount}</strong>
            <em>在线车辆 / 车速 &gt; 0</em>
          </article>
          <article>
            <span>总里程可用</span>
            <strong>{mileageReadyCount}/{realtimeRows.length}</strong>
            <em>多源不做总里程求和</em>
          </article>
          <article>
            <span>字段覆盖</span>
            <strong>{selectedFieldCount}</strong>
            <em>{attentionRows} 行需关注</em>
          </article>
          <article>
            <span>多源可校验</span>
            <strong>{multiSourceConsistencyRows.length}</strong>
            <em>{consistencyAttentionCount} 台需关注</em>
          </article>
        </div>

        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>可信里程口径</strong>
            <span>{selectedProtocolText} / 显示 {displayedMileageDecisions.length} / {mileageDecisions.length} 台</span>
          </div>
          <div className="vpc-mileage-decision-summary" aria-label="可信里程口径摘要">
            <article>
              <span>已选来源</span>
              <strong>{mileageDecisionReadyCount}/{mileageDecisions.length}</strong>
              <em>每辆车只选一路来源作为展示口径</em>
            </article>
            <article>
              <span>需处理</span>
              <strong>{mileageDecisionIssueCount}</strong>
              <em>缺失、非在线或多源冲突</em>
            </article>
            <article>
              <span>可信日里程</span>
              <strong>{formatNumber(selectedDailyMileageKm, 1)} km</strong>
              <em>按选中来源合计，不叠加多协议</em>
            </article>
          </div>
          {mileageDecisions.length === 0 ? (
            <div className="vpc-empty">当前筛选下暂无可判定的车辆里程来源。</div>
          ) : (
            <div className="vpc-mileage-decision-table">
              <div className="vpc-mileage-decision-row vpc-mileage-decision-head">
                <span>车辆</span>
                <span>选中来源</span>
                <span>今日 / 总里程</span>
                <span>候选来源</span>
                <span>口径状态</span>
                <span>证据</span>
              </div>
              {displayedMileageDecisions.map((decision) => {
                const statusMeta = mileageDecisionStatusMeta(decision.status);
                return (
                  <div className="vpc-mileage-decision-row" key={decision.id}>
                    <strong data-label="车辆">{decision.plate}<em>{decision.vin}</em></strong>
                    <span data-label="选中来源">
                      {decision.selectedProtocol ? (
                        <Tag color={protocolMeta[decision.selectedProtocol].color}>{protocolMeta[decision.selectedProtocol].short}</Tag>
                      ) : (
                        <Tag color="grey">无候选</Tag>
                      )}
                      <em>{decision.selectedSourceName}</em>
                    </span>
                    <span data-label="今日 / 总里程">
                      {formatNumber(decision.selectedDailyMileageKm, 1)} km
                      <em>{formatNumber(decision.selectedTotalMileageKm, 1)} km</em>
                    </span>
                    <span className="vpc-mileage-source-chips" data-label="候选来源">
                      {decision.sources.slice(0, 3).map((source) => (
                        <b className={source.protocol === decision.selectedProtocol && source.sourceName === decision.selectedSourceName ? 'vpc-mileage-source-selected' : ''} key={source.id}>
                          {protocolMeta[source.protocol].short}
                        </b>
                      ))}
                      {decision.sources.length > 3 && <b>+{decision.sources.length - 3}</b>}
                      <em>{decision.candidateCount}/{decision.sourceCount} 有里程</em>
                    </span>
                    <span data-label="口径状态">
                      <Tag color={statusMeta.color}>{statusMeta.label}</Tag>
                      <em>{decision.title}</em>
                    </span>
                    <span className="vpc-row-actions" data-label="证据">
                      <Button onClick={() => onOpenReplay(decision.vin)} size="small" theme="borderless">轨迹</Button>
                      <Button disabled={!decision.selectedProtocol} onClick={() => decision.selectedProtocol && onOpenHistory(decision.vin, decision.selectedProtocol)} size="small" theme="borderless">RAW</Button>
                    </span>
                  </div>
                );
              })}
            </div>
          )}
          {mileageDecisions.length > statsDefaultMileageDecisionLimit && (
            <div className="vpc-stat-row-load">
              <span>已显示 {displayedMileageDecisions.length} / {mileageDecisions.length} 台，可信日里程合计仍基于全部当前筛选车辆。</span>
              <div>
                {statsMileageDecisionLimit < mileageDecisions.length && (
                  <Button onClick={() => setStatsMileageDecisionLimit((value) => Math.min(value + statsDefaultMileageDecisionLimit, mileageDecisions.length))} type="primary">
                    再显示 {statsDefaultMileageDecisionLimit} 台
                  </Button>
                )}
                {statsMileageDecisionLimit > statsDefaultMileageDecisionLimit && (
                  <Button onClick={() => setStatsMileageDecisionLimit(statsDefaultMileageDecisionLimit)} theme="borderless">
                    收起
                  </Button>
                )}
              </div>
            </div>
          )}
        </div>

        <section className="vpc-page-grid">
          <div className="vpc-panel">
            <div className="vpc-panel-head">
              <strong>实时协议覆盖</strong>
              <span>/api/realtime/locations + snapshots</span>
            </div>
            <div className="vpc-stat-protocol-grid">
              {byRealtimeProtocol.map((item) => (
                <article className="vpc-stat-protocol-card" key={item.protocol}>
                  <div>
                    <Tag color={protocolMeta[item.protocol].color}>{protocolMeta[item.protocol].short}</Tag>
                    <strong>{item.label}</strong>
                  </div>
                  <strong>{item.onlineCount}/{item.rowCount}</strong>
                  <span>{item.movingCount} 台行驶 / 平均 {formatNumber(item.avgSpeedKph, 1)} km/h</span>
                  <em>字段 {item.fieldCount} / 总里程可用 {item.mileageReadyCount}/{item.rowCount}</em>
                  <div className="vpc-bar-track">
                    <span style={{ width: `${Math.min(100, (item.fieldCount / maxRealtimeFields) * 100)}%` }} />
                  </div>
                </article>
              ))}
            </div>
          </div>

          <div className="vpc-panel">
            <div className="vpc-panel-head">
              <strong>统计边界</strong>
              <Tag color="orange">真实 API 边界</Tag>
            </div>
            <div className="vpc-stats-boundary-strip">
              <article>
                <strong>已接入</strong>
                <span>/api/realtime/locations + snapshots</span>
                <em>在线、位置、速度、最新总里程、字段覆盖</em>
              </article>
              <article>
                <strong>未接入</strong>
                <span>vehicle_daily_mileage / /api/mileage/daily</span>
                <em>不展示演示口径的日里程、趋势和排名</em>
              </article>
              <article>
                <strong>可追溯</strong>
                <span>vehicle_locations / raw_frames</span>
                <em>明细行可跳转轨迹和 RAW</em>
              </article>
            </div>
          </div>
        </section>

        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>多源一致性观察</strong>
            <span>{selectedProtocolText} / 显示 {displayedConsistencyRows.length} / {multiSourceConsistencyRows.length} 台</span>
          </div>
          {multiSourceConsistencyRows.length === 0 ? (
            <div className="vpc-empty">当前筛选协议下暂无同一 VIN 的多来源实时数据，暂不能做跨来源一致性观察。</div>
          ) : (
            <div className="vpc-consistency-table">
              <div className="vpc-consistency-row vpc-consistency-head">
                <span>车辆</span>
                <span>来源覆盖</span>
                <span>可信候选</span>
                <span>里程差</span>
                <span>时间差</span>
                <span>结论</span>
                <span>证据</span>
              </div>
              {displayedConsistencyRows.map((row) => (
                <div className="vpc-consistency-row" key={row.id}>
                  <strong data-label="车辆">{row.plate}<em>{row.vin}</em></strong>
                  <span data-label="来源覆盖">
                    {row.onlineSourceCount}/{row.sourceCount}
                    <em>{row.protocols.map((protocol) => protocolMeta[protocol].short).join(' / ')}</em>
                  </span>
                  <span data-label="可信候选">
                    <Tag color={protocolMeta[row.trustedProtocol].color}>{protocolMeta[row.trustedProtocol].short}</Tag>
                    <em>{row.trustedSourceName}</em>
                  </span>
                  <span data-label="里程差">{formatNumber(row.mileageDeltaKm, 1)} km</span>
                  <span data-label="时间差">{formatNumber(row.sourceTimeDeltaSeconds, 0)} s</span>
                  <span data-label="结论">
                    <Tag color={row.severity === 'error' ? 'red' : row.severity === 'warning' ? 'orange' : 'green'}>
                      {row.title}
                    </Tag>
                    <em>{row.detail}</em>
                  </span>
                  <span className="vpc-row-actions" data-label="证据">
                    <Button onClick={() => onOpenReplay(row.vin)} size="small" theme="borderless">轨迹</Button>
                    <Button onClick={() => onOpenHistory(row.vin, row.trustedProtocol)} size="small" theme="borderless">RAW</Button>
                  </span>
                </div>
              ))}
            </div>
          )}
          {multiSourceConsistencyRows.length > statsDefaultConsistencyLimit && (
            <div className="vpc-stat-row-load">
              <span>已显示 {displayedConsistencyRows.length} / {multiSourceConsistencyRows.length} 台多源车辆，结论计数仍基于全部多源样本。</span>
              <div>
                {statsConsistencyLimit < multiSourceConsistencyRows.length && (
                  <Button onClick={() => setStatsConsistencyLimit((value) => Math.min(value + statsDefaultConsistencyLimit, multiSourceConsistencyRows.length))} type="primary">
                    再显示 {statsDefaultConsistencyLimit} 台
                  </Button>
                )}
                {statsConsistencyLimit > statsDefaultConsistencyLimit && (
                  <Button onClick={() => setStatsConsistencyLimit(statsDefaultConsistencyLimit)} theme="borderless">
                    收起
                  </Button>
                )}
              </div>
            </div>
          )}
        </div>

        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>实时来源明细</strong>
            <span>{selectedProtocolText} / 显示 {displayedRealtimeRows.length} / {visibleRealtimeRows.length} 行</span>
          </div>
          <div className="vpc-stat-row-filter" aria-label="统计明细范围">
            {[
              { key: 'ALL', label: '全部', value: realtimeRows.length },
              { key: 'ATTENTION', label: '需关注', value: attentionRows },
              { key: 'MOVING', label: '行驶中', value: selectedMovingCount },
              { key: 'MILEAGE_READY', label: '总里程可用', value: mileageReadyCount }
            ].map((item) => (
              <button
                className={statsRowFilter === item.key ? 'vpc-stat-row-filter-active' : ''}
                key={item.key}
                onClick={() => setStatsRowFilter(item.key as typeof statsRowFilter)}
                type="button"
              >
                <span>{item.label}</span>
                <strong>{item.value}</strong>
              </button>
            ))}
          </div>
          <div className="vpc-mileage-table">
            <div className="vpc-mileage-row vpc-mileage-head">
              <span>车辆</span>
              <span>协议</span>
              <span>来源</span>
              <span>车速</span>
              <span>最新总里程</span>
              <span>状态/字段</span>
              <span>证据</span>
            </div>
            {displayedRealtimeRows.map((row) => (
              <div className="vpc-mileage-row" key={row.id}>
                <strong data-label="车辆">{row.plate}<em>{row.vin}</em></strong>
                <span data-label="协议"><Tag color={protocolMeta[row.protocol].color}>{protocolMeta[row.protocol].short}</Tag></span>
                <span data-label="来源">{row.sourceName}</span>
                <span data-label="车速">{formatNumber(row.speedKph, 1)} km/h</span>
                <span data-label="最新总里程">{formatNumber(row.totalMileageKm, 1)} km</span>
                <span data-label="状态/字段">
                  <Tag color={statsRowState(row).color}>{statsRowState(row).label}</Tag>
                  <em className="vpc-row-muted">{row.fieldCount} fields / {row.lastSeen}</em>
                </span>
                <span className="vpc-row-actions" data-label="证据">
                  <Button onClick={() => onOpenReplay(row.vin)} size="small" theme="borderless">轨迹</Button>
                  <Button onClick={() => onOpenHistory(row.vin, row.protocol)} size="small" theme="borderless">RAW</Button>
                </span>
              </div>
            ))}
          </div>
          {visibleRealtimeRows.length > statsDefaultRealtimeLimit && (
            <div className="vpc-stat-row-load">
              <span>已显示 {displayedRealtimeRows.length} / {visibleRealtimeRows.length} 行，筛选计数仍基于全部真实来源行。</span>
              <div>
                {statsVisibleLimit < visibleRealtimeRows.length && (
                  <Button onClick={() => setStatsVisibleLimit((value) => Math.min(value + statsDefaultRealtimeLimit, visibleRealtimeRows.length))} type="primary">
                    再显示 {statsDefaultRealtimeLimit} 行
                  </Button>
                )}
                {statsVisibleLimit > statsDefaultRealtimeLimit && (
                  <Button onClick={() => setStatsVisibleLimit(statsDefaultRealtimeLimit)} theme="borderless">
                    收起
                  </Button>
                )}
              </div>
            </div>
          )}
          {visibleRealtimeRows.length === 0 && (
            <div className="vpc-empty">当前明细范围下暂无来源行</div>
          )}
        </div>
      </section>
    );
  }

  const selectedProtocolText = protocolFilter === 'ALL' ? '全部协议' : protocolMeta[protocolFilter].label;
  const dailyMileageReady = getStatsProbe(statsApiProbes, 'daily-mileage')?.status === 'ready';
  const statsInterpretationItems = getStatsInterpretationItems([], protocolFilter, dailyMileageReady);

  return (
    <section className="vpc-page-stack vpc-stats-page">
      <StatsProductionReadiness probes={statsApiProbes} realtimeRows={0} usingRealData={usingRealData} />

      <div className="vpc-stat-summary">
        <article>
          <span>当前筛选</span>
          <strong>{selectedProtocolText}</strong>
          <em>等待真实实时接口</em>
        </article>
        <article>
          <span>实时来源行</span>
          <strong>--</strong>
          <em>locations + snapshots 未连接</em>
        </article>
        <article>
          <span>日里程统计</span>
          <strong>未展示</strong>
          <em>不使用样例数据伪造结果</em>
        </article>
        <article>
          <span>证据入口</span>
          <strong>待连接</strong>
          <em>轨迹与 RAW 依赖真实 VIN</em>
        </article>
      </div>

      <StatsApiProbePanel probes={statsApiProbes} />

      <StatsInterpretationPanel dailyMileageReady={dailyMileageReady} items={statsInterpretationItems} />

      <section className="vpc-page-grid">
        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>统计能力蓝图</strong>
            <Tag color="orange">等待真实数据</Tag>
          </div>
          <div className="vpc-stat-readiness-grid">
            <article className="vpc-stat-readiness-card vpc-stat-readiness-ready">
              <span>实时统计</span>
              <strong>在线、速度、最新总里程</strong>
              <em>连接 locations + snapshots 后展示真实来源行和快照字段，不预置假车辆。</em>
            </article>
            <article className="vpc-stat-readiness-card vpc-stat-readiness-ready">
              <span>证据回溯</span>
              <strong>轨迹与 RAW</strong>
              <em>连接 TDengine 后按 VIN 回查 `vehicle_locations` 与 `raw_frames`。</em>
            </article>
            <article className="vpc-stat-readiness-card vpc-stat-readiness-pending">
              <span>待接入</span>
              <strong>日里程 / 趋势 / 排名</strong>
              <em>需要 `vehicle_daily_mileage` 或统计 API，未接入前不显示数值。</em>
            </article>
          </div>
        </div>

        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>统计口径</strong>
            <Tag color="grey">仅说明</Tag>
          </div>
          <div className="vpc-rule-list">
            <RuleLine title="协议独立统计" detail="正式统计应按 VIN、日期、协议、来源分别计算，不把 32960、808、MQTT 混成一条。" />
            <RuleLine title="日里程来源" detail="日里程必须来自统计服务或 MySQL 统计表，不能由前端样例生成。" />
            <RuleLine title="缺失回溯" detail="没有前一日最后总里程时，向前找最近有效总里程；完全没有则用当日第一条作为基准。" />
            <RuleLine title="质量事件" detail="断链、VIN 缺失、字段缺失、容量风险只能在 durable alert/quality API 上线后作为真值展示。" />
          </div>
        </div>
      </section>

      <div className="vpc-panel">
        <div className="vpc-panel-head">
          <strong>统计源头边界</strong>
          <span>Redis / MySQL / TDengine</span>
        </div>
        <div className="vpc-stats-boundary-strip vpc-stats-source-boundary">
          <article>
            <strong>Redis</strong>
            <span>realtime kv / online key</span>
            <em>适合实时在线、最新字段和当前态，不作为历史统计真值。</em>
          </article>
          <article>
            <strong>MySQL</strong>
            <span>snapshot / location / vehicle_daily_mileage</span>
            <em>适合最新快照、位置缓存和日里程结果；统计 API 未接入前不展示数值。</em>
          </article>
          <article>
            <strong>TDengine</strong>
            <span>raw_frames / vehicle_locations</span>
            <em>适合 RAW、轨迹和字段回溯；页面只在接口返回后展示明细。</em>
          </article>
        </div>
      </div>
    </section>
  );
}

function sourceRecordMatchesQuery(source: DataSourceRecord, query: string) {
  const keyword = query.trim().toLowerCase();
  if (!keyword) {
    return true;
  }
  return [
    source.name,
    source.endpoint,
    source.platformAccount,
    source.owner,
    protocolMeta[source.protocol].label,
    protocolMeta[source.protocol].short
  ].some((value) => String(value ?? '').toLowerCase().includes(keyword));
}

type SourceHealthFilter = SourceHealth | 'ALL';

function SourcesPage({
  canQueryRealSources,
  query,
  protocolFilter,
  onOpenRawHistory
}: {
  canQueryRealSources: boolean;
  query: string;
  protocolFilter: ProtocolFilter;
  onOpenRawHistory: (protocol: Protocol) => void;
}) {
  const [sourceMonitor, setSourceMonitor] = useState<PrototypeSourceMonitorState>({
    records: [],
    protocolEvidence: [],
    status: canQueryRealSources ? 'loading' : 'disabled',
    source: '/api/realtime/locations + /api/history/raw-frames/query',
    realtimeRows: 0,
    rawRows: 0,
    rawEndpointCount: 0,
    missingEndpointCount: 0
  });
  const [sourceHealthFilter, setSourceHealthFilter] = useState<SourceHealthFilter>('ALL');
  const [selectedSourceId, setSelectedSourceId] = useState('');
  const [showSourceSamples, setShowSourceSamples] = useState(false);
  const sourceSampleCopy = getSampleBoundaryCopy('source-monitor', showSourceSamples);
  const isSourceCompactViewport = useCompactViewport();
  const sourceDefaultVisibleLimit = isSourceCompactViewport ? sourceCompactVisibleLimit : sourceDesktopVisibleLimit;
  const [sourceVisibleLimit, setSourceVisibleLimit] = useState(defaultSourceVisibleLimit);
  const baseSourceRows = useMemo(() => {
    const rows = canQueryRealSources ? sourceMonitor.records : dataSources;
    return rows.filter((source) => {
      const protocolMatched = protocolFilter === 'ALL' || source.protocol === protocolFilter;
      return protocolMatched && sourceRecordMatchesQuery(source, query);
    });
  }, [canQueryRealSources, protocolFilter, query, sourceMonitor.records]);
  const sourceHealthOptions = useMemo(
    () =>
      [
        { key: 'ALL' as const, label: '全部', value: baseSourceRows.length },
        { key: 'healthy' as const, label: sourceHealthLabel.healthy, value: baseSourceRows.filter((source) => source.health === 'healthy').length },
        { key: 'warning' as const, label: sourceHealthLabel.warning, value: baseSourceRows.filter((source) => source.health === 'warning').length },
        { key: 'down' as const, label: sourceHealthLabel.down, value: baseSourceRows.filter((source) => source.health === 'down').length }
      ],
    [baseSourceRows]
  );
  const sourceRows = useMemo(() => {
    if (sourceHealthFilter === 'ALL') {
      return baseSourceRows;
    }
    return baseSourceRows.filter((source) => source.health === sourceHealthFilter);
  }, [baseSourceRows, sourceHealthFilter]);
  const sourceFallbackSummary = [
    { label: '真实来源证据', value: '待读取' },
    { label: 'RAW 端点', value: '待回查' },
    { label: '平台台账', value: '未接入' },
    { label: '样例验证', value: showSourceSamples ? '已展开' : '默认收起' }
  ];
  const displayedSourceRows = sourceRows.slice(0, sourceVisibleLimit);
  const selectedSource = sourceRows.find((source) => source.id === selectedSourceId) ?? sourceRows[0];
  const showSourceTable = canQueryRealSources || showSourceSamples;
  const sourceMonitorTitle = sourceMonitor.status === 'loading'
    ? '正在读取真实来源证据'
    : sourceMonitor.status === 'partial'
      ? '来源证据部分可用'
      : sourceMonitor.status === 'error'
        ? '真实来源证据读取失败'
        : sourceMonitor.status === 'empty'
          ? '真实来源证据为空'
          : '真实来源证据已接入';

  useEffect(() => {
    if (!canQueryRealSources) {
      return undefined;
    }
    let mounted = true;
    setSourceMonitor((current) => ({ ...current, status: 'loading' }));
    loadPrototypeSourceMonitor().then((next) => {
      if (mounted) {
        setSourceMonitor(next);
      }
    });
    return () => {
      mounted = false;
    };
  }, [canQueryRealSources]);

  useEffect(() => {
    if (sourceRows.length > 0 && !sourceRows.some((source) => source.id === selectedSourceId)) {
      setSelectedSourceId(sourceRows[0].id);
    }
  }, [selectedSourceId, sourceRows]);

  useEffect(() => {
    setSourceVisibleLimit(sourceDefaultVisibleLimit);
  }, [protocolFilter, query, sourceDefaultVisibleLimit, sourceHealthFilter]);

  useEffect(() => {
    if (canQueryRealSources) {
      setShowSourceSamples(false);
    }
  }, [canQueryRealSources]);

  return (
    <section className="vpc-page-stack">
      {canQueryRealSources && (
        <div className={`vpc-real-source-banner vpc-real-source-banner-${sourceMonitor.status}`}>
          <div>
            <strong>{sourceMonitorTitle}</strong>
            <span>{sourceMonitor.source}</span>
            {sourceMonitor.error && <em>{sourceMonitor.error}</em>}
          </div>
          <Metric label="实时行" value={`${sourceMonitor.realtimeRows}`} />
          <Metric label="RAW 样本" value={`${sourceMonitor.rawRows}`} />
          <Metric label="端点" value={`${sourceMonitor.rawEndpointCount}`} />
          <Metric label="缺端点" value={`${sourceMonitor.missingEndpointCount}`} />
        </div>
      )}

      {!canQueryRealSources && (
        <div className="vpc-real-source-banner vpc-source-blueprint-banner">
          <div>
            <strong>真实来源证据未读取，当前只展示来源监控蓝图</strong>
            <span>不会把本地样例来源当作生产 `vehicle_data_source` 台账；真实端点仍需由 realtime、raw_frames 和 ops API 共同证明。</span>
          </div>
          {sourceFallbackSummary.map((item) => (
            <Metric key={item.label} label={item.label} value={item.value} />
          ))}
        </div>
      )}

      {!canQueryRealSources && (
        <div className="vpc-source-evidence-layers vpc-source-blueprint-layers" aria-label="来源监控蓝图边界">
          <article>
            <span>实时来源</span>
            <strong>Redis / MySQL 投影</strong>
            <em>用于证明协议、VIN、在线态；当前失败态下不展示真实来源覆盖。</em>
          </article>
          <article>
            <span>端点证据</span>
            <strong>TDengine raw_frames</strong>
            <em>用于回查发送端 IP、端口、topic、平台名称；当前未读取真实样本。</em>
          </article>
          <article>
            <span>平台配置</span>
            <strong>vehicle_data_source / ops API</strong>
            <em>用于维护平台名称和审批状态；未接入前不模拟配置闭环。</em>
          </article>
        </div>
      )}

      {canQueryRealSources && (
        <div className="vpc-source-evidence-layers" aria-label="来源证据分层">
          <article>
            <span>实时覆盖</span>
            <strong>/api/realtime/locations</strong>
            <em>证明协议、VIN、在线态和实时位置；当前不返回 source_endpoint。</em>
          </article>
          <article>
            <span>RAW 端点</span>
            <strong>TDengine raw_frames</strong>
            <em>证明最近发送端、topic、平台名称和解析字段；可回查协议 RAW。</em>
          </article>
          <article>
            <span>平台台账</span>
            <strong>vehicle_data_source</strong>
            <em>当前原型不展示审批/配置状态，避免把样本端点当平台台账。</em>
          </article>
        </div>
      )}

      {canQueryRealSources && (
        <div className="vpc-panel">
          <div className="vpc-panel-head">
            <strong>协议来源证据矩阵</strong>
            <span>Redis/MySQL 实时投影 + TDengine RAW 样本</span>
          </div>
          <div className="vpc-source-matrix" aria-label="协议来源证据矩阵">
            {sourceMonitor.protocolEvidence.length > 0 ? sourceMonitor.protocolEvidence.map((item) => {
              const hasRawEndpoint = item.endpointCount > 0;
              const hasRealtime = item.realtimeRows > 0;
              const hasGap = item.missingEndpointRows > 0 || !hasRawEndpoint || !hasRealtime;
              return (
                <article className={`vpc-source-matrix-card ${hasGap ? 'vpc-source-matrix-gap' : ''}`} key={item.protocol}>
                  <div>
                    <Tag color={protocolMeta[item.protocol].color}>{protocolMeta[item.protocol].short}</Tag>
                    <strong>{protocolMeta[item.protocol].label}</strong>
                  </div>
                  <div className="vpc-source-matrix-metrics">
                    <Metric label="实时行" value={`${item.realtimeRows}`} />
                    <Metric label="RAW" value={`${item.rawRows}`} />
                    <Metric label="端点" value={`${item.endpointCount}`} />
                  </div>
                  <p>
                    健康 {item.healthyEndpoints} / 波动 {item.warningEndpoints} / 中断 {item.downEndpoints}
                    {item.missingEndpointRows > 0 ? `，${item.missingEndpointRows} 条 RAW 缺少 endpoint` : ''}
                  </p>
                  <em>{item.lastFrameAt ? `最近 ${item.lastFrameAt}` : '当前没有该协议真实样本'}</em>
                  <div className="vpc-source-matrix-actions">
                    <span>{hasRealtime && hasRawEndpoint ? '实时与 RAW 均有证据' : hasRawEndpoint ? '只有 RAW 端点证据' : hasRealtime ? '只有实时投影证据' : '暂无证据'}</span>
                    <Button onClick={() => onOpenRawHistory(item.protocol)} size="small" theme="borderless">
                      RAW
                    </Button>
                  </div>
                </article>
              );
            }) : (
              <div className="vpc-empty">当前没有可展示的协议来源证据</div>
            )}
          </div>
          <div className="vpc-history-note">
            <span>矩阵不代表平台台账完整，只表达当前实时投影与 RAW 样本是否能互相印证。</span>
            <span>正式的平台名称、来源 IP/端口、审批状态仍应由 `vehicle_data_source` 或 ops API 提供。</span>
          </div>
        </div>
      )}

      <div className="vpc-panel">
        <div className="vpc-panel-head">
          <strong>能力边界</strong>
          <span>只展示当前源头可支撑的功能</span>
        </div>
        <div className="vpc-capability-grid">
          {capabilityBoundaries.map((item) => (
            <article className="vpc-capability-card" key={item.capability}>
              <strong>{item.capability}</strong>
              <span>{item.source}</span>
              <em>{item.entry}</em>
              <p>{item.boundary}</p>
            </article>
          ))}
        </div>
      </div>

      <div className="vpc-panel">
        <div className="vpc-panel-head">
          <strong>{canQueryRealSources ? '来源端点证据' : '样例来源'}</strong>
          <span>
            {showSourceTable
              ? `显示 ${displayedSourceRows.length} / ${sourceRows.length} 个来源 / ${protocolFilter === 'ALL' ? '全部协议' : protocolMeta[protocolFilter].label}${canQueryRealSources ? '' : ' / 非生产台账'}`
              : '真实证据未返回，样例来源默认不展示'}
          </span>
        </div>
        {canQueryRealSources && (
          <div className="vpc-history-note">
            <span>端点来自 TDengine raw_frames 最近样本。</span>
            <span>在线覆盖来自 MySQL realtime locations；当前实时接口未返回 source_endpoint。</span>
            {sourceMonitor.status === 'partial' && sourceMonitor.error && <span>部分接口当前不可用：{sourceMonitor.error}</span>}
            <span>/api/ops/source-readiness 当前未接入，因此不展示平台配置审批态。</span>
          </div>
        )}
        {!canQueryRealSources && (
          <div className="vpc-history-note">
            <span>样例来源只用于验证筛选、健康状态和详情布局，默认收起，避免误认为生产 `vehicle_data_source` 台账。</span>
            <span>真实生产台账需要 `vehicle_data_source`、最近 RAW 端点和实时投影共同返回后再展示。</span>
          </div>
        )}
        {!canQueryRealSources && (
          <div className="vpc-source-sample-gate">
            <div>
              <strong>{sourceSampleCopy.title}</strong>
              <span>{sourceSampleCopy.detail}</span>
            </div>
            <Button onClick={() => setShowSourceSamples((value) => !value)} theme={showSourceSamples ? 'borderless' : 'solid'} type={showSourceSamples ? 'tertiary' : 'primary'}>
              {sourceSampleCopy.actionLabel}
            </Button>
          </div>
        )}
        {showSourceTable ? (
          <>
            <div className="vpc-source-health-filter" aria-label="来源健康范围">
              {sourceHealthOptions.map((item) => (
                <button
                  className={sourceHealthFilter === item.key ? 'vpc-source-health-filter-active' : ''}
                  key={item.key}
                  onClick={() => setSourceHealthFilter(item.key)}
                  type="button"
                >
                  <span>{item.label}</span>
                  <strong>{item.value}</strong>
                </button>
              ))}
            </div>
            <div className="vpc-source-table">
              {displayedSourceRows.map((sourceItem) => (
                <SourceRow
                  key={sourceItem.id}
                  onSelectSource={setSelectedSourceId}
                  onOpenRawHistory={onOpenRawHistory}
                  selected={selectedSource?.id === sourceItem.id}
                  source={sourceItem}
                  usingRealData={canQueryRealSources}
                />
              ))}
            </div>
            {sourceRows.length > sourceDefaultVisibleLimit && (
              <div className="vpc-source-row-load">
                <span>
                  已显示 {displayedSourceRows.length} / {sourceRows.length} 个来源端点，筛选和健康计数仍基于全部{canQueryRealSources ? '真实样本' : '样例数据'}。
                </span>
                <div>
                  {sourceVisibleLimit < sourceRows.length && (
                    <Button onClick={() => setSourceVisibleLimit((value) => Math.min(value + sourceDefaultVisibleLimit, sourceRows.length))} type="primary">
                      再显示 {sourceDefaultVisibleLimit} 个
                    </Button>
                  )}
                  {sourceVisibleLimit > sourceDefaultVisibleLimit && (
                    <Button onClick={() => setSourceVisibleLimit(sourceDefaultVisibleLimit)} theme="borderless">
                      收起
                    </Button>
                  )}
                </div>
              </div>
            )}
            {sourceRows.length === 0 && (
              <div className="vpc-empty">
                {sourceMonitor.status === 'loading' ? '正在读取来源端点证据...' : '当前没有可展示的真实来源证据'}
              </div>
            )}
          </>
        ) : (
          <div className="vpc-source-sample-closed" aria-label="样例来源收起说明">
            <article>
              <span>不展示</span>
              <strong>样例健康计数</strong>
              <em>避免把本地样例当作生产来源总览。</em>
            </article>
            <article>
              <span>等待</span>
              <strong>真实 RAW 端点</strong>
              <em>接入后才展示来源 IP、端口、topic 与平台名。</em>
            </article>
            <article>
              <span>保留</span>
              <strong>原型验证入口</strong>
              <em>需要评审表格交互时可手动展开样例来源。</em>
            </article>
          </div>
        )}
      </div>
      {selectedSource && showSourceTable && (
        <SourceDetailPanel
          onOpenRawHistory={onOpenRawHistory}
          source={selectedSource}
          usingRealData={canQueryRealSources}
        />
      )}
    </section>
  );
}

function isRawEndpointEvidence(source: DataSourceRecord) {
  return source.platformAccount === 'RAW endpoint';
}

function sourceEndpointTitle(source: DataSourceRecord) {
  const endpoint = source.endpoint.trim();
  if (!endpoint) {
    return source.name;
  }
  return endpoint;
}

function sourceEndpointSubtitle(source: DataSourceRecord, usingRealData?: boolean) {
  if (!usingRealData) {
    return source.name === source.endpoint ? source.platformAccount : `${source.platformAccount} / ${source.endpoint}`;
  }
  if (isRawEndpointEvidence(source)) {
    return `${protocolMeta[source.protocol].label} / RAW endpoint`;
  }
  return `${source.platformAccount} / ${source.name}`;
}

function sourceEvidenceType(source: DataSourceRecord, usingRealData?: boolean) {
  if (!usingRealData) {
    return source.platformAccount;
  }
  if (isRawEndpointEvidence(source)) {
    return 'TDengine RAW';
  }
  return source.platformAccount;
}

function sourceCoverageLabel(source: DataSourceRecord, usingRealData?: boolean) {
  if (!usingRealData) {
    return '车辆';
  }
  if (isRawEndpointEvidence(source)) {
    return 'VIN/样本帧';
  }
  return '在线/车辆';
}

function SourceRow({
  source,
  usingRealData,
  onOpenRawHistory,
  onSelectSource,
  selected
}: {
  source: DataSourceRecord;
  usingRealData?: boolean;
  onOpenRawHistory: (protocol: Protocol) => void;
  onSelectSource: (id: string) => void;
  selected: boolean;
}) {
  return (
    <div
      aria-current={selected ? 'true' : undefined}
      className={`vpc-source-row ${selected ? 'vpc-source-row-active' : ''}`}
      onClick={() => onSelectSource(source.id)}
      onKeyDown={(event) => {
        if (event.key !== 'Enter' && event.key !== ' ') {
          return;
        }
        event.preventDefault();
        onSelectSource(source.id);
      }}
      role="button"
      tabIndex={0}
    >
      <div>
        <Tag color={protocolMeta[source.protocol].color}>{protocolMeta[source.protocol].short}</Tag>
        <strong>{sourceEndpointTitle(source)}</strong>
        <span>{sourceEndpointSubtitle(source, usingRealData)}</span>
      </div>
      <div>
        <span>{usingRealData ? '证据类型' : '平台账号'}</span>
        <strong>{sourceEvidenceType(source, usingRealData)}</strong>
      </div>
      <div>
        <span>{sourceCoverageLabel(source, usingRealData)}</span>
        <strong>{source.onlineCount}/{source.vehicleCount}</strong>
      </div>
      <div>
        <span>P95</span>
        <strong>{source.latencyP95Ms} ms</strong>
      </div>
      <div>
        <span>{usingRealData ? '最近上报' : '健康'}</span>
        <strong className={`vpc-health vpc-health-${source.health}`}>{sourceHealthLabel[source.health]}</strong>
        {usingRealData && <em>{source.lastFrameAt}</em>}
      </div>
      <div className="vpc-source-actions">
        <span>证据</span>
        <Button
          onClick={(event) => {
            event.stopPropagation();
            onOpenRawHistory(source.protocol);
          }}
          size="small"
          theme="borderless"
        >
          RAW
        </Button>
      </div>
    </div>
  );
}

function sourceHealthReason(source: DataSourceRecord, usingRealData?: boolean) {
  if (!usingRealData) {
    return '来自样例来源的健康状态，不代表生产链路。';
  }
  if (source.health === 'healthy') {
    return '最近 RAW 样本在 90 秒内，当前观测为健康。';
  }
  if (source.health === 'warning') {
    return '最近 RAW 样本超过 90 秒但未超过 10 分钟，需关注链路波动。';
  }
  return '最近 RAW 样本超过 10 分钟，按当前观测判定为中断。';
}

function SourceDetailPanel({
  source,
  usingRealData,
  onOpenRawHistory
}: {
  source: DataSourceRecord;
  usingRealData?: boolean;
  onOpenRawHistory: (protocol: Protocol) => void;
}) {
  return (
    <section className="vpc-panel vpc-source-detail-panel">
      <div className="vpc-panel-head">
        <strong>{usingRealData ? '来源详情' : '样例来源详情'}</strong>
        <div className="vpc-source-detail-tags">
          {!usingRealData && <Tag color="grey">样例</Tag>}
          <Tag color={source.health === 'healthy' ? 'green' : source.health === 'warning' ? 'orange' : 'red'}>
            {sourceHealthLabel[source.health]}
          </Tag>
        </div>
      </div>
      <div className="vpc-source-detail-grid">
        <article>
          <span>协议 / 证据类型</span>
          <strong>{protocolMeta[source.protocol].label}</strong>
          <em>{sourceEvidenceType(source, usingRealData)}</em>
        </article>
        <article>
          <span>发送端</span>
          <strong>{sourceEndpointTitle(source)}</strong>
          <em>{usingRealData ? '来自最近 RAW 样本' : '来自样例来源配置'}</em>
        </article>
        <article>
          <span>{sourceCoverageLabel(source, usingRealData)}</span>
          <strong>{source.onlineCount}/{source.vehicleCount}</strong>
          <em>{source.owner}</em>
        </article>
        <article>
          <span>P95 延迟</span>
          <strong>{source.latencyP95Ms} ms</strong>
          <em>按当前样本计算</em>
        </article>
        <article>
          <span>最近上报</span>
          <strong>{source.lastFrameAt}</strong>
          <em>{sourceHealthReason(source, usingRealData)}</em>
        </article>
      </div>
      <div className="vpc-source-detail-actions" aria-label="来源排查入口">
        <Button onClick={() => onOpenRawHistory(source.protocol)} type="primary">
          查看 RAW 证据
        </Button>
        <span>当前后端未提供 endpoint 维度 RAW 查询，入口按协议过滤。</span>
      </div>
      {usingRealData && (
        <div className="vpc-source-detail-evidence">
          <article>
            <span>这条记录证明</span>
            <strong>最近 RAW 样本来自该端点</strong>
          </article>
          <article>
            <span>这条记录不证明</span>
            <strong>平台配置已完整入库</strong>
          </article>
          <article>
            <span>需要补强</span>
            <strong>endpoint 维度 RAW 查询与台账关联</strong>
          </article>
        </div>
      )}
      <div className="vpc-history-note">
        <span>健康阈值：90 秒内健康，90 秒到 10 分钟波动，超过 10 分钟中断。</span>
        <span>实时位置接口当前未返回 source_endpoint，因此在线覆盖和 RAW 端点是两层证据。</span>
      </div>
    </section>
  );
}

function InfoLine({ label, value }: { label: string; value: string }) {
  return (
    <div className="vpc-info-line">
      <span>{label}</span>
      <strong>{value}</strong>
    </div>
  );
}

function Metric({ label, value }: { label: string; value: string }) {
  return (
    <div>
      <span>{label}</span>
      <strong>{value}</strong>
    </div>
  );
}

function RuleLine({ title, detail }: { title: string; detail: string }) {
  return (
    <article className="vpc-rule-line">
      <strong>{title}</strong>
      <span>{detail}</span>
    </article>
  );
}
