import { Banner, Button, Card, Descriptions, Form, Select, Space, Table, Tabs, Tag, Toast, Typography } from '@douyinfe/semi-ui';
import { IconCopy, IconDownload, IconRefresh, IconSearch } from '@douyinfe/semi-icons';
import { useEffect, useMemo, useRef, useState } from 'react';
import { api } from '../api/client';
import type { QualityIssueRow, RealtimeLocationRow, VehicleDetail as VehicleDetailData, VehicleSourceStatus } from '../api/types';
import { PageHeader } from '../components/PageHeader';
import { SourceStatusTags } from '../components/SourceStatusTags';
import { StatusTag } from '../components/StatusTag';
import { VehicleMap, type VehicleMapPoint } from '../components/VehicleMap';
import { buildAppHash } from '../domain/appRoute';
import { buildCsv, downloadCsv, type CsvColumn } from '../domain/csvExport';
import { qualityIssueLabel } from '../domain/qualityIssue';
import { isLikelyVIN } from '../domain/vehicleLookup';
import { summarizeVehicleService } from '../domain/vehicleService';

type VehicleQuery = {
  keyword: string;
  protocol?: string;
};

const sourceCapabilities: Array<{ key: keyof Pick<VehicleSourceStatus, 'hasRealtime' | 'hasHistory' | 'hasRaw' | 'hasMileage'>; label: string }> = [
  { key: 'hasRealtime', label: '实时' },
  { key: 'hasHistory', label: '轨迹' },
  { key: 'hasRaw', label: '历史数据' },
  { key: 'hasMileage', label: '里程' }
];

const coverageStatusText: Record<string, string> = {
  online: '全部在线',
  partial: '部分在线',
  offline: '全部离线',
  no_data: '暂无来源'
};

function isFiniteNumber(value: unknown): value is number {
  return typeof value === 'number' && Number.isFinite(value);
}

function formatCompactNumber(value?: number, suffix = '') {
  if (!isFiniteNumber(value)) return '-';
  return `${value.toLocaleString(undefined, { maximumFractionDigits: 1 })}${suffix}`;
}

function formatLocation(row?: RealtimeLocationRow) {
  if (!row || !isFiniteNumber(row.longitude) || !isFiniteNumber(row.latitude)) return '-';
  return `${row.longitude}, ${row.latitude}`;
}

function parseTimeMs(value?: string) {
  if (!value) return undefined;
  const ms = Date.parse(value);
  return Number.isFinite(ms) ? ms : undefined;
}

function formatSeconds(value?: number) {
  if (!isFiniteNumber(value)) return '-';
  return `${Math.round(value)} 秒`;
}

function customerStatusTitle(title?: string) {
  if (!title) return '';
  return title === '来源不完整' ? '数据通道不完整' : title;
}

function customerScopeText(protocol?: string) {
  return protocol ? `单一数据通道：${protocol}` : '全部数据通道聚合';
}

function sourceServiceRole(source: VehicleSourceStatus, primaryProtocol?: string) {
  if (source.protocol === primaryProtocol) return { label: '主数据通道', color: 'blue' as const };
  if (source.online) return { label: '在线数据通道', color: 'green' as const };
  if (!source.lastSeen && !source.hasRealtime && !source.hasHistory && !source.hasRaw && !source.hasMileage) {
    return { label: '暂无来源', color: 'grey' as const };
  }
  return { label: '离线证据', color: 'grey' as const };
}

function sourceFusionRow(source: VehicleSourceStatus, realtime: RealtimeLocationRow | undefined, primaryProtocol?: string): SourceFusionRow {
  const hasLocation = !!realtime && isFiniteNumber(realtime.longitude) && isFiniteNumber(realtime.latitude) && realtime.longitude !== 0 && realtime.latitude !== 0;
  const hasMileage = isFiniteNumber(realtime?.totalMileageKm) || source.hasMileage;
  const contribution = [
    source.protocol === primaryProtocol ? '主实时通道' : '',
    source.online ? '在线心跳' : '',
    source.hasRealtime || realtime ? '实时字段' : '',
    hasLocation ? '定位数据' : '',
    source.hasHistory ? '轨迹回放' : '',
    source.hasRaw ? '历史数据' : '',
    hasMileage ? '里程口径' : ''
  ].filter(Boolean);
  return {
    source,
    realtime,
    role: sourceServiceRole(source, primaryProtocol),
    freshness: source.online ? `在线 / ${source.lastSeen || realtime?.lastSeen || '-'}` : source.lastSeen ? `离线 / ${source.lastSeen}` : '未接入',
    realtimeText: source.hasRealtime || realtime ? `速度 ${formatCompactNumber(realtime?.speedKmh, ' km/h')} / SOC ${formatCompactNumber(realtime?.socPercent, '%')}` : '无实时字段',
    locationText: hasLocation ? `${realtime?.longitude}, ${realtime?.latitude}` : '无有效坐标',
    rawText: source.hasRaw ? '可查历史数据' : '无历史数据',
    mileageText: hasMileage ? formatCompactNumber(realtime?.totalMileageKm, ' km') : '无里程数据',
    contribution: contribution.length > 0 ? contribution : ['待补来源']
  };
}

type VehicleServiceAction = {
  key: string;
  label: string;
  description: string;
  color: 'green' | 'orange' | 'red' | 'blue';
  onClick: () => void;
};

type SourceFusionRow = {
  source: VehicleSourceStatus;
  realtime?: RealtimeLocationRow;
  role: { label: string; color: 'green' | 'orange' | 'red' | 'blue' | 'grey' };
  freshness: string;
  realtimeText: string;
  locationText: string;
  rawText: string;
  mileageText: string;
  contribution: string[];
};

type VehicleReportRow = {
  section: string;
  item: string;
  value: string;
};

const vehicleReportColumns: CsvColumn<VehicleReportRow>[] = [
  { title: '模块', value: (row) => row.section },
  { title: '项目', value: (row) => row.item },
  { title: '值', value: (row) => row.value }
];

function reportText(value: unknown) {
  if (value == null || value === '') return '-';
  if (Array.isArray(value)) return value.length > 0 ? value.join('|') : '-';
  return String(value);
}

function vehicleReportFileName(vin: string, protocol?: string) {
  return `vehicle-service-${vin || 'unknown'}-${protocol || 'all-source'}.csv`;
}

function qualityIssuePriority(row: QualityIssueRow) {
  if (row.severity === 'error') return 0;
  if (row.severity === 'warning') return 1;
  return 2;
}

function issueEvidenceDate(value?: string) {
  const match = value?.match(/\d{4}-\d{2}-\d{2}/);
  return match?.[0];
}

function nextDate(value: string) {
  const [year, month, day] = value.split('-').map(Number);
  const date = new Date(Date.UTC(year, month - 1, day + 1));
  return date.toISOString().slice(0, 10);
}

function scopedRangeText(dateFrom?: string, dateTo?: string) {
  if (!dateFrom && !dateTo) return '未限定时间';
  return `${dateFrom || '未指定'} 至 ${dateTo || '未指定'}`;
}

function qualityIssueVehicleLabel(row: QualityIssueRow, fallbackVIN: string) {
  const vin = row.vin?.trim() || fallbackVIN;
  return [row.plate?.trim(), vin].filter(Boolean).join(' / ') || row.phone || row.sourceEndpoint || '-';
}

async function copyText(value: string, label: string) {
  try {
    await navigator.clipboard.writeText(value);
    Toast.success(`已复制${label}`);
  } catch {
    Toast.error(`复制${label}失败`);
  }
}

