import { useEffect, useMemo, useRef, useState, type ReactNode } from 'react';
import { Tag } from '@douyinfe/semi-ui';
import { getAMapConfig, isAMapConfigured } from '../config/appConfig';
import { isValidAMapCoordinate, loadAMap, wgs84ToGcj02, type AMapMap, type AMapOverlay } from '../integrations/amap';

export type VehicleMapPoint = {
  id: string;
  label: string;
  longitude: number;
  latitude: number;
  online?: boolean;
  title?: string;
};

function validPoint(point: VehicleMapPoint) {
  return isValidAMapCoordinate(point.longitude, point.latitude);
}

function pointToPixelStyle(point: VehicleMapPoint, index: number) {
  if (!validPoint(point)) {
    return { left: `${18 + (index % 4) * 18}%`, top: `${28 + (index % 3) * 17}%` };
  }
  const left = Math.min(88, Math.max(10, ((point.longitude + 180) / 360) * 100));
  const top = Math.min(82, Math.max(12, ((90 - point.latitude) / 180) * 100));
  return { left: `${left}%`, top: `${top}%` };
}

function escapeHTML(value: string) {
  return value.replace(/[&<>"']/g, (char) => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;'
  }[char] ?? char));
}

function markerContent(point: VehicleMapPoint, index: number, selected: boolean, mode: 'realtime' | 'track') {
  const statusClass = point.online === false ? 'vp-amap-marker-offline' : 'vp-amap-marker-online';
  const selectedClass = selected ? 'vp-amap-marker-selected' : '';
  const markerText = mode === 'track' ? String(index + 1) : '';
  const label = selected ? `<span class="vp-amap-marker-label">${escapeHTML(point.label)}</span>` : '';
  return `<button type="button" class="vp-amap-marker-shell ${selected ? 'vp-amap-marker-shell-selected' : ''}" data-map-vehicle-id="${escapeHTML(point.id)}" aria-label="选择地图车辆 ${escapeHTML(point.label)}"><span class="vp-amap-marker ${statusClass} ${selectedClass}">${markerText}</span>${label}</button>`;
}

function initialMapView(points: VehicleMapPoint[], mode: 'realtime' | 'track') {
  const firstPoint = points[0];
  if (firstPoint) {
    return {
      center: wgs84ToGcj02(firstPoint.longitude, firstPoint.latitude),
      zoom: mode === 'track' ? 13 : 11
    };
  }
  return {
    center: wgs84ToGcj02(104.1954, 35.8617),
    zoom: 4
  };
}

export function VehicleMap({
  points,
  mode = 'realtime',
  heightClassName = 'vp-map-monitor',
  fallbackLabel,
  maxFallbackPoints = 120,
  selectedId,
  onPointSelect,
  children
}: {
  points: VehicleMapPoint[];
  mode?: 'realtime' | 'track';
  heightClassName?: string;
  fallbackLabel?: string;
  maxFallbackPoints?: number;
  selectedId?: string;
  onPointSelect?: (point: VehicleMapPoint) => void;
  children?: ReactNode;
}) {
  const containerRef = useRef<HTMLDivElement | null>(null);
  const mapRef = useRef<AMapMap | null>(null);
  const overlaysRef = useRef<AMapOverlay[]>([]);
  const [status, setStatus] = useState<'ready' | 'fallback' | 'loading'>('fallback');
  const config = getAMapConfig();
  const validPoints = useMemo(() => points.filter(validPoint), [points]);

  useEffect(() => {
    let cancelled = false;
    if (!isAMapConfigured(config) || !containerRef.current) {
      setStatus('fallback');
      return;
    }
    setStatus('loading');
    loadAMap()
      .then((AMap) => {
        if (cancelled || !containerRef.current) return;
        const mapView = initialMapView(validPoints, mode);
        if (!mapRef.current) {
          mapRef.current = new AMap.Map(containerRef.current, {
            zoom: mapView.zoom,
            center: mapView.center,
            viewMode: '2D',
            mapStyle: 'amap://styles/normal'
          });
          mapRef.current.addControl(new AMap.Scale());
        }
        overlaysRef.current.forEach((overlay) => overlay.setMap?.(null));
        const markers = validPoints.slice(0, 500).map((point, index) => {
          const selected = point.id === selectedId;
          const marker = new AMap.Marker({
            position: wgs84ToGcj02(point.longitude, point.latitude),
            title: point.title || point.label,
            zIndex: selected ? 300 : mode === 'track' ? 100 + index : 100,
            content: markerContent(point, index, selected, mode)
          });
          marker.on?.('click', () => onPointSelect?.(point));
          return marker;
        });
        const nextOverlays: AMapOverlay[] = [...markers];
        if (mode === 'track' && validPoints.length > 1) {
          nextOverlays.push(new AMap.Polyline({
            path: validPoints.map((point) => wgs84ToGcj02(point.longitude, point.latitude)),
            strokeColor: '#1664ff',
            strokeOpacity: 0.85,
            strokeWeight: 5,
            lineJoin: 'round'
          }));
        }
        overlaysRef.current = nextOverlays;
        if (nextOverlays.length > 0) {
          mapRef.current.add(nextOverlays);
          mapRef.current.setFitView(nextOverlays, false, [56, 56, 56, 56]);
        }
        setStatus('ready');
      })
      .catch(() => {
        if (!cancelled) setStatus('fallback');
      });
    return () => {
      cancelled = true;
    };
  }, [config.webJsKey, config.securityJsCode, config.securityServiceHost, mode, onPointSelect, selectedId, validPoints]);

  useEffect(() => () => {
    mapRef.current?.destroy();
    mapRef.current = null;
    overlaysRef.current = [];
  }, []);

  const fallbackPoints = (validPoints.length > 0 ? validPoints : points).slice(0, maxFallbackPoints);
  const showFallback = status !== 'ready';

  return (
    <div className={`vp-map ${heightClassName}`}>
      <div ref={containerRef} className="vp-amap-canvas" />
      {showFallback ? (
        <div className="vp-map-fallback">
          {fallbackPoints.map((point, index) => (
            <button
              key={`${point.id}-${index}`}
              type="button"
              aria-label={`选择地图车辆 ${point.label}`}
              className={`vp-map-dot ${mode === 'track' && index === 0 ? 'vp-map-dot-start' : mode === 'track' && index === fallbackPoints.length - 1 ? 'vp-map-dot-end' : point.online === false ? 'vp-map-dot-offline' : 'vp-map-dot-online'} ${point.id === selectedId ? 'vp-map-dot-selected' : ''}`}
              title={point.title || point.label}
              style={pointToPixelStyle(point, index)}
              onClick={() => onPointSelect?.(point)}
            />
          ))}
          <Tag className="vp-map-fallback-status" color={isAMapConfigured(config) ? 'blue' : 'orange'}>
            {status === 'loading' ? '地图加载中' : fallbackLabel || '高德地图未配置，显示坐标预览'}
          </Tag>
        </div>
      ) : (
        <Tag className="vp-map-provider-status" color="green">
          高德地图已加载
        </Tag>
      )}
      {children}
    </div>
  );
}
