import { useQuery } from '@tanstack/react-query';
import { Button, Card, Empty, Input, Spin, Tag } from '@douyinfe/semi-ui';
import { useMemo, useState } from 'react';
import { api } from '../../api/client';
import type { VehicleLocationSourceEvidence, VehicleMileageSourceEvidence } from '../../api/types';
import { QUERY_MEMORY } from '../queryPolicy';

function today() {
  const now = new Date();
  const offset = now.getTimezoneOffset() * 60_000;
  return new Date(now.getTime() - offset).toISOString().slice(0, 10);
}

function number(value?: number, digits = 1) {
  return value == null || !Number.isFinite(value) ? '—' : value.toLocaleString('zh-CN', { minimumFractionDigits: digits, maximumFractionDigits: digits });
}

function coordinate(source: VehicleLocationSourceEvidence) {
  if (source.longitude == null || source.latitude == null) return '—';
  return `${source.longitude.toFixed(6)}, ${source.latitude.toFixed(6)}`;
}

function evidenceTone(source: Pick<VehicleLocationSourceEvidence, 'recommended' | 'enabled' | 'online' | 'qualityStatus'>) {
  if (!source.enabled) return 'disabled';
  if (source.qualityStatus !== 'OK') return 'warning';
  if (source.recommended) return 'recommended';
  return source.online ? 'ready' : 'offline';
}

function sourceBadges(source: Pick<VehicleLocationSourceEvidence, 'recommended' | 'selectedWithinProtocol' | 'enabled' | 'online' | 'qualityStatus'>) {
  return <>
    {source.recommended ? <Tag className="is-recommended" color="blue" type="light" size="small">当前推荐</Tag> : null}
    {!source.recommended && source.selectedWithinProtocol ? <Tag color="cyan" type="light" size="small">协议内选中</Tag> : null}
    {!source.enabled ? <Tag className="is-disabled" color="grey" type="light" size="small">已禁用</Tag> : null}
    {source.enabled && !source.online ? <Tag className="is-offline" color="grey" type="light" size="small">离线</Tag> : null}
    {source.qualityStatus !== 'OK' ? <Tag className="is-warning" color="orange" type="light" size="small">{source.qualityStatus}</Tag> : null}
  </>;
}

function LocationSourceCard({ source }: { source: VehicleLocationSourceEvidence }) {
  return <Card className={`v2-source-evidence-card is-${evidenceTone(source)}`} bodyStyle={{ padding: 0 }}>
    <header><div><strong>{source.sourceLabel || source.protocol}</strong><span>{source.protocol}{source.terminalLabel ? ` · ${source.terminalLabel}` : ''}</span></div><aside>{sourceBadges(source)}</aside></header>
    <dl>
      <div><dt>坐标</dt><dd>{coordinate(source)}</dd></div>
      <div><dt>速度</dt><dd>{source.speedKmh == null ? '—' : `${number(source.speedKmh)} km/h`}</dd></div>
      <div><dt>总里程</dt><dd>{source.totalMileageKm == null ? '—' : `${number(source.totalMileageKm)} km`}</dd></div>
      <div><dt>SOC</dt><dd>{source.socPercent == null ? '—' : `${number(source.socPercent)}%`}</dd></div>
      <div><dt>设备时间</dt><dd>{source.eventTime || '—'}</dd></div>
      <div><dt>接收时间</dt><dd>{source.receivedAt || '—'}</dd></div>
    </dl>
    {source.qualityReason ? <p>质量说明：{source.qualityReason}</p> : null}
  </Card>;
}

function MileageSourceCard({ source }: { source: VehicleMileageSourceEvidence }) {
  const comparable = { ...source, online: true };
  return <Card className={`v2-source-evidence-card is-${evidenceTone(comparable)}`} bodyStyle={{ padding: 0 }}>
    <header><div><strong>{source.sourceLabel || source.protocol}</strong><span>{source.protocol}{source.terminalLabel ? ` · ${source.terminalLabel}` : ''}</span></div><aside>{sourceBadges(comparable)}</aside></header>
    <dl>
      <div><dt>当日里程</dt><dd>{source.dailyMileageKm == null ? '—' : `${number(source.dailyMileageKm)} km`}</dd></div>
      <div><dt>最新总里程</dt><dd>{source.latestTotalMileageKm == null ? '—' : `${number(source.latestTotalMileageKm)} km`}</dd></div>
      <div><dt>起始总里程</dt><dd>{source.firstTotalMileageKm == null ? '—' : `${number(source.firstTotalMileageKm)} km`}</dd></div>
      <div><dt>有效样本</dt><dd>{source.sampleCount.toLocaleString('zh-CN')}</dd></div>
      <div><dt>首条时间</dt><dd>{source.firstEventTime || '—'}</dd></div>
      <div><dt>末条时间</dt><dd>{source.latestEventTime || '—'}</dd></div>
    </dl>
    {source.qualityReason ? <p>选举说明：{source.qualityReason}</p> : null}
  </Card>;
}