export function VehicleDetail({
  vin,
  protocol,
  platformRelease,
  onOpenRealtime,
  onOpenHistory,
  onOpenRaw,
  onOpenMileage,
  onOpenVehicles,
  onOpenQuality,
  onOpenHistoryEvidence,
  onOpenRawEvidence,
  onOpenMileageEvidence,
  onQueryChange
}: {
  vin: string;
  protocol?: string;
  platformRelease?: string;
  onOpenRealtime: (vin: string, protocol?: string) => void;
  onOpenHistory: (vin: string, protocol?: string) => void;
  onOpenRaw: (vin: string, protocol?: string) => void;
  onOpenMileage: (vin: string, protocol?: string) => void;
  onOpenVehicles?: (filters?: Record<string, string>) => void;
  onOpenQuality?: (filters?: Record<string, string>) => void;
  onOpenHistoryEvidence?: (filters?: Record<string, string>) => void;
  onOpenRawEvidence?: (filters?: Record<string, string>) => void;
  onOpenMileageEvidence?: (filters?: Record<string, string>) => void;
  onQueryChange?: (keyword: string, protocol?: string) => void;
}) {
  const [query, setQuery] = useState<VehicleQuery>({ keyword: vin, protocol });
  const [detail, setDetail] = useState<VehicleDetailData | null>(null);
  const [vehicleTimeWindow, setVehicleTimeWindow] = useState<Record<string, string>>({});
  const [loading, setLoading] = useState(false);
  const requestSeq = useRef(0);

  const load = (nextQuery = query) => {
    const keyword = nextQuery.keyword.trim();
    if (!keyword) {
      Toast.warning('请输入 VIN / 车牌 / 手机号');
      return;
    }
    setLoading(true);
    const params = new URLSearchParams({ keyword });
    if (nextQuery.protocol?.trim()) {
      params.set('protocol', nextQuery.protocol.trim());
    }
    const seq = requestSeq.current + 1;
    requestSeq.current = seq;
    api.vehicleDetail(params)
      .then((nextDetail) => {
        if (requestSeq.current === seq) {
          setDetail(nextDetail);
        }
      })
      .catch((error: Error) => {
        if (requestSeq.current === seq) {
          Toast.error(error.message);
        }
      })
      .finally(() => {
        if (requestSeq.current === seq) {
          setLoading(false);
        }
      });
  };

  useEffect(() => {
    const nextQuery = { keyword: vin, protocol };
    setQuery(nextQuery);
    load(nextQuery);
  }, [vin, protocol]);

  const identity = detail?.identity;
  const summary = detail?.realtimeSummary;
  const latest = detail?.realtime?.[0];
  const resolution = detail?.resolution;
  const overview = detail?.serviceOverview;
  const resolvedVIN = resolution?.vin || detail?.vin || summary?.vin || identity?.vin || latest?.vin || query.keyword;
  const hasResolvedVIN = resolution?.resolved ?? detail?.lookupResolved ?? isLikelyVIN(resolvedVIN);
  const displayVIN = hasResolvedVIN ? resolvedVIN : '-';
  const displayLookupKey = resolution?.lookupKey || detail?.lookupKey || query.keyword;
  const protocols = useMemo(() => resolution?.protocols?.length ? resolution.protocols : detail?.sources ?? [], [detail?.sources, resolution?.protocols]);
  const latestRaw = detail?.raw?.items?.[0];
  const qualityCount = detail?.quality?.total ?? 0;
  const priorityQualityIssue = useMemo(() => {
    const items = detail?.quality?.items ?? [];
    return [...items].sort((a, b) => {
      const severityDelta = qualityIssuePriority(a) - qualityIssuePriority(b);
      if (severityDelta !== 0) return severityDelta;
      return (Date.parse(b.lastSeen || '') || 0) - (Date.parse(a.lastSeen || '') || 0);
    })[0];
  }, [detail?.quality?.items]);
  const online = resolution?.online || summary?.online || identity?.online || false;
  const lastSeen = resolution?.lastSeen || summary?.lastSeen || latest?.lastSeen || '-';
  const serviceStatus = detail?.serviceStatus;
  const realtimeRows = detail?.realtime ?? [];
  const locatedRealtimeRows = useMemo(() => realtimeRows.filter((row) => (
    isFiniteNumber(row.longitude) &&
    isFiniteNumber(row.latitude) &&
    row.longitude !== 0 &&
    row.latitude !== 0
  )), [realtimeRows]);
  const sourceOnlineByProtocol = useMemo(() => new Map((detail?.sourceStatus ?? []).map((source) => [source.protocol, source.online])), [detail?.sourceStatus]);
  const vehicleMapPoints = useMemo<VehicleMapPoint[]>(() => locatedRealtimeRows.map((row) => ({
    id: `${row.protocol || 'source'}-${row.lastSeen || row.vin}`,
    label: row.protocol || row.vin,
    longitude: row.longitude,
    latitude: row.latitude,
    online: sourceOnlineByProtocol.get(row.protocol) ?? true,
    title: `${row.protocol || '来源'} / ${formatCompactNumber(row.speedKmh, ' km/h')}`
  })), [locatedRealtimeRows, sourceOnlineByProtocol]);
  const latestRealtimeByProtocol = useMemo(() => {
    const next = new Map<string, RealtimeLocationRow>();
    for (const row of realtimeRows) {
      if (!row.protocol || next.has(row.protocol)) continue;
      next.set(row.protocol, row);
    }
    return next;
  }, [realtimeRows]);
  const sourceFusionRows = useMemo(() => (
    (detail?.sourceStatus ?? []).map((source) => sourceFusionRow(source, latestRealtimeByProtocol.get(source.protocol), summary?.primaryProtocol))
  ), [detail?.sourceStatus, latestRealtimeByProtocol, summary?.primaryProtocol]);
  const realtimeSources = new Set(realtimeRows.map((row) => row.protocol).filter(Boolean));
  const sourceStatusRows = detail?.sourceStatus ?? [];
  const sourceCount = Math.max(sourceStatusRows.length, realtimeSources.size, summary?.sourceCount ?? 0, protocols.length);
  const onlineSourceCount = sourceStatusRows.length
    ? sourceStatusRows.filter((source) => source.online).length
    : summary?.onlineSourceCount ?? 0;
  const locatedSourceCount = realtimeRows.filter((row) => isFiniteNumber(row.longitude) && isFiniteNumber(row.latitude)).length;
  const mileageValues = realtimeRows.map((row) => row.totalMileageKm).filter(isFiniteNumber);
  const mileageDelta = mileageValues.length > 1 ? Math.max(...mileageValues) - Math.min(...mileageValues) : undefined;
  const timeValues = [
    ...realtimeRows.map((row) => parseTimeMs(row.lastSeen)),
    ...(detail?.sourceStatus ?? []).map((source) => parseTimeMs(source.lastSeen))
  ].filter(isFiniteNumber);
  const sourceTimeDeltaSeconds = timeValues.length > 1 ? (Math.max(...timeValues) - Math.min(...timeValues)) / 1000 : undefined;
  const consistency = detail?.sourceConsistency;
  const consistencySourceCount = consistency?.sourceCount ?? sourceCount;
  const consistencyOnlineSourceCount = consistency?.onlineSourceCount ?? onlineSourceCount;
  const consistencyLocatedSourceCount = consistency?.locatedSourceCount ?? locatedSourceCount;
  const consistencyMileageDelta = consistency?.mileageDeltaKm ?? mileageDelta;
  const consistencyTimeDeltaSeconds = consistency?.sourceTimeDeltaSeconds ?? sourceTimeDeltaSeconds;
  const consistencyTitle = consistency?.title ?? '-';
  const consistencyDetail = consistency?.detail ?? '-';
  const missingProtocols = consistency?.missingProtocols ?? [];
  const missingProtocolText = missingProtocols.length > 0 ? (
    <Space spacing={4}>
      {missingProtocols.map((item) => (
        <Button
          key={item}
          size="small"
          theme="light"
          type="warning"
          onClick={() => onOpenVehicles?.({ serviceStatus: 'degraded', missingProtocol: item })}
        >
          查看缺 {item} 车辆
        </Button>
      ))}
    </Space>
  ) : '-';
  const evidenceSourceCount = overview?.sourceCount ?? consistencySourceCount;
  const evidenceOnlineSourceCount = overview?.onlineSourceCount ?? consistencyOnlineSourceCount;
  const evidenceLocatedSourceCount = consistencyLocatedSourceCount;
  const evidenceMileageDelta = consistencyMileageDelta;
  const evidenceTimeDeltaSeconds = consistencyTimeDeltaSeconds;
  const activeProtocol = query.protocol?.trim() ?? '';
  const scopeText = customerScopeText(activeProtocol);
  const archivePlate = resolution?.plate || summary?.plate || identity?.plate || latest?.plate || '';
  const archivePhone = resolution?.phone || summary?.phone || identity?.phone || '';
  const archiveOEM = resolution?.oem || summary?.oem || identity?.oem || '';
  const archiveFields = [hasResolvedVIN && displayVIN !== '-', archivePlate, archivePhone, archiveOEM];
  const archiveCompleteness = `${archiveFields.filter(Boolean).length}/${archiveFields.length}`;
  const archiveMissingLabels = [
    { value: hasResolvedVIN && displayVIN !== '-' ? displayVIN : '', label: '缺VIN' },
    { value: archivePlate, label: '缺车牌' },
    { value: archivePhone, label: '缺手机号' },
    { value: archiveOEM, label: '缺OEM' }
  ]
    .filter((item) => !String(item.value ?? '').trim())
    .map((item) => item.label);
  const archiveSourceCount = Math.max(protocols.length, sourceCount);
  const formKey = `${query.keyword}-${query.protocol ?? ''}`;
  const switchSource = (nextProtocol = '') => {
    const nextQuery = { keyword: resolvedVIN || query.keyword, protocol: nextProtocol };
    setQuery(nextQuery);
    onQueryChange?.(nextQuery.keyword, nextQuery.protocol);
    load(nextQuery);
  };
  const serviceConclusion = useMemo(() => summarizeVehicleService({
    resolved: hasResolvedVIN,
    sourceCount,
    onlineSourceCount,
    qualityIssueCount: qualityCount,
    missingProtocols,
    mileageDeltaKm: consistencyMileageDelta
  }), [consistencyMileageDelta, hasResolvedVIN, missingProtocols, onlineSourceCount, qualityCount, sourceCount]);
  const qualityFiltersForCurrentVehicle = () => ({
    keyword: resolvedVIN,
    ...(activeProtocol ? { protocol: activeProtocol } : {})
  });
  const qualityIssueEvidenceFilters = (row: QualityIssueRow, tab?: 'raw') => {
    const dateFrom = issueEvidenceDate(row.lastSeen);
    return {
      keyword: row.vin?.trim() || resolvedVIN,
      protocol: row.protocol || activeProtocol,
      ...(dateFrom ? { dateFrom, dateTo: nextDate(dateFrom) } : {}),
      ...(tab === 'raw' ? { tab: 'raw', includeFields: 'true' } : {})
    };
  };
  const openQualityIssueHistoryEvidence = (row: QualityIssueRow) => {
    const filters = qualityIssueEvidenceFilters(row);
    if (onOpenHistoryEvidence) {
      onOpenHistoryEvidence(filters);
      return;
    }
    onOpenHistory(filters.keyword, filters.protocol);
  };
  const openQualityIssueRawEvidence = (row: QualityIssueRow) => {
    const filters = qualityIssueEvidenceFilters(row, 'raw');
    if (onOpenRawEvidence) {
      onOpenRawEvidence(filters);
      return;
    }
    onOpenRaw(filters.keyword, filters.protocol);
  };
  const vehicleServiceURL = (hash: string) => `${window.location.origin}${window.location.pathname}${hash}`;
  const vehicleServiceHash = (page: 'detail' | 'realtime' | 'history' | 'history-query' | 'mileage', filters?: Record<string, string>) => buildAppHash({
    page,
    keyword: resolvedVIN,
    protocol: activeProtocol,
    filters
  });
  const vehicleTimeWindowScope = () => ({
    keyword: resolvedVIN,
    ...(activeProtocol ? { protocol: activeProtocol } : {}),
    ...(vehicleTimeWindow.dateFrom?.trim() ? { dateFrom: vehicleTimeWindow.dateFrom.trim() } : {}),
    ...(vehicleTimeWindow.dateTo?.trim() ? { dateTo: vehicleTimeWindow.dateTo.trim() } : {})
  });
  const vehicleTimeWindowText = scopedRangeText(vehicleTimeWindow.dateFrom?.trim(), vehicleTimeWindow.dateTo?.trim());
  const openVehicleWindowHistory = () => {
    const filters = vehicleTimeWindowScope();
    if (onOpenHistoryEvidence) {
      onOpenHistoryEvidence(filters);
      return;
    }
    onOpenHistory(filters.keyword, filters.protocol);
  };
  const openVehicleWindowMileage = () => {
    const filters = vehicleTimeWindowScope();
    if (onOpenMileageEvidence) {
      onOpenMileageEvidence(filters);
      return;
    }
    onOpenMileage(filters.keyword, filters.protocol);
  };
  const openVehicleWindowRaw = () => {
    const filters = { ...vehicleTimeWindowScope(), tab: 'raw', includeFields: 'true' };
    if (onOpenRawEvidence) {
      onOpenRawEvidence(filters);
      return;
    }
    onOpenRaw(filters.keyword, filters.protocol);
  };
  const openVehicleWindowAlerts = () => {
    const filters = vehicleTimeWindowScope();
    onOpenQuality?.(filters);
  };
  const copyVehicleTimeWindowPackage = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的单车时间窗交付包');
      return;
    }
    const filters = vehicleTimeWindowScope();
    const rawFilters = { ...filters, tab: 'raw', includeFields: 'true' };
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【单车时间窗交付包】',
      `车辆：${vehicleName}`,
      `时间范围：${vehicleTimeWindowText}`,
      `数据通道：${activeProtocol || '全部数据通道'}`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `最新上报：${lastSeen}`,
      `轨迹证据：${overview?.historyCount ?? detail.history.total ?? 0} 条`,
      `历史数据：${overview?.rawCount ?? detail.raw.total ?? 0} 条`,
      `里程统计：${overview?.mileageCount ?? detail.mileage.total ?? 0} 条`,
      `告警事件：${qualityCount.toLocaleString()} 项`,
      `轨迹回放：${vehicleServiceURL(buildAppHash({ page: 'history', keyword: filters.keyword, protocol: filters.protocol, filters }))}`,
      `里程统计：${vehicleServiceURL(buildAppHash({ page: 'mileage', keyword: filters.keyword, protocol: filters.protocol, filters }))}`,
      `历史导出：${vehicleServiceURL(buildAppHash({ page: 'history-query', keyword: rawFilters.keyword, protocol: rawFilters.protocol, filters: rawFilters }))}`,
      `告警通知：${vehicleServiceURL(buildAppHash({ page: 'alert-events', keyword: filters.keyword, protocol: filters.protocol, filters }))}`
    ];
    copyText(lines.join('\n'), '单车时间窗交付包');
  };
  const copyVehicleServiceURL = () => copyText(vehicleServiceURL(window.location.hash), '服务链接');
  const copyVehicleDiagnosticSummary = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的诊断摘要');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【车辆服务诊断摘要】',
      ...(platformRelease?.trim() ? [`运行版本：${platformRelease.trim()}`] : []),
      `车辆：${vehicleName}`,
      `查询关键词：${reportText(displayLookupKey)}`,
      `当前范围：${scopeText}`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `服务说明：${serviceStatus?.detail ?? '-'}`,
      `服务判断：${serviceConclusion.status}`,
      `主要风险：${serviceConclusion.risk}`,
      `下一步：${serviceConclusion.nextStep}`,
      `数据通道：${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '-'}`,
      `定位数据：${evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个通道有位置` : '暂无位置'}`,
      `里程差异：${formatCompactNumber(evidenceMileageDelta, ' km')}`,
      `时间差异：${formatSeconds(evidenceTimeDeltaSeconds)}`,
      `服务数据：实时 ${overview?.realtimeCount ?? detail.realtime.length} / 轨迹 ${overview?.historyCount ?? detail.history.total ?? 0} / 历史数据 ${overview?.rawCount ?? detail.raw.total ?? 0} / 里程 ${overview?.mileageCount ?? detail.mileage.total ?? 0} / 告警 ${overview?.qualityIssueCount ?? qualityCount}`,
      `一致性：${customerStatusTitle(consistencyTitle) || consistencyTitle}`,
      `一致性说明：${consistencyDetail}`,
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`,
      `实时：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`
    ];
    copyText(lines.join('\n'), '诊断摘要');
  };
  const copySourceFusionReport = () => {
    if (!detail || sourceFusionRows.length === 0) {
      Toast.warning('当前没有可复制的数据通道归并矩阵');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【单车数据通道归并矩阵】',
      `车辆：${vehicleName}`,
      `当前范围：${scopeText}`,
      `主数据通道：${overview?.primaryProtocol || summary?.primaryProtocol || '-'}`,
      `通道覆盖：${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '-'}`,
      `一致性：${customerStatusTitle(consistencyTitle) || consistencyTitle}`,
      '',
      ...sourceFusionRows.map((row, index) => [
        `${index + 1}. ${row.source.protocol} / ${row.role.label}`,
        `   新鲜度：${row.freshness}`,
        `   贡献：${row.contribution.join('、')}`,
        `   实时：${row.realtimeText}`,
        `   定位：${row.locationText}`,
        `   历史数据：${row.rawText}`,
        `   里程：${row.mileageText}`
      ].join('\n')),
      '',
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`,
      `实时监控：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹回放：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`
    ];
    copyText(lines.join('\n'), '数据通道归并矩阵');
  };
  const qualityIssueAction = (count: number) => {
    if (count <= 0) {
      return <Tag color="green">无</Tag>;
    }
    return (
      <Button
        size="small"
        theme="light"
        type="warning"
        onClick={() => onOpenQuality?.(qualityFiltersForCurrentVehicle())}
      >
        查看质量问题 {count} 项
      </Button>
    );
  };
  const serviceActions = useMemo<VehicleServiceAction[]>(() => {
    const actions: VehicleServiceAction[] = [];
    if (!hasResolvedVIN) {
      actions.push({
        key: 'identity',
        label: '维护身份绑定',
        description: `关键词 ${displayLookupKey} 暂未解析到 VIN，先补齐绑定后再看跨证据服务。`,
        color: 'orange',
        onClick: () => onOpenVehicles?.({ bindingStatus: 'unbound' })
      });
    }
    for (const item of missingProtocols) {
      actions.push({
        key: `missing-${item}`,
        label: `补齐 ${item} 证据`,
        description: `${item} 当前没有形成有效数据通道，会影响这辆车的统一服务可信度。`,
        color: 'orange',
        onClick: () => onOpenVehicles?.({ serviceStatus: 'degraded', missingProtocol: item })
      });
    }
    for (const source of detail?.sourceStatus ?? []) {
      if (source.online) continue;
      actions.push({
        key: `offline-${source.protocol}`,
        label: `排查 ${source.protocol} 离线`,
        description: `${source.protocol} 最后上报时间：${source.lastSeen || '无上报'}。`,
        color: 'orange',
        onClick: () => switchSource(source.protocol)
      });
    }
    if (qualityCount > 0) {
      actions.push({
        key: 'quality',
        label: `处理质量问题 ${qualityCount} 项`,
        description: '质量问题会影响车辆服务的定位、里程和实时状态可信度。',
        color: 'orange',
        onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
      });
    }
    if (actions.length === 0 && hasResolvedVIN) {
      actions.push({
        key: 'healthy',
        label: '查看实时服务',
        description: '当前没有明确处置项，可直接查看该车统一实时状态。',
        color: 'green',
        onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
      });
    }
    return actions;
  }, [activeProtocol, detail?.sourceStatus, displayLookupKey, hasResolvedVIN, missingProtocols, onOpenQuality, onOpenRealtime, onOpenVehicles, qualityCount, resolvedVIN]);
  const serviceAssetItems = [
    {
      label: '实时',
      value: formatCompactNumber(overview?.realtimeCount ?? detail?.realtime?.length ?? 0),
      detail: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '暂无来源',
      color: evidenceOnlineSourceCount > 0 ? 'green' as const : 'orange' as const
    },
    {
      label: '轨迹',
      value: formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0),
      detail: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个位置证据` : '暂无位置',
      color: (overview?.historyCount ?? detail?.history?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const
    },
    {
      label: '历史数据',
      value: formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0),
      detail: latestRaw?.frameType || '解析字段',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const
    },
    {
      label: '里程',
      value: formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0),
      detail: formatCompactNumber(evidenceMileageDelta, ' km 差异'),
      color: isFiniteNumber(evidenceMileageDelta) && Math.abs(evidenceMileageDelta) > 1 ? 'orange' as const : 'green' as const
    },
    {
      label: '告警',
      value: qualityCount.toLocaleString(),
      detail: priorityQualityIssue ? qualityIssueLabel(priorityQualityIssue.issueType) : '暂无告警',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const
    }
  ];
  const unifiedVehicleServiceItems = [
    {
      label: '车辆身份',
      value: hasResolvedVIN ? displayVIN : displayLookupKey,
      detail: archivePlate || archivePhone || archiveOEM || '待补身份',
      color: hasResolvedVIN ? 'green' as const : 'orange' as const
    },
    {
      label: '服务状态',
      value: customerStatusTitle(serviceStatus?.title) || serviceConclusion.status,
      detail: serviceStatus?.detail ?? serviceConclusion.risk,
      color: serviceConclusion.color
    },
    {
      label: '实时主数据通道',
      value: overview?.primaryProtocol || summary?.primaryProtocol || '-',
      detail: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '暂无来源',
      color: evidenceOnlineSourceCount > 0 ? 'green' as const : 'orange' as const
    },
    {
      label: '业务可用性',
      value: online ? '在线可用' : hasResolvedVIN ? '离线待查' : '待绑定',
      detail: lastSeen === '-' ? '无最后上报' : `最后上报 ${lastSeen}`,
      color: online ? 'green' as const : 'orange' as const
    }
  ];
  const copyUnifiedVehicleService = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的统一车辆服务摘要');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【统一车辆服务摘要】',
      `车辆：${vehicleName}`,
      `当前范围：${scopeText}`,
      `车辆身份：${hasResolvedVIN ? displayVIN : '待绑定'}`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `服务说明：${serviceStatus?.detail ?? serviceConclusion.risk}`,
      `实时主数据通道：${overview?.primaryProtocol || summary?.primaryProtocol || '-'}`,
      `通道在线：${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount}` : '-'}`,
      `业务可用性：${online ? '在线可用' : hasResolvedVIN ? '离线待查' : '待绑定'}`,
      `服务数据：实时 ${overview?.realtimeCount ?? detail.realtime.length} / 轨迹 ${overview?.historyCount ?? detail.history.total ?? 0} / 历史数据 ${overview?.rawCount ?? detail.raw.total ?? 0} / 里程 ${overview?.mileageCount ?? detail.mileage.total ?? 0} / 告警 ${overview?.qualityIssueCount ?? qualityCount}`,
      `下一步：${serviceActions[0]?.label ?? serviceConclusion.nextStep}`,
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`,
      `实时监控：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹回放：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`
    ];
    copyText(lines.join('\n'), '统一车辆服务摘要');
  };
  const copyVehicleServiceDossier = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的车辆服务档案');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【车辆服务档案】',
      `车辆：${vehicleName}`,
      `查询关键词：${displayLookupKey}`,
      `当前范围：${scopeText}`,
      `档案完整度：${archiveCompleteness}${archiveMissingLabels.length > 0 ? `（${archiveMissingLabels.join('、')}）` : ''}`,
      `主数据通道：${overview?.primaryProtocol || summary?.primaryProtocol || '-'}`,
      `通道在线：${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount}` : '-'}`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `服务说明：${serviceStatus?.detail ?? serviceConclusion.risk}`,
      `资产概览：${serviceAssetItems.map((item) => `${item.label} ${item.value}`).join(' / ')}`,
      `一致性：${customerStatusTitle(consistencyTitle) || consistencyTitle}`,
      `下一步：${serviceActions[0]?.label ?? serviceConclusion.nextStep}`,
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`,
      `实时监控：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹回放：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`
    ];
    copyText(lines.join('\n'), '车辆服务档案');
  };
  const copyVehicleOperationsSummary = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的车辆服务摘要');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const actionLines = serviceActions.map((item, index) => `${index + 1}. ${item.label}：${item.description}`);
    const lines = [
      '【车辆服务摘要】',
      `车辆：${vehicleName}`,
      `当前范围：${scopeText}`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `业务影响：${serviceConclusion.risk}`,
      `建议动作：${serviceConclusion.nextStep}`,
      `在线数据通道：${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount}` : '-'}`,
      `定位数据：${evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount}` : '0'}`,
      `质量问题：${qualityCount.toLocaleString()} 项`,
      `服务数据：轨迹 ${overview?.historyCount ?? detail.history.total ?? 0} / 历史数据 ${overview?.rawCount ?? detail.raw.total ?? 0} / 里程 ${overview?.mileageCount ?? detail.mileage.total ?? 0}`,
      `下一步清单：${actionLines.length > 0 ? '' : '暂无明确处置项，持续观察实时状态。'}`,
      ...actionLines,
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`,
      `实时监控：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹回放：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`
    ];
    copyText(lines.join('\n'), '车辆服务摘要');
  };
  const detailWorkbench = [
    {
      title: '实时定位',
      value: lastSeen,
      meta: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '暂无来源',
      color: online ? 'green' as const : 'orange' as const,
      detail: '查看该车最新位置、速度、SOC、总里程和多通道实时字段。',
      disabled: !hasResolvedVIN,
      actions: [
        { label: '查看实时', onClick: () => onOpenRealtime(resolvedVIN, activeProtocol) }
      ]
    },
    {
      title: '轨迹回放',
      value: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条历史`,
      meta: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个位置证据` : '暂无位置',
      color: evidenceLocatedSourceCount > 0 ? 'blue' as const : 'grey' as const,
      detail: '回放历史轨迹，复核定位断点、速度变化和里程连续性。',
      disabled: !hasResolvedVIN,
      actions: [
        { label: '打开轨迹', onClick: () => onOpenHistory(resolvedVIN, activeProtocol) }
      ]
    },
    {
      title: '历史数据',
      value: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 帧`,
      meta: latestRaw?.frameType || '字段明细',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      detail: '查看历史明细和字段明细，用于复核定位、里程和告警依据。',
      disabled: !hasResolvedVIN,
      actions: [
        { label: '查看历史数据', onClick: () => onOpenRaw(resolvedVIN, activeProtocol) }
      ]
    },
    {
      title: '告警处置',
      value: `${qualityCount.toLocaleString()} 项`,
      meta: priorityQualityIssue ? qualityIssueLabel(priorityQualityIssue.issueType) : '暂无告警',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      detail: '进入告警队列，处理断链、VIN 缺失、字段缺失和来源不一致。',
      disabled: !hasResolvedVIN && qualityCount <= 0,
      actions: [
        { label: '查看告警', onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle()) }
      ]
    },
    {
      title: '里程复核',
      value: `${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条统计`,
      meta: formatCompactNumber(evidenceMileageDelta, ' km 差异'),
      color: isFiniteNumber(evidenceMileageDelta) && Math.abs(evidenceMileageDelta) > 1 ? 'orange' as const : 'green' as const,
      detail: '核对里程口径，确认区间总值、每日里程与数据通道是否闭合。',
      disabled: !hasResolvedVIN,
      actions: [
        { label: '查看统计', onClick: () => onOpenMileage(resolvedVIN, activeProtocol) }
      ]
    }
  ];
  const customerVehicleActionBar = [
    {
      title: '看当前位置',
      value: formatLocation(latest),
      detail: '确认车辆当前位置、在线状态、最后上报和地图可用性。',
      action: '实时地图',
      color: online ? 'green' as const : hasResolvedVIN ? 'orange' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      title: '回放轨迹',
      value: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条`,
      detail: '按同一车辆进入轨迹回放，复核位置、速度和里程断点。',
      action: '轨迹回放',
      color: (overview?.historyCount ?? detail?.history?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenHistory(resolvedVIN, activeProtocol)
    },
    {
      title: '核对里程',
      value: `${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条`,
      detail: '进入里程统计，核对区间里程、日里程和统计闭合。',
      action: '里程统计',
      color: (overview?.mileageCount ?? detail?.mileage?.total ?? 0) > 0 ? 'green' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenMileage(resolvedVIN, activeProtocol)
    },
    {
      title: '导出证据',
      value: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 条`,
      detail: '查询历史数据和字段证据，作为客户复盘与导出依据。',
      action: '历史导出',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRaw(resolvedVIN, activeProtocol)
    },
    {
      title: '告警通知',
      value: `${qualityCount.toLocaleString()} 项`,
      detail: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无待通知告警。',
      action: '告警闭环',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      disabled: !hasResolvedVIN && qualityCount <= 0,
      onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
    }
  ];
  const serviceRunbookSteps = [
    {
      title: '确认实时状态',
      evidence: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线，最后上报 ${lastSeen}` : '暂无在线数据',
      acceptance: '车辆在线状态、最新时间、有效坐标均可解释。',
      action: '打开实时',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      title: '回放轨迹断点',
      evidence: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个通道有位置，时间差 ${formatSeconds(evidenceTimeDeltaSeconds)}` : '暂无可回放位置',
      acceptance: '轨迹点、速度和总里程变化连续，异常点可定位到时间段。',
      action: '轨迹回放',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenHistory(resolvedVIN, activeProtocol)
    },
    {
      title: '查询历史数据',
      evidence: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 条历史数据，最新类型 ${latestRaw?.frameType || '-'}`,
      acceptance: '关键字段来自解析字段而不是页面二次推断。',
      action: '历史数据',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRaw(resolvedVIN, activeProtocol)
    },
    {
      title: '处理告警闭环',
      evidence: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无质量告警',
      acceptance: '断链、VIN 缺失、字段缺失等问题进入告警队列并有处置结论。',
      action: '告警队列',
      disabled: !onOpenQuality || (!hasResolvedVIN && qualityCount <= 0),
      onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
    },
    {
      title: '复核里程口径',
      evidence: `${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条统计，证据里程差 ${formatCompactNumber(evidenceMileageDelta, ' km')}`,
      acceptance: '区间里程、每日里程和轨迹总里程可以互相解释。',
      action: '里程统计',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenMileage(resolvedVIN, activeProtocol)
    }
  ];
  const copyVehicleRunbook = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的单车处理清单');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【单车服务处理清单】',
      `车辆：${vehicleName}`,
      `当前范围：${scopeText}`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `一致性：${customerStatusTitle(consistencyTitle) || consistencyTitle}`,
      ...serviceRunbookSteps.map((item, index) => [
        `${index + 1}. ${item.title}`,
        `   证据：${item.evidence}`,
        `   验收：${item.acceptance}`
      ].join('\n')),
      `实时监控：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹回放：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `告警事件：${vehicleServiceURL(buildAppHash({ page: 'alert-events', keyword: resolvedVIN, protocol: activeProtocol }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`,
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`
    ];
    copyText(lines.join('\n'), '单车处理清单');
  };
  const detailTaskBoard = [
    {
      title: '看实时位置',
      value: lastSeen,
      detail: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线，先确认车辆当前是否仍在上报。` : '暂无在线数据，优先确认数据接入。',
      color: online ? 'green' as const : 'orange' as const,
      primaryAction: '实时监控',
      secondaryAction: '复制摘要',
      disabled: !hasResolvedVIN,
      onPrimary: () => onOpenRealtime(resolvedVIN, activeProtocol),
      onSecondary: () => copyUnifiedVehicleService()
    },
    {
      title: '回放轨迹证据',
      value: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条历史`,
      detail: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个位置证据，可回放定位、速度和里程断点。` : '暂无有效位置证据，先检查实时坐标。',
      color: evidenceLocatedSourceCount > 0 ? 'blue' as const : 'grey' as const,
      primaryAction: '轨迹回放',
      secondaryAction: '处理清单',
      disabled: !hasResolvedVIN,
      onPrimary: () => onOpenHistory(resolvedVIN, activeProtocol),
      onSecondary: () => copyVehicleRunbook()
    },
    {
      title: '查询历史数据',
      value: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 帧`,
      detail: latestRaw?.frameType ? `最新历史数据类型 ${latestRaw.frameType}，用于核对解析字段。` : '按车辆和数据通道查询历史明细与解析字段。',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      primaryAction: '历史数据',
      secondaryAction: '导出档案',
      disabled: !hasResolvedVIN,
      onPrimary: () => onOpenRaw(resolvedVIN, activeProtocol),
      onSecondary: () => exportVehicleReport()
    },
    {
      title: '复核里程统计',
      value: `${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条统计`,
      detail: `证据里程差 ${formatCompactNumber(evidenceMileageDelta, ' km')}，确认区间和日统计能闭合。`,
      color: isFiniteNumber(evidenceMileageDelta) && Math.abs(evidenceMileageDelta) > 1 ? 'orange' as const : 'green' as const,
      primaryAction: '里程统计',
      secondaryAction: '诊断摘要',
      disabled: !hasResolvedVIN,
      onPrimary: () => onOpenMileage(resolvedVIN, activeProtocol),
      onSecondary: () => copyVehicleDiagnosticSummary()
    },
    {
      title: '闭环告警事件',
      value: `${qualityCount.toLocaleString()} 项`,
      detail: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无高优先级告警，保持观察。',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      primaryAction: '告警事件',
      secondaryAction: '服务摘要',
      disabled: !onOpenQuality || (!hasResolvedVIN && qualityCount <= 0),
      onPrimary: () => onOpenQuality?.(qualityFiltersForCurrentVehicle()),
      onSecondary: () => copyVehicleOperationsSummary()
    }
  ];
  const customerServicePackageItems = [
    {
      title: '实时监控',
      value: online ? '在线' : hasResolvedVIN ? '离线' : '待绑定',
      detail: lastSeen === '-' ? '暂无最后上报时间' : `最后上报 ${lastSeen}`,
      color: online ? 'green' as const : 'orange' as const,
      action: '打开监控',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      title: '轨迹回放',
      value: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条`,
      detail: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个通道可定位` : '暂无可用定位数据',
      color: evidenceLocatedSourceCount > 0 ? 'blue' as const : 'grey' as const,
      action: '回放轨迹',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenHistory(resolvedVIN, activeProtocol)
    },
    {
      title: '历史数据查询',
      value: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 帧`,
      detail: latestRaw?.frameType ? `最新 ${latestRaw.frameType}` : 'RAW 与解析字段证据',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      action: '查询历史',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRaw(resolvedVIN, activeProtocol)
    },
    {
      title: '告警通知',
      value: `${qualityCount.toLocaleString()} 项`,
      detail: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无待通知告警',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      action: '告警闭环',
      disabled: !onOpenQuality || (!hasResolvedVIN && qualityCount <= 0),
      onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
    },
    {
      title: '里程统计',
      value: `${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条`,
      detail: `里程差 ${formatCompactNumber(evidenceMileageDelta, ' km')}`,
      color: isFiniteNumber(evidenceMileageDelta) && Math.abs(evidenceMileageDelta) > 1 ? 'orange' as const : 'green' as const,
      action: '里程复核',
      disabled: !hasResolvedVIN,
      onClick: () => onOpenMileage(resolvedVIN, activeProtocol)
    }
  ];
  const liveViewActions = [
    {
      title: '实时位置',
      value: formatLocation(latest),
      detail: lastSeen === '-' ? '暂无最后上报时间' : `最后上报 ${lastSeen}`,
      action: '查看实时',
      color: online ? 'green' as const : 'orange' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      title: '轨迹历史',
      value: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条`,
      detail: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个定位证据` : '暂无有效定位',
      action: '轨迹回放',
      color: evidenceLocatedSourceCount > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenHistory(resolvedVIN, activeProtocol)
    },
    {
      title: '里程与能源',
      value: `${formatCompactNumber(latest?.totalMileageKm, ' km')}`,
      detail: `SOC ${formatCompactNumber(latest?.socPercent, '%')} / 速度 ${formatCompactNumber(latest?.speedKmh, ' km/h')}`,
      action: '里程统计',
      color: isFiniteNumber(latest?.totalMileageKm) ? 'green' as const : 'orange' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenMileage(resolvedVIN, activeProtocol)
    },
    {
      title: '数据导出',
      value: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 帧`,
      detail: latestRaw?.frameType ? `最新 ${latestRaw.frameType}` : '历史明细与字段',
      action: '历史导出',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRaw(resolvedVIN, activeProtocol)
    },
    {
      title: '告警通知',
      value: `${qualityCount.toLocaleString()} 项`,
      detail: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无待通知告警',
      action: '告警闭环',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      disabled: !onOpenQuality || (!hasResolvedVIN && qualityCount <= 0),
      onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
    }
  ];
  const vehicleArchiveSummaryItems = [
    {
      title: '服务状态',
      value: online ? '在线可服务' : hasResolvedVIN ? '离线待核' : '待绑定',
      detail: lastSeen === '-' ? '暂无最后上报' : `最后上报 ${lastSeen}`,
      action: '查看实时',
      color: online ? 'green' as const : 'orange' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      title: '轨迹证据',
      value: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条`,
      detail: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个定位证据可回放` : '暂无有效定位证据',
      action: '轨迹回放',
      color: evidenceLocatedSourceCount > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenHistory(resolvedVIN, activeProtocol)
    },
    {
      title: '历史证据',
      value: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 帧`,
      detail: latestRaw?.frameType ? `最新 ${latestRaw.frameType}` : '历史明细与解析字段',
      action: '历史查询',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRaw(resolvedVIN, activeProtocol)
    },
    {
      title: '告警通知',
      value: `${qualityCount.toLocaleString()} 项`,
      detail: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无待通知告警',
      action: '告警闭环',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      disabled: !onOpenQuality || (!hasResolvedVIN && qualityCount <= 0),
      onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
    },
    {
      title: '里程口径',
      value: `${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条`,
      detail: `证据里程差 ${formatCompactNumber(evidenceMileageDelta, ' km')}`,
      action: '里程统计',
      color: isFiniteNumber(evidenceMileageDelta) && Math.abs(evidenceMileageDelta) > 1 ? 'orange' as const : 'green' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenMileage(resolvedVIN, activeProtocol)
    }
  ];
  const customerQuestionActions = [
    {
      question: '这辆车现在在哪里？',
      answer: formatLocation(latest),
      action: '实时监控',
      color: online ? 'green' as const : 'orange' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      question: '最近是否还在线？',
      answer: lastSeen === '-' ? '暂无最后上报' : `最后上报 ${lastSeen}`,
      action: '查看实时',
      color: online ? 'green' as const : 'orange' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRealtime(resolvedVIN, activeProtocol)
    },
    {
      question: '能不能回放轨迹？',
      answer: `${formatCompactNumber(overview?.historyCount ?? detail?.history?.total ?? 0)} 条轨迹证据`,
      action: '轨迹回放',
      color: evidenceLocatedSourceCount > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenHistory(resolvedVIN, activeProtocol)
    },
    {
      question: '这辆车跑了多少？',
      answer: `${formatCompactNumber(latest?.totalMileageKm, ' km')} / ${formatCompactNumber(overview?.mileageCount ?? detail?.mileage?.total ?? 0)} 条统计`,
      action: '里程统计',
      color: isFiniteNumber(latest?.totalMileageKm) ? 'green' as const : 'orange' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenMileage(resolvedVIN, activeProtocol)
    },
    {
      question: '数据能导出吗？',
      answer: `${formatCompactNumber(overview?.rawCount ?? detail?.raw?.total ?? 0)} 条历史数据`,
      action: '历史导出',
      color: (overview?.rawCount ?? detail?.raw?.total ?? 0) > 0 ? 'blue' as const : 'grey' as const,
      disabled: !hasResolvedVIN,
      onClick: () => onOpenRaw(resolvedVIN, activeProtocol)
    },
    {
      question: '是否需要通知处理？',
      answer: priorityQualityIssue ? `${qualityIssueLabel(priorityQualityIssue.issueType)} / ${priorityQualityIssue.lastSeen || '-'}` : '暂无待通知告警',
      action: '告警通知',
      color: qualityCount > 0 ? 'orange' as const : 'green' as const,
      disabled: !onOpenQuality || (!hasResolvedVIN && qualityCount <= 0),
      onClick: () => onOpenQuality?.(qualityFiltersForCurrentVehicle())
    }
  ];
  const copyCustomerServicePackage = () => {
    if (!detail) {
      Toast.warning('当前没有可复制的客户服务交付包');
      return;
    }
    const vehicleName = [archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey;
    const lines = [
      '【单车客户服务交付包】',
      `车辆：${vehicleName}`,
      `当前范围：${scopeText}`,
      `平台能力：实时监控 / 轨迹回放 / 历史数据查询 / 告警通知 / 里程统计`,
      `服务状态：${customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}`,
      `服务说明：${serviceStatus?.detail ?? serviceConclusion.risk}`,
      `在线数据通道：${evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount}` : '-'}`,
      `最新上报：${lastSeen}`,
      `轨迹证据：${overview?.historyCount ?? detail.history.total ?? 0} 条`,
      `历史数据：${overview?.rawCount ?? detail.raw.total ?? 0} 条`,
      `里程统计：${overview?.mileageCount ?? detail.mileage.total ?? 0} 条，证据差异 ${formatCompactNumber(evidenceMileageDelta, ' km')}`,
      `告警事件：${qualityCount.toLocaleString()} 项`,
      `车辆服务：${vehicleServiceURL(vehicleServiceHash('detail'))}`,
      `实时监控：${vehicleServiceURL(vehicleServiceHash('realtime'))}`,
      `轨迹回放：${vehicleServiceURL(vehicleServiceHash('history'))}`,
      `历史数据查询：${vehicleServiceURL(vehicleServiceHash('history-query', { tab: 'raw', includeFields: 'true' }))}`,
      `告警通知：${vehicleServiceURL(buildAppHash({ page: 'alert-events', keyword: resolvedVIN, protocol: activeProtocol }))}`,
      `里程统计：${vehicleServiceURL(vehicleServiceHash('mileage'))}`
    ];
    copyText(lines.join('\n'), '客户服务交付包');
  };
  const qualityTable = (
    <Table
      loading={loading}
      pagination={false}
      rowKey={(row?: QualityIssueRow) => `${row?.protocol ?? ''}-${row?.issueType ?? ''}-${row?.lastSeen ?? ''}`}
      dataSource={detail?.quality?.items ?? []}
      columns={[
        { title: '来源', dataIndex: 'protocol', width: 130 },
        { title: '问题', dataIndex: 'issueType', width: 150 },
        { title: '级别', width: 110, render: (_: unknown, row: QualityIssueRow) => <Tag color={row.severity === 'error' ? 'red' : 'orange'}>{row.severity}</Tag> },
        { title: '最后时间', dataIndex: 'lastSeen', width: 190 },
        { title: '说明', dataIndex: 'detail' }
      ]}
    />
  );
  const exportVehicleReport = () => {
    if (!detail) {
      Toast.warning('当前没有可导出的车辆档案');
      return;
    }
    const rows: VehicleReportRow[] = [
      { section: '身份档案', item: '车辆主键', value: reportText(displayVIN) },
      { section: '身份档案', item: '查询关键词', value: reportText(displayLookupKey) },
      { section: '身份档案', item: '车牌', value: reportText(archivePlate) },
      { section: '身份档案', item: '手机号', value: reportText(archivePhone) },
      { section: '身份档案', item: 'OEM', value: reportText(archiveOEM) },
      { section: '身份档案', item: '档案完整度', value: archiveCompleteness },
      { section: '身份档案', item: '档案缺项', value: reportText(archiveMissingLabels) },
      { section: '服务结论', item: '服务判断', value: serviceConclusion.status },
      { section: '服务结论', item: '主要风险', value: serviceConclusion.risk },
      { section: '服务结论', item: '下一步', value: serviceConclusion.nextStep },
      { section: '车辆服务', item: '数据通道', value: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '-' },
      { section: '车辆服务', item: '定位数据', value: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个通道有位置` : '暂无位置' },
      { section: '车辆服务', item: '里程差异', value: formatCompactNumber(evidenceMileageDelta, ' km') },
      { section: '车辆服务', item: '时间差异', value: formatSeconds(evidenceTimeDeltaSeconds) },
      { section: '车辆服务', item: '一致性结论', value: customerStatusTitle(consistencyTitle) || consistencyTitle },
      { section: '车辆服务', item: '一致性说明', value: consistencyDetail },
      { section: '数据规模', item: '历史记录', value: String(overview?.historyCount ?? detail.history.total ?? 0) },
      { section: '数据规模', item: '历史数据', value: String(overview?.rawCount ?? detail.raw.total ?? 0) },
      { section: '数据规模', item: '里程记录', value: String(overview?.mileageCount ?? detail.mileage.total ?? 0) },
      { section: '数据规模', item: '质量问题', value: String(qualityCount) }
    ];
    for (const source of detail.sourceStatus ?? []) {
      rows.push(
        { section: `数据通道 ${source.protocol}`, item: '在线', value: source.online ? '在线' : '离线' },
        { section: `数据通道 ${source.protocol}`, item: '最后时间', value: reportText(source.lastSeen) },
        { section: `数据通道 ${source.protocol}`, item: '能力', value: sourceCapabilities.filter((item) => source[item.key]).map((item) => item.label).join('|') || '-' }
      );
    }
    downloadCsv(vehicleReportFileName(displayVIN, activeProtocol), buildCsv(vehicleReportColumns, rows));
    Toast.success('已导出车辆服务档案');
  };

  return (
    <div className="vp-page">
      <PageHeader title="车辆服务" description="以车辆为主对象查看实时位置、轨迹回放、里程统计、告警通知和历史数据" />
      <Card bordered>
        <Form key={formKey} initValues={query} layout="horizontal" onSubmit={(values) => {
          const nextQuery = { keyword: String(values.keyword ?? ''), protocol: String(values.protocol ?? '') };
          setQuery(nextQuery);
          onQueryChange?.(nextQuery.keyword, nextQuery.protocol);
          load(nextQuery);
        }}>
          <Form.Input field="keyword" label="车辆关键词" placeholder="VIN / 车牌 / 手机号" style={{ width: 280 }} />
          <Form.Select field="protocol" label="数据通道" placeholder="全部数据通道" style={{ width: 180 }}>
            <Select.Option value="GB32960">GB32960</Select.Option>
            <Select.Option value="JT808">JT808</Select.Option>
            <Select.Option value="YUTONG_MQTT">YUTONG_MQTT</Select.Option>
          </Form.Select>
          <Space>
            <Button icon={<IconSearch />} htmlType="submit" theme="solid" type="primary">查询车辆</Button>
            <Button icon={<IconRefresh />} onClick={() => load(query)} loading={loading}>刷新</Button>
            <Button icon={<IconCopy />} onClick={copyVehicleServiceURL}>复制服务链接</Button>
            <Button disabled={!detail} icon={<IconCopy />} onClick={copyVehicleDiagnosticSummary}>复制诊断摘要</Button>
            <Button disabled={!detail} icon={<IconCopy />} onClick={copyVehicleOperationsSummary}>复制服务摘要</Button>
            <Button disabled={!detail} icon={<IconDownload />} onClick={exportVehicleReport}>导出档案 CSV</Button>
            <Button disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}>查看实时</Button>
            <Button disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}>轨迹回放</Button>
            <Button disabled={!hasResolvedVIN} onClick={() => onOpenRaw(resolvedVIN, activeProtocol)}>历史数据</Button>
            <Button disabled={!hasResolvedVIN} onClick={() => onOpenMileage(resolvedVIN, activeProtocol)}>里程统计</Button>
          </Space>
        </Form>
      </Card>

      <div className="vp-scope-bar">
        <span className="vp-scope-label">当前查看范围</span>
        <Tag color={activeProtocol ? 'blue' : 'green'}>{scopeText}</Tag>
        <Typography.Text type="tertiary">
          {activeProtocol ? '下方实时、轨迹、历史数据和里程仅展示该数据通道返回的数据。' : '下方数据按车辆聚合展示全部可用数据通道。'}
        </Typography.Text>
      </div>

      {serviceStatus ? (
        <div className={`vp-service-status vp-service-status-${serviceStatus.severity}`}>
          <span className="vp-scope-label">车辆服务状态</span>
          <Tag color={serviceStatus.severity === 'ok' ? 'green' : serviceStatus.severity === 'error' ? 'red' : 'orange'}>
            {customerStatusTitle(serviceStatus.title)}
          </Tag>
          <Typography.Text type="tertiary">{serviceStatus.detail}</Typography.Text>
        </div>
      ) : null}

      <Card bordered className="vp-vehicle-live-view">
        <div className="vp-vehicle-live-main">
          <div className="vp-vehicle-live-copy">
            <Space wrap>
              <Tag color="blue">单车 Live View</Tag>
              <Tag color={online ? 'green' : hasResolvedVIN ? 'orange' : 'grey'}>{online ? '在线' : hasResolvedVIN ? '离线' : '待绑定'}</Tag>
              <Tag color={serviceConclusion.color}>{customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}</Tag>
            </Space>
            <Typography.Title heading={3} style={{ margin: 0 }}>
              {[archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey}
            </Typography.Title>
            <Typography.Text type="secondary">
              客户打开一辆车时，先看当前位置、最后上报、速度、SOC、总里程和告警，再进入轨迹回放、里程统计、数据导出和告警闭环。
            </Typography.Text>
            <div className="vp-single-vehicle-action-bar" aria-label="客户单车操作台">
              <div className="vp-single-vehicle-action-head">
                <div>
                  <strong>客户单车操作台</strong>
                  <span>围绕这辆车直接完成看车、回放、统计、导出和告警通知。</span>
                </div>
                <Tag color="blue">单车服务</Tag>
              </div>
              <div className="vp-single-vehicle-action-grid">
                {customerVehicleActionBar.map((item) => (
                  <button
                    key={item.title}
                    type="button"
                    className="vp-single-vehicle-action-item"
                    disabled={item.disabled}
                    onClick={item.onClick}
                    aria-label={`客户单车操作台 ${item.title} ${item.value} ${item.action}`}
                  >
                    <Tag color={item.color}>{item.title}</Tag>
                    <strong>{item.value}</strong>
                    <span>{item.detail}</span>
                    <em>{item.action}</em>
                  </button>
                ))}
              </div>
            </div>
            <div className="vp-vehicle-live-facts">
              {[
                { label: '当前位置', value: formatLocation(latest) },
                { label: '最后上报', value: lastSeen },
                { label: '速度', value: formatCompactNumber(latest?.speedKmh, ' km/h') },
                { label: 'SOC', value: formatCompactNumber(latest?.socPercent, '%') },
                { label: '总里程', value: formatCompactNumber(latest?.totalMileageKm, ' km') }
              ].map((item) => (
                <div key={item.label}>
                  <span>{item.label}</span>
                  <strong>{item.value}</strong>
                </div>
              ))}
            </div>
            <Space wrap>
              <Button theme="solid" type="primary" disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}>实时监控</Button>
              <Button theme="light" type="primary" disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}>轨迹回放</Button>
              <Button theme="light" type="primary" disabled={!hasResolvedVIN} onClick={() => onOpenRaw(resolvedVIN, activeProtocol)}>数据导出</Button>
              <Button theme="light" disabled={!detail} icon={<IconCopy />} onClick={copyCustomerServicePackage}>复制交付包</Button>
            </Space>
          </div>
          <VehicleMap
            points={vehicleMapPoints}
            maxFallbackPoints={16}
            heightClassName="vp-vehicle-live-map"
            fallbackLabel="显示该车最新位置"
          />
        </div>
        <div className="vp-vehicle-live-actions">
          {liveViewActions.map((item) => (
            <button
              key={item.title}
              type="button"
              className="vp-vehicle-live-action"
              disabled={item.disabled}
              aria-label={`单车实时视图 ${item.title} ${item.action}`}
              onClick={item.onClick}
            >
              <Tag color={item.color}>{item.title}</Tag>
              <strong>{item.value}</strong>
              <span>{item.detail}</span>
              <em>{item.action}</em>
            </button>
          ))}
        </div>
      </Card>

      <Card bordered className="vp-single-vehicle-time-window" title="单车时间窗交付">
        <div className="vp-single-vehicle-time-window-main">
          <div className="vp-single-vehicle-time-window-copy">
            <Space wrap>
              <Tag color="blue">单车时间窗</Tag>
              <Tag color={activeProtocol ? 'blue' : 'green'}>{activeProtocol || '全部数据通道'}</Tag>
              <Tag color={hasResolvedVIN ? 'green' : 'orange'}>{hasResolvedVIN ? '车辆已定位' : '待绑定车辆'}</Tag>
            </Space>
            <Typography.Title heading={4} style={{ margin: 0 }}>单车时间窗交付</Typography.Title>
            <Typography.Text type="secondary">
              把同一辆车和同一段时间带入轨迹回放、里程统计、历史导出和告警通知，客户复盘时不需要跨页面重复输入。
            </Typography.Text>
            <div className="vp-single-vehicle-time-window-controls">
              <label>
                <span>开始日期</span>
                <input
                  placeholder="单车开始日期"
                  value={vehicleTimeWindow.dateFrom ?? ''}
                  onChange={(event) => setVehicleTimeWindow((previous) => ({ ...previous, dateFrom: event.currentTarget.value }))}
                />
              </label>
              <label>
                <span>结束日期</span>
                <input
                  placeholder="单车结束日期"
                  value={vehicleTimeWindow.dateTo ?? ''}
                  onChange={(event) => setVehicleTimeWindow((previous) => ({ ...previous, dateTo: event.currentTarget.value }))}
                />
              </label>
              <Button size="small" theme="light" onClick={() => setVehicleTimeWindow({})}>清空</Button>
              <Button size="small" theme="light" icon={<IconCopy />} disabled={!detail} onClick={copyVehicleTimeWindowPackage}>复制时间窗包</Button>
            </div>
          </div>
          <div className="vp-single-vehicle-time-window-actions">
            {[
              { title: '轨迹回放', value: vehicleTimeWindowText, detail: '按同一时间窗回放位置、速度和里程断点。', action: '轨迹回放', color: 'blue' as const, onClick: openVehicleWindowHistory },
              { title: '里程统计', value: vehicleTimeWindowText, detail: '核对区间里程、日统计和总里程差值。', action: '里程统计', color: 'green' as const, onClick: openVehicleWindowMileage },
              { title: '历史数据导出', value: vehicleTimeWindowText, detail: '导出 RAW 与解析字段证据，缩小复盘范围。', action: '历史导出', color: 'blue' as const, onClick: openVehicleWindowRaw },
              { title: '告警通知', value: vehicleTimeWindowText, detail: '查看这辆车在同一范围内的风险事件。', action: '告警通知', color: qualityCount > 0 ? 'orange' as const : 'green' as const, onClick: openVehicleWindowAlerts }
            ].map((item) => (
              <button
                key={item.title}
                type="button"
                className="vp-single-vehicle-time-window-action"
                disabled={!hasResolvedVIN || (item.title === '告警通知' && !onOpenQuality)}
                aria-label={`单车时间窗交付 ${item.title} ${item.value}`}
                onClick={item.onClick}
              >
                <Tag color={item.color}>{item.title}</Tag>
                <strong>{item.value}</strong>
                <span>{item.detail}</span>
                <em>{item.action}</em>
              </button>
            ))}
          </div>
        </div>
      </Card>

      <Card bordered className="vp-vehicle-archive-summary" title="客户车辆档案摘要">
        <div className="vp-vehicle-archive-summary-main">
          <div className="vp-vehicle-archive-summary-copy">
            <Space wrap>
              <Tag color={hasResolvedVIN ? 'green' : 'orange'}>{hasResolvedVIN ? '已解析车辆' : '待绑定车辆'}</Tag>
              <Tag color={activeProtocol ? 'blue' : 'green'}>{scopeText}</Tag>
              <Tag color={serviceConclusion.color}>{customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}</Tag>
            </Space>
            <Typography.Title heading={4} style={{ margin: 0 }}>
              {[archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey}
            </Typography.Title>
            <Typography.Text type="secondary">
              把 VIN、车牌、在线状态、实时位置、轨迹、历史数据、告警和统计放在同一个单车入口，协议来源只作为可追溯证据。
            </Typography.Text>
          </div>
          <div className="vp-vehicle-archive-summary-grid">
            {vehicleArchiveSummaryItems.map((item) => (
              <button
                key={item.title}
                type="button"
                className="vp-vehicle-archive-summary-item"
                disabled={item.disabled}
                aria-label={`车辆档案摘要 ${item.title} ${item.action}`}
                onClick={item.onClick}
              >
                <Tag color={item.color}>{item.title}</Tag>
                <strong>{item.value}</strong>
                <span>{item.detail}</span>
                <em>{item.action}</em>
              </button>
            ))}
          </div>
        </div>
      </Card>

      <Card bordered title="客户常问" style={{ marginTop: 16 }}>
        <div className="vp-vehicle-question-grid">
          {customerQuestionActions.map((item) => (
            <button
              key={item.question}
              type="button"
              className="vp-vehicle-question-item"
              disabled={item.disabled}
              aria-label={`单车客户常问 ${item.question} ${item.action}`}
              onClick={item.onClick}
            >
              <strong>{item.question}</strong>
              <span>{item.answer}</span>
              <Tag color={item.color}>{item.action}</Tag>
            </button>
          ))}
        </div>
      </Card>

      <Card
        bordered
        title={<Space><span>车辆服务总览</span><Button size="small" disabled={!detail} icon={<IconCopy />} onClick={copyUnifiedVehicleService}>复制归一摘要</Button></Space>}
        style={{ marginTop: 16 }}
      >
        <div className="vp-unified-service-board">
          <div className="vp-unified-service-main">
            <Space wrap>
              <Tag color={activeProtocol ? 'blue' : 'green'}>{scopeText}</Tag>
              <Tag color={serviceConclusion.color}>{customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}</Tag>
            </Space>
            <Typography.Title heading={4} style={{ margin: 0 }}>
              {[archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey}
            </Typography.Title>
            <Typography.Text type="secondary">
              {serviceStatus?.detail ?? serviceConclusion.risk}
            </Typography.Text>
            <div className="vp-unified-service-actions">
              <Button size="small" theme="solid" type="primary" disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}>实时监控</Button>
              <Button size="small" theme="light" disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}>轨迹回放</Button>
              <Button size="small" theme="light" disabled={!hasResolvedVIN} onClick={() => onOpenRaw(resolvedVIN, activeProtocol)}>历史数据</Button>
              <Button size="small" theme="light" disabled={!hasResolvedVIN} onClick={() => onOpenMileage(resolvedVIN, activeProtocol)}>里程统计</Button>
            </div>
          </div>
          <div className="vp-unified-service-grid">
            {unifiedVehicleServiceItems.map((item) => (
              <div key={item.label} className="vp-unified-service-item">
                <Tag color={item.color}>{item.label}</Tag>
                <strong>{item.value}</strong>
                <Typography.Text type="secondary">{item.detail}</Typography.Text>
              </div>
            ))}
          </div>
        </div>
      </Card>

      <Card
        bordered
        title={<Space><span>车辆服务档案总览</span><Button size="small" disabled={!detail} icon={<IconCopy />} onClick={copyVehicleServiceDossier}>复制档案</Button></Space>}
        style={{ marginTop: 16 }}
      >
        <div className="vp-service-dossier">
          <div className="vp-service-dossier-main">
            <Space wrap>
              <Tag color={hasResolvedVIN ? 'green' : 'orange'}>{hasResolvedVIN ? '已解析 VIN' : '待维护身份'}</Tag>
              <Tag color={activeProtocol ? 'blue' : 'green'}>{scopeText}</Tag>
              <Tag color={serviceConclusion.color}>{customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}</Tag>
            </Space>
            <Typography.Title heading={4} style={{ margin: 0 }}>
              {[archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey}
            </Typography.Title>
            <div className="vp-service-dossier-meta">
              {[
                { label: '手机号', value: archivePhone || '-' },
                { label: 'OEM', value: archiveOEM || '-' },
                { label: '主数据通道', value: overview?.primaryProtocol || summary?.primaryProtocol || '-' },
                { label: '最后上报', value: lastSeen },
                { label: '档案完整度', value: archiveCompleteness },
                { label: '下一步', value: serviceActions[0]?.label ?? serviceConclusion.nextStep }
              ].map((item) => (
                <div key={item.label}>
                  <span>{item.label}</span>
                  <strong>{item.value}</strong>
                </div>
              ))}
            </div>
          </div>
          <div className="vp-service-dossier-assets">
            {serviceAssetItems.map((item) => (
              <div key={item.label} className="vp-service-dossier-asset">
                <Tag color={item.color}>{item.label}</Tag>
                <strong>{item.value}</strong>
                <Typography.Text type="secondary">{item.detail}</Typography.Text>
              </div>
            ))}
          </div>
        </div>
        {archiveMissingLabels.length > 0 ? (
          <div className="vp-service-dossier-missing">
            {archiveMissingLabels.map((label) => (
              <Tag key={label} color="orange">{label}</Tag>
            ))}
          </div>
        ) : null}
      </Card>

      <Card
        bordered
        title={<Space><span>单车客户服务交付包</span><Button size="small" disabled={!detail} icon={<IconCopy />} onClick={copyCustomerServicePackage}>复制交付包</Button></Space>}
        style={{ marginTop: 16 }}
      >
        <div className="vp-customer-service-package">
          <div className="vp-customer-service-summary">
            <Space wrap>
              <Tag color={serviceConclusion.color}>{customerStatusTitle(serviceStatus?.title) || serviceConclusion.status}</Tag>
              <Tag color={activeProtocol ? 'blue' : 'green'}>{scopeText}</Tag>
              <Tag color={hasResolvedVIN ? 'green' : 'orange'}>{hasResolvedVIN ? 'VIN 已解析' : '身份待绑定'}</Tag>
            </Space>
            <Typography.Title heading={4} style={{ margin: 0 }}>
              {[archivePlate, displayVIN].filter((item) => item && item !== '-').join(' / ') || displayLookupKey}
            </Typography.Title>
            <Typography.Text type="secondary">
              面向客户交付时，以车辆为主对象提供实时监控、轨迹回放、历史数据查询、告警通知和里程统计，协议来源只作为可追溯证据。
            </Typography.Text>
            <div className="vp-customer-service-links">
              <Button size="small" theme="solid" type="primary" disabled={!hasResolvedVIN} onClick={() => onOpenRealtime(resolvedVIN, activeProtocol)}>实时监控</Button>
              <Button size="small" theme="light" disabled={!hasResolvedVIN} onClick={() => onOpenHistory(resolvedVIN, activeProtocol)}>轨迹回放</Button>
              <Button size="small" theme="light" disabled={!hasResolvedVIN} onClick={() => onOpenRaw(resolvedVIN, activeProtocol)}>历史数据查询</Button>
              <Button size="small" theme="light" disabled={!onOpenQuality || (!hasResolvedVIN && qualityCount <= 0)} onClick={() => onOpenQuality?.(qualityFiltersForCurrentVehicle())}>告警通知</Button>
              <Button size="small" theme="light" disabled={!hasResolvedVIN} onClick={() => onOpenMileage(resolvedVIN, activeProtocol)}>里程统计</Button>
            </div>
          </div>
          <div className="vp-customer-service-grid">
            {customerServicePackageItems.map((item) => (
              <button
                key={item.title}
                className="vp-customer-service-item"
                disabled={item.disabled}
                aria-label={`客户服务交付 ${item.title} ${item.action}`}
                onClick={item.onClick}
                type="button"
              >
                <Tag color={item.color}>{item.title}</Tag>
                <strong>{item.value}</strong>
                <span>{item.detail}</span>
                <em>{item.action}</em>
              </button>
            ))}
          </div>
        </div>
      </Card>

      {overview ? (
        <Card bordered title="车辆服务概览" style={{ marginTop: 16 }}>
          <Descriptions
            row
            data={[
              { key: '服务车辆', value: [overview.plate, overview.vin].filter(Boolean).join(' / ') || '-' },
              { key: '在线数据通道', value: `${overview.onlineSourceCount}/${overview.sourceCount}` },
              { key: '覆盖状态', value: <Tag color={overview.coverageStatus === 'online' ? 'green' : overview.coverageStatus === 'partial' ? 'orange' : 'grey'}>{coverageStatusText[overview.coverageStatus] ?? overview.coverageStatus}</Tag> },
              { key: '主数据通道', value: overview.primaryProtocol || '-' },
              { key: '最后上报', value: overview.lastSeen || '-' },
              { key: '服务数据', value: `轨迹 ${overview.historyCount} / 历史数据 ${overview.rawCount} / 里程 ${overview.mileageCount}` },
              { key: '实时来源', value: overview.realtimeCount },
              { key: '质量问题', value: qualityIssueAction(overview.qualityIssueCount) }
            ]}
          />
        </Card>
      ) : null}

      <Card bordered title="车辆服务结论" style={{ marginTop: 16 }}>
        <div className="vp-conclusion-grid">
          {[
            { label: '服务判断', value: <Tag color={serviceConclusion.color}>{serviceConclusion.status}</Tag> },
            { label: '主要风险', value: serviceConclusion.risk },
            { label: '下一步', value: serviceConclusion.nextStep }
          ].map((item) => (
            <div key={item.label} className="vp-conclusion-item">
              <div className="vp-evidence-label">{item.label}</div>
              <div className="vp-evidence-value">{item.value}</div>
            </div>
          ))}
        </div>
      </Card>

      <Card bordered title="今日单车服务任务板" style={{ marginTop: 16 }}>
        <div className="vp-vehicle-task-grid">
          {detailTaskBoard.map((item) => (
            <div key={item.title} className="vp-vehicle-task-item">
              <div className="vp-vehicle-task-head">
                <Tag color={item.color}>{item.title}</Tag>
                <strong>{item.value}</strong>
              </div>
              <Typography.Text type="secondary">{item.detail}</Typography.Text>
              <Space wrap>
                <Button
                  size="small"
                  theme="solid"
                  type="primary"
                  disabled={item.disabled}
                  aria-label={`单车任务 ${item.title} ${item.primaryAction}`}
                  onClick={item.onPrimary}
                >
                  {item.primaryAction}
                </Button>
                <Button
                  size="small"
                  theme="light"
                  type="primary"
                  disabled={item.disabled && item.title !== '闭环告警事件'}
                  aria-label={`单车任务 ${item.title} ${item.secondaryAction}`}
                  onClick={item.onSecondary}
                >
                  {item.secondaryAction}
                </Button>
              </Space>
            </div>
          ))}
        </div>
      </Card>

      <Card bordered title="单车服务任务台" style={{ marginTop: 16 }}>
        <div className="vp-workbench-grid">
          {detailWorkbench.map((item) => (
            <div key={item.title} className="vp-workbench-item">
              <div className="vp-workbench-head">
                <Tag color={item.color}>{item.title}</Tag>
                <Typography.Text type="secondary">{item.meta}</Typography.Text>
              </div>
              <div className="vp-workbench-value">{item.value}</div>
              <Typography.Text type="secondary">{item.detail}</Typography.Text>
              <Space wrap>
                {item.actions.map((action) => (
                  <Button
                    key={action.label}
                    size="small"
                    theme="light"
                    type="primary"
                    disabled={item.disabled || (item.title === '告警处置' && !onOpenQuality)}
                    aria-label={`单车服务任务台 ${item.title} ${action.label}`}
                    onClick={action.onClick}
                  >
                    {action.label}
                  </Button>
                ))}
              </Space>
            </div>
          ))}
        </div>
      </Card>

      <Card
        bordered
        title={<Space><span>单车服务处理清单</span><Button size="small" onClick={copyVehicleRunbook}>复制处理清单</Button></Space>}
        style={{ marginTop: 16 }}
      >
        <div className="vp-runbook-grid">
          {serviceRunbookSteps.map((item, index) => (
            <div key={item.title} className="vp-runbook-step">
              <div className="vp-runbook-index">{index + 1}</div>
              <div className="vp-runbook-body">
                <Typography.Title heading={6} style={{ margin: 0 }}>{item.title}</Typography.Title>
                <Typography.Text type="secondary">{item.evidence}</Typography.Text>
                <div className="vp-runbook-acceptance">{item.acceptance}</div>
                <Button
                  size="small"
                  theme="light"
                  type="primary"
                  disabled={item.disabled}
                  aria-label={`单车处理清单 ${item.title} ${item.action}`}
                  onClick={item.onClick}
                >
                  {item.action}
                </Button>
              </div>
            </div>
          ))}
        </div>
      </Card>

      {overview || consistency ? (
        <Card bordered title="车辆服务数据链" style={{ marginTop: 16 }}>
          <div className="vp-evidence-grid">
            {[
              { label: '数据通道', value: evidenceSourceCount > 0 ? `${evidenceOnlineSourceCount}/${evidenceSourceCount} 在线` : '-' },
              { label: '定位数据', value: evidenceLocatedSourceCount > 0 ? `${evidenceLocatedSourceCount} 个通道有位置` : '暂无位置' },
              { label: '里程差异', value: formatCompactNumber(evidenceMileageDelta, ' km') },
              { label: '时间差异', value: formatSeconds(evidenceTimeDeltaSeconds) },
              { label: '主数据通道', value: overview?.primaryProtocol || summary?.primaryProtocol || '-' },
              { label: '服务结论', value: customerStatusTitle(consistencyTitle) || consistencyTitle }
            ].map((item) => (
              <div key={item.label} className="vp-evidence-item">
                <div className="vp-evidence-label">{item.label}</div>
                <div className="vp-evidence-value">{item.value}</div>
              </div>
            ))}
          </div>
          <Typography.Text type="secondary">{consistencyDetail}</Typography.Text>
        </Card>
      ) : null}

      {hasResolvedVIN && sourceFusionRows.length > 0 ? (
        <Card
          bordered
          title={<Space><span>数据通道归并矩阵</span><Button size="small" aria-label="复制归并矩阵" icon={<IconCopy />} onClick={copySourceFusionReport}>复制归并矩阵</Button></Space>}
          style={{ marginTop: 16 }}
        >
          <div className="vp-source-fusion-grid">
            {sourceFusionRows.map((row) => (
              <div key={row.source.protocol} className="vp-source-fusion-item">
                <div className="vp-source-fusion-head">
                  <Space spacing={6} wrap>
                    <Tag color={row.role.color}>{row.source.protocol}</Tag>
                    <Tag color={row.source.online ? 'green' : row.source.lastSeen ? 'orange' : 'grey'}>{row.freshness}</Tag>
                  </Space>
                  <Tag color={row.role.color}>{row.role.label}</Tag>
                </div>
                <div className="vp-source-fusion-contribution">
                  {row.contribution.map((item) => (
                    <Tag key={item} color={item === '待补来源' ? 'orange' : 'blue'}>{item}</Tag>
                  ))}
                </div>
                <div className="vp-source-fusion-facts">
                  {[
                    { label: '实时', value: row.realtimeText },
                    { label: '定位', value: row.locationText },
                    { label: '历史数据', value: row.rawText },
                    { label: '里程', value: row.mileageText }
                  ].map((item) => (
                    <div key={item.label} className="vp-source-fusion-fact">
                      <span>{item.label}</span>
                      <strong>{item.value}</strong>
                    </div>
                  ))}
                </div>
                <Space wrap>
                  <Button
                    size="small"
                    theme={activeProtocol === row.source.protocol ? 'solid' : 'light'}
                    type={activeProtocol === row.source.protocol ? 'primary' : 'tertiary'}
                    disabled={activeProtocol === row.source.protocol}
                    aria-label={`归并矩阵仅看 ${row.source.protocol}`}
                    onClick={() => switchSource(row.source.protocol)}
                  >
                    仅看
                  </Button>
                  <Button size="small" theme="light" disabled={!row.source.hasRealtime} onClick={() => onOpenRealtime(resolvedVIN, row.source.protocol)}>实时</Button>
                  <Button size="small" theme="light" disabled={!row.source.hasHistory} onClick={() => onOpenHistory(resolvedVIN, row.source.protocol)}>轨迹</Button>
                  <Button size="small" theme="light" disabled={!row.source.hasRaw} onClick={() => onOpenRaw(resolvedVIN, row.source.protocol)}>历史数据</Button>
                  <Button size="small" theme="light" disabled={!row.source.hasMileage} onClick={() => onOpenMileage(resolvedVIN, row.source.protocol)}>里程</Button>
                </Space>
              </div>
            ))}
          </div>
        </Card>
      ) : null}

      {hasResolvedVIN && vehicleMapPoints.length > 0 ? (
        <Card bordered title="车辆位置态势" style={{ marginTop: 16 }}>
          <div className="vp-vehicle-map-layout">
            <VehicleMap
              points={vehicleMapPoints}
              heightClassName="vp-vehicle-detail-map"
              maxFallbackPoints={12}
              fallbackLabel="高德地图未配置，显示车辆服务坐标预览"
            />
            <div className="vp-vehicle-map-side">
              <Space wrap>
                <Tag color="blue">{locatedRealtimeRows.length.toLocaleString()} 个来源有最新位置</Tag>
                <Tag color={activeProtocol ? 'blue' : 'green'}>{scopeText}</Tag>
              </Space>
              {locatedRealtimeRows.map((row) => (
                <div key={`${row.protocol}-${row.lastSeen}-${row.longitude}-${row.latitude}`} className="vp-vehicle-map-source">
                  <div className="vp-vehicle-map-source-main">
                    <Typography.Text strong>{row.protocol}</Typography.Text>
                    <Tag color={sourceOnlineByProtocol.get(row.protocol) === false ? 'orange' : 'green'}>
                      {row.protocol} / {formatCompactNumber(row.speedKmh, ' km/h')}
                    </Tag>
                  </div>
                  <Typography.Text type="secondary" size="small">
                    {row.longitude}, {row.latitude}
                  </Typography.Text>
                  <Typography.Text type="tertiary" size="small">
                    {formatCompactNumber(row.totalMileageKm, ' km')} / {row.lastSeen || '-'}
                  </Typography.Text>
                </div>
              ))}
            </div>
          </div>
        </Card>
      ) : null}

      <Card bordered title="服务处置建议" style={{ marginTop: 16 }}>
        <div className="vp-action-grid">
          {serviceActions.map((item) => (
            <div key={item.key} className="vp-action-item">
              <div>
                <Tag color={item.color}>{item.label}</Tag>
                <Typography.Text type="secondary" style={{ display: 'block', marginTop: 8 }}>{item.description}</Typography.Text>
              </div>
              <Button size="small" theme="light" type={item.color === 'red' ? 'danger' : item.color === 'green' ? 'primary' : 'warning'} onClick={item.onClick}>
                {item.label}
              </Button>
            </div>
          ))}
        </div>
      </Card>

      {priorityQualityIssue ? (
        <Card bordered title="单车处置建议" style={{ marginTop: 16 }}>
          <div className="vp-action-item">
            <div>
              <Space wrap>
                <Tag color={priorityQualityIssue.severity === 'error' ? 'red' : 'orange'}>
                  {qualityIssueLabel(priorityQualityIssue.issueType)}
                </Tag>
                <Tag color="blue">{priorityQualityIssue.protocol || activeProtocol || '全部来源'}</Tag>
                <Tag color="grey">{priorityQualityIssue.lastSeen || '无时间'}</Tag>
              </Space>
              <Typography.Text strong style={{ display: 'block', marginTop: 8 }}>
                {qualityIssueVehicleLabel(priorityQualityIssue, resolvedVIN)}
              </Typography.Text>
              <Typography.Text type="secondary" style={{ display: 'block', marginTop: 6 }}>
                {priorityQualityIssue.detail || '该车存在告警事件，需要结合轨迹和历史数据确认影响范围。'}
              </Typography.Text>
            </div>
            <Space wrap>
              <Button size="small" theme="light" type="warning" onClick={() => onOpenQuality?.({
                keyword: priorityQualityIssue.vin || resolvedVIN,
                protocol: priorityQualityIssue.protocol || activeProtocol,
                issueType: priorityQualityIssue.issueType
              })}>
                告警列表
              </Button>
              <Button
                aria-label="单车告警轨迹证据"
                size="small"
                theme="light"
                type="primary"
                onClick={() => openQualityIssueHistoryEvidence(priorityQualityIssue)}
              >
                轨迹证据
              </Button>
              <Button
                aria-label="单车告警历史数据"
                size="small"
                theme="light"
                type="tertiary"
                onClick={() => openQualityIssueRawEvidence(priorityQualityIssue)}
              >
                历史数据
              </Button>
            </Space>
          </div>
        </Card>
      ) : null}

      <Card bordered title="车辆档案" style={{ marginTop: 16 }}>
        <div className="vp-vehicle-summary">
          <Descriptions
            row
            data={[
              { key: '车辆主键', value: displayVIN },
              { key: '查询关键词', value: displayLookupKey },
              { key: 'VIN', value: displayVIN },
              { key: '解析状态', value: <Tag color={hasResolvedVIN ? 'green' : 'orange'}>{hasResolvedVIN ? '已解析 VIN' : '未解析到 VIN'}</Tag> },
              { key: '车牌', value: archivePlate || '-' },
              { key: '手机号', value: archivePhone || '-' },
              { key: 'OEM', value: archiveOEM || '-' },
              {
                key: '档案完整度',
                value: (
                  <Space spacing={4} wrap>
                    <Tag color={archiveCompleteness === '4/4' ? 'green' : 'orange'}>{archiveCompleteness}</Tag>
                    {archiveMissingLabels.map((label) => (
                      <Tag key={label} color="orange">{label}</Tag>
                    ))}
                  </Space>
                )
              },
              { key: '归并来源数', value: archiveSourceCount },
              { key: '在线', value: <StatusTag status={online ? 'ok' : 'offline'} /> },
              {
                key: '数据通道',
                value: protocols.length > 0 ? (
                  <SourceStatusTags sourceStatus={detail?.sourceStatus} protocols={protocols} lastSeen={lastSeen === '-' ? '' : lastSeen} />
                ) : '-'
              },
              { key: '在线数据通道', value: summary ? `${summary.onlineSourceCount}/${summary.sourceCount}` : '-' },
              { key: '最后位置时间', value: lastSeen },
              { key: '最新历史数据时间', value: latestRaw?.serverTime ?? '-' },
              { key: '质量问题', value: <Tag color={qualityCount > 0 ? 'orange' : 'green'}>{qualityCount > 0 ? `${qualityCount} 项` : '无'}</Tag> }
            ]}
          />
        </div>
        {!hasResolvedVIN ? (
          <Banner
            type="warning"
            bordered
            title="身份绑定待处理"
            description={`车辆关键词 ${displayLookupKey} 暂未解析到 VIN，请维护车辆身份绑定后再查看历史、里程和跨证据数据。`}
            style={{ marginTop: 12 }}
          />
        ) : null}
      </Card>

      {hasResolvedVIN ? (
        <>
          <Card bordered title="数据通道覆盖" style={{ marginTop: 16 }}>
            {detail?.sourceStatus?.length ? (
              <>
                <div className="vp-source-toolbar">
                  <Space>
                    <Tag color={activeProtocol ? 'grey' : 'blue'}>{activeProtocol ? `当前 ${activeProtocol}` : '当前 全部数据通道'}</Tag>
                    <SourceStatusTags sourceStatus={detail.sourceStatus} protocols={protocols} lastSeen={lastSeen === '-' ? '' : lastSeen} />
                    <Button size="small" disabled={!activeProtocol} onClick={() => switchSource('')}>全部数据通道</Button>
                  </Space>
                </div>
                <Table
                  loading={loading}
                  pagination={false}
                  rowKey="protocol"
                  dataSource={detail.sourceStatus}
                  columns={[
                    {
                      title: '数据通道',
                      dataIndex: 'protocol',
                      width: 140,
                      render: (_: unknown, row: VehicleSourceStatus) => (
                        <Tag color={row.protocol === summary?.primaryProtocol ? 'blue' : 'grey'}>{row.protocol}</Tag>
                      )
                    },
                    {
                      title: '车辆服务角色',
                      width: 130,
                      render: (_: unknown, row: VehicleSourceStatus) => {
                        const role = sourceServiceRole(row, summary?.primaryProtocol);
                        return <Tag color={role.color}>{role.label}</Tag>;
                      }
                    },
                    { title: '在线', width: 100, render: (_: unknown, row: VehicleSourceStatus) => <StatusTag status={row.online ? 'ok' : 'offline'} /> },
                    { title: '最后时间', dataIndex: 'lastSeen', width: 190, render: (value?: string) => value || '无上报' },
                    {
                      title: '最新位置',
                      width: 170,
                      render: (_: unknown, row: VehicleSourceStatus) => formatLocation(latestRealtimeByProtocol.get(row.protocol))
                    },
                    {
                      title: '里程',
                      width: 110,
                      render: (_: unknown, row: VehicleSourceStatus) => formatCompactNumber(latestRealtimeByProtocol.get(row.protocol)?.totalMileageKm, ' km')
                    },
                    {
                      title: '速度',
                      width: 110,
                      render: (_: unknown, row: VehicleSourceStatus) => formatCompactNumber(latestRealtimeByProtocol.get(row.protocol)?.speedKmh, ' km/h')
                    },
                    {
                      title: 'SOC',
                      width: 90,
                      render: (_: unknown, row: VehicleSourceStatus) => formatCompactNumber(latestRealtimeByProtocol.get(row.protocol)?.socPercent, '%')
                    },
                    ...sourceCapabilities.map((item) => ({
                      title: item.label,
                      width: 90,
                      render: (_: unknown, row: VehicleSourceStatus) => <Tag color={row[item.key] ? 'green' : 'grey'}>{row[item.key] ? '有' : '无'}</Tag>
                    })),
                    {
                      title: '操作',
                      width: 330,
                      render: (_: unknown, row: VehicleSourceStatus) => (
                        <Space spacing={6} wrap>
                          <Button
                            size="small"
                            theme={activeProtocol === row.protocol ? 'solid' : 'light'}
                            type={activeProtocol === row.protocol ? 'primary' : 'tertiary'}
                            disabled={activeProtocol === row.protocol}
                            onClick={() => switchSource(row.protocol)}
                          >
                            仅看 {row.protocol}
                          </Button>
                          <Button
                            size="small"
                            theme="light"
                            type="tertiary"
                            disabled={!row.hasHistory}
                            onClick={() => onOpenHistory(resolvedVIN, row.protocol)}
                          >
                            查看 {row.protocol} 轨迹
                          </Button>
                          <Button
                            size="small"
                            theme="light"
                            type="tertiary"
                            disabled={!row.hasRaw}
                            onClick={() => onOpenRaw(resolvedVIN, row.protocol)}
                          >
                            查看 {row.protocol} 历史数据
                          </Button>
                          <Button
                            size="small"
                            theme="light"
                            type="tertiary"
                            disabled={!row.hasMileage}
                            onClick={() => onOpenMileage(resolvedVIN, row.protocol)}
                          >
                            查看 {row.protocol} 里程
                          </Button>
                        </Space>
                      )
                    }
                  ]}
                />
              </>
            ) : (
              <Typography.Text type="secondary">暂未查询到该车辆的数据通道覆盖。</Typography.Text>
            )}
          </Card>

          <Card bordered title="跨证据一致性" style={{ marginTop: 16 }}>
            <Descriptions
              row
              data={[
                { key: '一致性结论', value: customerStatusTitle(consistencyTitle) || consistencyTitle },
                { key: '通道覆盖', value: consistencySourceCount > 0 ? `${consistencySourceCount} 个通道` : '-' },
                { key: '在线数据通道', value: consistencySourceCount > 0 ? `${consistencyOnlineSourceCount}/${consistencySourceCount} 在线` : '-' },
                { key: '缺失通道', value: missingProtocolText },
                { key: '位置覆盖', value: consistencyLocatedSourceCount > 0 ? `${consistencyLocatedSourceCount} 个通道有位置` : '暂无位置' },
                { key: '里程差异', value: formatCompactNumber(consistencyMileageDelta, ' km') },
                { key: '通道时间差', value: formatSeconds(consistencyTimeDeltaSeconds) },
                { key: '诊断说明', value: consistencyDetail },
                { key: '车辆服务视角', value: activeProtocol ? `当前只看 ${activeProtocol}` : '三类来源合并为同一车辆服务' }
              ]}
            />
          </Card>
        </>
      ) : null}

      {!hasResolvedVIN ? (
        <Card bordered style={{ marginTop: 16 }}>
          <Tabs>
            <Tabs.TabPane tab="质量问题" itemKey="quality">
              {qualityTable}
            </Tabs.TabPane>
          </Tabs>
        </Card>
      ) : (
        <Card bordered style={{ marginTop: 16 }}>
          <Tabs>
          <Tabs.TabPane tab="实时状态" itemKey="realtime">
            <div className="vp-realtime-strip">
              {[
                { label: '最新来源', value: summary?.primaryProtocol || '-' },
                { label: '速度 km/h', value: summary ? summary.speedKmh : '-' },
                { label: 'SOC %', value: summary ? summary.socPercent : '-' },
                { label: '总里程 km', value: summary ? summary.totalMileageKm : '-' },
                { label: '经纬度', value: summary ? `${summary.longitude}, ${summary.latitude}` : '-' },
                { label: '最后时间', value: lastSeen }
              ].map((item) => (
                <div key={item.label} className="vp-realtime-strip-item">
                  <div className="vp-realtime-strip-label">{item.label}</div>
                  <div className="vp-realtime-strip-value">{item.value}</div>
                </div>
              ))}
            </div>
            <Table
              loading={loading}
              pagination={false}
              rowKey="protocol"
              dataSource={detail?.realtime ?? []}
              columns={[
                { title: '来源', dataIndex: 'protocol', width: 130 },
                { title: '经度', dataIndex: 'longitude', width: 120 },
                { title: '纬度', dataIndex: 'latitude', width: 120 },
                { title: '速度 km/h', dataIndex: 'speedKmh', width: 120 },
                { title: 'SOC %', dataIndex: 'socPercent', width: 120 },
                { title: '总里程 km', dataIndex: 'totalMileageKm', width: 130 },
                { title: '最后时间', dataIndex: 'lastSeen', width: 190 }
              ]}
            />
          </Tabs.TabPane>
          <Tabs.TabPane tab="历史位置" itemKey="history">
            <Table
              loading={loading}
              pagination={false}
              rowKey="deviceTime"
              dataSource={detail?.history?.items ?? []}
              columns={[
                { title: '来源', dataIndex: 'protocol', width: 130 },
                { title: '经度', dataIndex: 'longitude', width: 120 },
                { title: '纬度', dataIndex: 'latitude', width: 120 },
                { title: '速度 km/h', dataIndex: 'speedKmh', width: 120 },
                { title: '总里程 km', dataIndex: 'totalMileageKm', width: 130 },
                { title: '设备时间', dataIndex: 'deviceTime', width: 190 },
                { title: '入库时间', dataIndex: 'serverTime', width: 190 }
              ]}
            />
          </Tabs.TabPane>
          <Tabs.TabPane tab="原始字段" itemKey="raw">
            <Table
              loading={loading}
              pagination={false}
              rowKey="id"
              dataSource={detail?.raw?.items ?? []}
              columns={[
                { title: '来源', dataIndex: 'protocol', width: 130 },
                { title: '帧类型', dataIndex: 'frameType', width: 190 },
                { title: '大小 B', dataIndex: 'rawSizeBytes', width: 100 },
                { title: '设备时间', dataIndex: 'deviceTime', width: 190 },
                { title: '入库时间', dataIndex: 'serverTime', width: 190 }
              ]}
            />
            <Typography.Text type="tertiary">最新历史数据字段明细</Typography.Text>
            <pre className="vp-json">{JSON.stringify(latestRaw?.parsedFields ?? {}, null, 2)}</pre>
          </Tabs.TabPane>
          <Tabs.TabPane tab="里程" itemKey="mileage">
            <Table
              loading={loading}
              pagination={false}
              rowKey="date"
              dataSource={detail?.mileage?.items ?? []}
              columns={[
                { title: '日期', dataIndex: 'date', width: 130 },
                { title: '来源', dataIndex: 'source', width: 130 },
                { title: '起始里程', dataIndex: 'startMileageKm', width: 130 },
                { title: '结束里程', dataIndex: 'endMileageKm', width: 130 },
                { title: '日里程', dataIndex: 'dailyMileageKm', width: 130 }
              ]}
            />
          </Tabs.TabPane>
          <Tabs.TabPane tab="质量问题" itemKey="quality">
            {qualityTable}
          </Tabs.TabPane>
          </Tabs>
        </Card>
      )}
    </div>
  );
}
