import { useEffect, useMemo, useRef, useState } from 'react';
import type { HistoryLocationRow, TrackStop } from '../../api/types';
import { getAMapConfig, isAMapConfigured } from '../../config/appConfig';
import { isValidAMapCoordinate, loadAMap, wgs84ToGcj02, type AMapLike, type AMapMap, type AMapOverlay } from '../../integrations/amap';

function markerContent(kind: 'start' | 'end' | 'stop' | 'current', label?: string) {
  if (kind === 'current') return '<div class="v2-track-current-marker" aria-hidden="true"><i></i><span></span></div>';
  return `<div class="v2-track-marker is-${kind}"><span>${label ?? ''}</span></div>`;
}

export function TrackMap({ points, stops, activeIndex, showStops, follow, onSelectIndex, onFollowChange }: {
  points: HistoryLocationRow[];
  stops: TrackStop[];
  activeIndex: number;
  showStops: boolean;
  follow: boolean;
  onSelectIndex: (index: number) => void;
  onFollowChange: (follow: boolean) => void;
}) {
  const containerRef = useRef<HTMLDivElement>(null);
  const mapRef = useRef<AMapMap | null>(null);
  const amapRef = useRef<AMapLike | null>(null);
  const overlaysRef = useRef<AMapOverlay[]>([]);
  const currentMarkerRef = useRef<AMapOverlay | null>(null);
  const passedPathRef = useRef<AMapOverlay | null>(null);
  const pathRef = useRef<[number, number][]>([]);
  const selectRef = useRef(onSelectIndex);
  const followChangeRef = useRef(onFollowChange);
  const [state, setState] = useState<'loading' | 'ready' | 'fallback' | 'error'>('loading');
  const valid = useMemo(() => points.map((point, index) => ({ point, index })).filter(({ point }) => isValidAMapCoordinate(point.longitude, point.latitude)), [points]);

  useEffect(() => { selectRef.current = onSelectIndex; }, [onSelectIndex]);
  useEffect(() => { followChangeRef.current = onFollowChange; }, [onFollowChange]);

  useEffect(() => {
    if (!containerRef.current || !isAMapConfigured(getAMapConfig())) { setState('fallback'); return; }
    let cancelled = false;
    loadAMap(['AMap.Scale', 'AMap.ToolBar']).then((AMap) => {
      if (cancelled || !containerRef.current) return;
      const first = valid[0]?.point;
      const map = new AMap.Map(containerRef.current, {
        zoom: first ? 13 : 5,
        center: first ? wgs84ToGcj02(first.longitude, first.latitude) : wgs84ToGcj02(105.4, 35.9),
        viewMode: '2D', mapStyle: 'amap://styles/whitesmoke', showLabel: true, resizeEnable: true,
        zooms: [3, 20]
      });
      map.addControl(new AMap.Scale());
      if (AMap.ToolBar) map.addControl(new AMap.ToolBar({ position: { right: '18px', bottom: '148px' } }));
      map.on?.('dragstart', () => followChangeRef.current(false));
      mapRef.current = map;
      amapRef.current = AMap;
      setState('ready');
    }).catch(() => { if (!cancelled) setState('error'); });
    return () => {
      cancelled = true;
      overlaysRef.current.forEach((overlay) => overlay.setMap?.(null));
      currentMarkerRef.current?.setMap?.(null);
      mapRef.current?.destroy();
      overlaysRef.current = [];
      currentMarkerRef.current = null;
      passedPathRef.current = null;
      pathRef.current = [];
      mapRef.current = null;
      amapRef.current = null;
    };
  }, []);

  useEffect(() => {
    const AMap = amapRef.current;
    const map = mapRef.current;
    if (state !== 'ready' || !map || !valid.length || !AMap) return;
    overlaysRef.current.forEach((overlay) => overlay.setMap?.(null));
    currentMarkerRef.current?.setMap?.(null);

    const path = valid.map(({ point }) => wgs84ToGcj02(point.longitude, point.latitude));
    pathRef.current = path;
    const nextValidIndex = valid.findIndex(({ index }) => index >= activeIndex);
    const activeValidIndex = nextValidIndex >= 0 ? nextValidIndex : valid.length - 1;
    const fullPath = new AMap.Polyline({ path, strokeColor: '#2563eb', strokeWeight: 6, strokeOpacity: 0.82, lineJoin: 'round', lineCap: 'round', showDir: true, zIndex: 70 });
    const passedPath = new AMap.Polyline({ path: path.slice(0, activeValidIndex + 1), strokeColor: '#18a86b', strokeWeight: 7, strokeOpacity: 0.96, lineJoin: 'round', lineCap: 'round', zIndex: 80 });
    passedPathRef.current = passedPath;

    const first = valid[0];
    const last = valid[valid.length - 1];
    const start = new AMap.Marker({ position: path[0], anchor: 'center', content: markerContent('start', '始'), zIndex: 115 });
    const end = new AMap.Marker({ position: path[path.length - 1], anchor: 'center', content: markerContent('end', '终'), zIndex: 115 });
    start.on?.('click', () => selectRef.current(first.index));
    end.on?.('click', () => selectRef.current(last.index));
    const overlays: AMapOverlay[] = [fullPath, passedPath, start, end];

    if (showStops) stops.slice(0, 80).forEach((stop, index) => {
      if (!isValidAMapCoordinate(stop.longitude, stop.latitude)) return;
      const marker = new AMap.Marker({
        position: wgs84ToGcj02(stop.longitude, stop.latitude), anchor: 'center',
        content: markerContent('stop', String(index + 1)), zIndex: 105
      });
      marker.on?.('click', () => selectRef.current(Math.min(points.length - 1, Math.max(0, stop.sampledIndex))));
      overlays.push(marker);
    });

    const active = valid.find(({ index }) => index === activeIndex) ?? first;
    const current = new AMap.Marker({ position: wgs84ToGcj02(active.point.longitude, active.point.latitude), anchor: 'center', content: markerContent('current'), zIndex: 130 });
    currentMarkerRef.current = current;
    overlaysRef.current = overlays;
    map.add([...overlays, current]);
    map.setFitView([fullPath], false, [72, 72, 168, 72]);
  }, [points, showStops, state, stops, valid]);

  useEffect(() => {
    const point = points[activeIndex];
    if (!point || !isValidAMapCoordinate(point.longitude, point.latitude)) return;
    const position = wgs84ToGcj02(point.longitude, point.latitude);
    currentMarkerRef.current?.setPosition?.(position);
    const passedCount = valid.reduce((count, entry) => count + (entry.index <= activeIndex ? 1 : 0), 0);
    passedPathRef.current?.setPath?.(pathRef.current.slice(0, Math.max(1, passedCount)));
    if (follow) mapRef.current?.panTo?.(position, 180);
  }, [activeIndex, follow, points, valid]);

  return <div className="v2-track-map">
    <div ref={containerRef} className="v2-track-map-canvas" aria-label="历史轨迹地图" />
    {state !== 'ready' ? <div className={`v2-map-state is-${state}`}>
      {state === 'loading' ? <><span className="v2-spinner" />轨迹地图加载中</> : null}
      {state === 'fallback' ? `地图未配置，已载入 ${valid.length} 个有效轨迹点` : null}
      {state === 'error' ? '地图加载失败，请检查高德地图配置' : null}
    </div> : null}
  </div>;
}