export function VehicleSourceEvidencePanel({
  vin,
  compact = false,
  open,
  onOpenChange
}: {
  vin: string;
  compact?: boolean;
  open?: boolean;
  onOpenChange?: (open: boolean) => void;
}) {
  const [internalOpen, setInternalOpen] = useState(false);
  const expanded = open ?? internalOpen;
  const setExpanded = (value: boolean) => {
    if (open == null) setInternalOpen(value);
    onOpenChange?.(value);
  };
  const [date, setDate] = useState(today);
  const query = useQuery({
    queryKey: ['vehicle-source-evidence', vin, date],
    queryFn: ({ signal }) => api.vehicleSourceEvidence(vin, date, signal),
    enabled: expanded && Boolean(vin),
    staleTime: 15_000,
    gcTime: QUERY_MEMORY.summaryGcTime,
    refetchOnWindowFocus: false
  });
  const sourceCount = (query.data?.locationSources.length ?? 0) + (query.data?.mileageSources.length ?? 0);
  const description = useMemo(() => {
    if (!query.data) return '按需读取，不影响车辆列表和地图刷新性能';
    if (sourceCount <= 2) return '当前车辆来源较少，仅展示实际存在的证据';
    return `已读取 ${query.data.locationSources.length} 个位置来源、${query.data.mileageSources.length} 个里程来源`;
  }, [query.data, sourceCount]);

  return <Card className={`v2-source-evidence${compact ? ' is-compact' : ''}${expanded ? ' is-open' : ''}`} bodyStyle={{ padding: 0 }}>
    <header className="v2-source-evidence-trigger">
      <div><strong>位置与里程来源</strong><span>{description}</span></div>
      <Button theme="light" aria-expanded={expanded} onClick={() => setExpanded(!expanded)}>{expanded ? '收起来源' : '查看全部来源'}</Button>
    </header>
    {expanded ? <div className="v2-source-evidence-body">
      <div className="v2-source-evidence-toolbar">
        <label><span>里程日期</span><Input aria-label="里程日期" type="date" value={date} max={today()} onChange={setDate} /></label>
        <small>终端标识已脱敏；推荐结果来自后台选举，展开不会改变原始证据。</small>
      </div>
      {query.isPending ? <div className="v2-source-evidence-state" role="status"><Spin size="small" />正在读取全部来源证据…</div> : null}
      {query.isError ? <div className="v2-source-evidence-state is-error"><span>{query.error instanceof Error ? query.error.message : '来源证据读取失败'}</span><Button theme="borderless" type="danger" size="small" onClick={() => void query.refetch()}>重试</Button></div> : null}
      {query.data ? <>
        <div className="v2-source-evidence-summary">
          <div><small>推荐位置来源</small><strong>{query.data.recommendedLocationLabel || query.data.recommendedLocationProtocol || '—'}</strong></div>
          <div><small>最大位置差</small><strong>{number(query.data.comparison.locationMaxDistanceM)}<em>m</em></strong></div>
          <div><small>总里程差</small><strong>{number(query.data.comparison.totalMileageDeltaKm)}<em>km</em></strong></div>
          <div><small>上报时间差</small><strong>{number(query.data.comparison.reportTimeDeltaSeconds, 0)}<em>s</em></strong></div>
        </div>
        {query.data.locationSources.length ? <section className="v2-source-evidence-group"><header><strong>当前位置来源</strong><span>{query.data.locationConflict ? `后台检测到位置冲突${query.data.conflictDistanceM == null ? '' : ` · ${number(query.data.conflictDistanceM)} m`}` : '推荐来源与备用来源并列展示'}</span></header><div>{query.data.locationSources.map((source, index) => <LocationSourceCard key={`${source.protocol}-${source.sourceLabel}-${source.terminalLabel}-${index}`} source={source} />)}</div></section> : null}
        {query.data.mileageSources.length ? <section className="v2-source-evidence-group"><header><strong>{query.data.mileageDate} 里程来源</strong><span>日里程差 {number(query.data.comparison.dailyMileageDeltaKm)} km</span></header><div>{query.data.mileageSources.map((source, index) => <MileageSourceCard key={`${source.protocol}-${source.sourceLabel}-${source.terminalLabel}-${index}`} source={source} />)}</div></section> : null}
        {!query.data.locationSources.length && !query.data.mileageSources.length ? <Empty className="v2-source-evidence-empty" title="暂无来源证据" description="该车辆当前没有可展示的位置或里程来源。" /> : null}
      </> : null}
    </div> : null}
  </Card>;
}
