import { getTodayDate } from '@/common/utils/day';
import { mapKey } from '@/common/utils/mapConfig';
import { Apis } from '@/gen/Apis';
import {
  CaretRightOutlined,
  ExpandOutlined,
  LeftOutlined,
  PauseOutlined,
} from '@ant-design/icons';
import { ProCard } from '@ant-design/pro-components';
import { useNavigate, useParams } from '@umijs/max';
import { Button, DatePicker, message, Select, Space, Spin } from 'antd';
import dayjs from 'dayjs';
import * as L from 'leaflet';
import 'leaflet/dist/leaflet.css';
import { useCallback, useEffect, useRef, useState } from 'react';
import endingPng from './ending.png';
import startingPng from './starting.png';
import './style.scss';

const dateFormat = 'YYYY/MM/DD';

export default function Index({ title = '员工轨迹' }) {
  const navigate = useNavigate();
  const { id } = useParams<{ id: string }>();
  const mapRef = useRef<HTMLDivElement>(null);
  const mapInstanceRef = useRef<L.Map | null>(null);
  const movingMarkerRef = useRef<L.Marker | null>(null);
  const trackLineRef = useRef<L.Polyline | null>(null);
  const animationRef = useRef<number | null>(null);
  const trackPointsRef = useRef<L.LatLngTuple[]>([]);

  const [loading, setLoading] = useState(false);
  const [isPlaying, setIsPlaying] = useState(false);
  const [trackInfo, setTrackInfo] = useState<{
    count: number;
    startTime: string;
    endTime: string;
  } | null>(null);
  const [employees, setEmployees] = useState<any[]>([]);
  const [employeeLoading, setEmployeeLoading] = useState(false);

  // 初始化地图
  const initMap = (center?: L.LatLngTuple) => {
    if (!mapRef.current || mapInstanceRef.current) return;

    const map = L.map(mapRef.current, {
      center: center || [35.8617, 104.1954],
      zoom: center ? 14 : 4,
      maxZoom: 18,
      zoomControl: false,
      attributionControl: false,
    });

    // 天地图底图层
    L.tileLayer(
      `https://t{s}.tianditu.gov.cn/DataServer?T=vec_w&x={x}&y={y}&l={z}&tk=${mapKey}`,
      {
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        attribution: '天地图',
        minZoom: 1,
        maxZoom: 18,
      },
    ).addTo(map);

    // 天地图文字注记层
    L.tileLayer(
      `https://t{s}.tianditu.gov.cn/DataServer?T=cva_w&x={x}&y={y}&l={z}&tk=${mapKey}`,
      {
        subdomains: ['0', '1', '2', '3', '4', '5', '6', '7'],
        attribution: '天地图',
        minZoom: 1,
        maxZoom: 18,
      },
    ).addTo(map);

    // 添加缩放控件到右下角
    L.control
      .zoom({
        position: 'bottomright',
      })
      .addTo(map);

    mapInstanceRef.current = map;
  };

  // 清除轨迹图层（保留底图）
  const clearTrackLayers = () => {
    const map = mapInstanceRef.current;
    if (!map) return;

    map.eachLayer((layer: L.Layer) => {
      if (
        layer instanceof L.Polyline ||
        layer instanceof L.Marker ||
        layer instanceof L.CircleMarker
      ) {
        map.removeLayer(layer);
      }
    });

    trackLineRef.current = null;
  };

  // 显示轨迹
  const showTrack = useCallback((data: any[]) => {
    const map = mapInstanceRef.current;
    if (!map) return;

    clearTrackLayers();

    if (!data || data.length === 0) {
      setTrackInfo(null);
      return;
    }

    const validPoints = data.filter(
      (point) => point.latitude && point.longitude,
    );

    const trackPoints: L.LatLngTuple[] = validPoints.map(
      (point) =>
        [
          parseFloat(point.latitude),
          parseFloat(point.longitude),
        ] as L.LatLngTuple,
    );

    if (trackPoints.length === 0) {
      setTrackInfo(null);
      return;
    }

    trackPointsRef.current = trackPoints;

    // 创建带流动动画的轨迹线
    const trackLine = L.polyline(trackPoints, {
      color: '#f5222d',
      weight: 4,
      opacity: 0.85,
      dashArray: '12, 8',
      lineCap: 'round',
      lineJoin: 'round',
    }).addTo(map);
    trackLineRef.current = trackLine;

    // 添加起点标记
    const startPoint = validPoints[0];
    L.marker(trackPoints[0], {
      icon: L.divIcon({
        className: 'track-start-marker',
        html: `<img width="36" height="36" src="${startingPng}" alt="起点" />`,
        iconSize: [36, 36],
        iconAnchor: [18, 36],
      }),
      zIndexOffset: 1000,
    })
      .bindPopup(
        `<div>
          <h4>起点</h4>
          <p><strong>时间:</strong> ${startPoint.track_time || '未知'}</p>
          <p><strong>坐标:</strong> ${startPoint.latitude}, ${
          startPoint.longitude
        }</p>
        </div>`,
      )
      .addTo(map);

    // 添加终点标记
    const endPoint = validPoints[validPoints.length - 1];
    L.marker(trackPoints[trackPoints.length - 1], {
      icon: L.divIcon({
        className: 'track-end-marker',
        html: `<img width="36" height="36" src="${endingPng}" alt="终点" />`,
        iconSize: [36, 36],
        iconAnchor: [18, 36],
      }),
      zIndexOffset: 1000,
    })
      .bindPopup(
        `<div>
          <h4>终点</h4>
          <p><strong>时间:</strong> ${endPoint.track_time || '未知'}</p>
          <p><strong>坐标:</strong> ${endPoint.latitude}, ${
          endPoint.longitude
        }</p>
        </div>`,
      )
      .addTo(map);

    // 中间点标记（每隔几个点显示一个，避免过多）
    const step = Math.max(1, Math.floor(trackPoints.length / 20));
    trackPoints.forEach((point, index) => {
      if (index === 0 || index === trackPoints.length - 1) return;
      if (index % step !== 0) return;

      const currentPoint = validPoints[index];
      L.marker(point, {
        icon: L.divIcon({
          className: 'track-point-marker',
          html: `<div style="width: 22px; height: 22px; border-radius: 50%; background: linear-gradient(135deg, #1890ff, #36cfc9); color: #fff; display: flex; align-items: center; justify-content: center; font-size: 11px; font-weight: bold; border: 2px solid #fff; box-shadow: 0 2px 6px rgba(0,0,0,0.2);">${
            index + 1
          }</div>`,
          iconSize: [22, 22],
          iconAnchor: [11, 11],
        }),
      })
        .bindPopup(
          `<div>
            <h4>点位 ${index + 1}</h4>
            <p><strong>时间:</strong> ${currentPoint.track_time || '未知'}</p>
            <p><strong>坐标:</strong> ${currentPoint.latitude}, ${
            currentPoint.longitude
          }</p>
          </div>`,
        )
        .addTo(map);
    });

    // 自动调整视图
    map.fitBounds(trackLine.getBounds(), { padding: [40, 40] });

    // 更新统计信息
    setTrackInfo({
      count: validPoints.length,
      startTime: startPoint.track_time || '未知',
      endTime: endPoint.track_time || '未知',
    });
  }, []);

  // 播放轨迹动画
  const playTrack = useCallback(() => {
    const map = mapInstanceRef.current;
    const points = trackPointsRef.current;
    if (!map || points.length < 2 || isPlaying) return;

    setIsPlaying(true);

    // 移除旧的移动标记
    if (movingMarkerRef.current) {
      map.removeLayer(movingMarkerRef.current);
    }

    const movingIcon = L.divIcon({
      className: 'track-moving-marker',
      html: '<div class="moving-icon"></div>',
      iconSize: [28, 28],
      iconAnchor: [14, 14],
    });

    const marker = L.marker(points[0], {
      icon: movingIcon,
      zIndexOffset: 2000,
    }).addTo(map);
    movingMarkerRef.current = marker;

    let currentIndex = 0;
    let progress = 0;
    const speed = 0.03; // 动画速度

    const animate = () => {
      if (currentIndex >= points.length - 1) {
        setIsPlaying(false);
        return;
      }

      progress += speed;

      if (progress >= 1) {
        progress = 0;
        currentIndex++;
      }

      const start = L.latLng(points[currentIndex]);
      const end = L.latLng(points[currentIndex + 1]);
      const lat = start.lat + (end.lat - start.lat) * progress;
      const lng = start.lng + (end.lng - start.lng) * progress;

      marker.setLatLng([lat, lng]);

      // 自动跟随视角（可选：平滑移动）
      if (currentIndex % 5 === 0 && progress < 0.1) {
        map.panTo([lat, lng], { animate: true, duration: 0.3 });
      }

      animationRef.current = requestAnimationFrame(animate);
    };

    animationRef.current = requestAnimationFrame(animate);
  }, [isPlaying]);

  // 暂停轨迹
  const pauseTrack = useCallback(() => {
    if (animationRef.current) {
      cancelAnimationFrame(animationRef.current);
      animationRef.current = null;
    }
    setIsPlaying(false);
  }, []);

  // 重置视图
  const resetView = useCallback(() => {
    const map = mapInstanceRef.current;
    const line = trackLineRef.current;
    if (map && line) {
      map.fitBounds(line.getBounds(), { padding: [40, 40] });
    }
  }, []);

  // 加载轨迹数据
  const loadShow = useCallback(
    (day: any) => {
      setLoading(true);
      pauseTrack();

      Apis.Attendance.AttendanceEmployeeTracks.Heatmap({
        company_employees_id: Number(id),
        date: day,
      })
        .then((res) => {
          const data = res?.data || [];
          const validPoints = data.filter(
            (point: any) => point.latitude && point.longitude,
          );

          if (validPoints.length === 0) {
            message.info('当天没有轨迹');
            clearTrackLayers();
            setTrackInfo(null);
            return;
          }

          const firstPoint: L.LatLngTuple = [
            parseFloat(validPoints[0].latitude),
            parseFloat(validPoints[0].longitude),
          ];
          initMap(firstPoint);
          showTrack(data);
        })
        .finally(() => {
          setLoading(false);
        });
    },
    [id, pauseTrack, showTrack],
  );

  // 加载员工列表
  const loadEmployees = useCallback(() => {
    setEmployeeLoading(true);
    Apis.Company.CompanyEmployees.Select()
      .then((res) => {
        const list = res?.data || [];
        setEmployees(list);
      })
      .finally(() => {
        setEmployeeLoading(false);
      });
  }, []);

  useEffect(() => {
    loadEmployees();
    loadShow(new Date(getTodayDate()));

    return () => {
      if (animationRef.current) {
        cancelAnimationFrame(animationRef.current);
      }
      if (mapInstanceRef.current) {
        mapInstanceRef.current.remove();
        mapInstanceRef.current = null;
      }
    };
  }, [id, loadEmployees, loadShow]);

  return (
    <ProCard
      title={
        <Button
          type="link"
          size="small"
          icon={<LeftOutlined />}
          onClick={() => navigate(-1)}
        >
          员工轨迹底图
        </Button>
      }
      headerBordered
      extra={
        <Space>
          <Select
            showSearch
            allowClear
            placeholder="切换员工"
            loading={employeeLoading}
            value={Number(id)}
            style={{ minWidth: 160 }}
            filterOption={(input, option) =>
              (option?.label ?? '').toLowerCase().includes(input.toLowerCase())
            }
            options={employees.map((item: any) => ({
              label: item?.name || item?.label,
              value: item?.id || item?.value,
            }))}
            onChange={(value) => {
              if (value) {
                navigate(`/attendance/employee_tracks/${value}`);
              }
            }}
          />
          <DatePicker
            defaultValue={dayjs(getTodayDate(), dateFormat)}
            format={dateFormat}
            onChange={(_e: any, dateString: any) => {
              loadShow(dateString);
            }}
          />
          <Button
            type="primary"
            icon={isPlaying ? <PauseOutlined /> : <CaretRightOutlined />}
            onClick={isPlaying ? pauseTrack : playTrack}
            disabled={!trackInfo}
          >
            {isPlaying ? '暂停' : '播放'}
          </Button>
          <Button icon={<ExpandOutlined />} onClick={resetView}>
            重置视图
          </Button>
        </Space>
      }
    >
      <div style={{ position: 'relative' }}>
        {/* 地图容器 */}
        <div
          ref={mapRef}
          style={{
            width: '100%',
            height: 'calc(100vh - 240px)',
            borderRadius: '8px',
            overflow: 'hidden',
            border: '1px solid #e8e8e8',
          }}
        />

        {/* 加载遮罩 */}
        {loading && (
          <div
            style={{
              position: 'absolute',
              top: 0,
              left: 0,
              right: 0,
              bottom: 0,
              background: 'rgba(255,255,255,0.7)',
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'center',
              zIndex: 2000,
              borderRadius: '8px',
            }}
          >
            <Spin tip="加载轨迹中..." size="large" />
          </div>
        )}

        {/* 轨迹统计面板 */}
        {trackInfo && !loading && (
          <div className="track-stats-panel">
            <div>
              <span className="stats-label">轨迹点数：</span>
              <span className="stats-value">{trackInfo.count} 个</span>
            </div>
            <div>
              <span className="stats-label">开始时间：</span>
              <span className="stats-value">{trackInfo.startTime}</span>
            </div>
            <div>
              <span className="stats-label">结束时间：</span>
              <span className="stats-value">{trackInfo.endTime}</span>
            </div>
          </div>
        )}
      </div>

      {/* 图例 */}
      <Space
        style={{
          paddingTop: '15px',
          fontSize: '12px',
          display: 'flex',
          alignItems: 'center',
        }}
      >
        <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          <span>起点：</span>
          <img src={startingPng} width="18" height="18" alt="起点" />
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          <span>终点：</span>
          <img src={endingPng} width="18" height="18" alt="终点" />
        </div>
        <div style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
          <span>轨迹线：</span>
          <span
            style={{
              display: 'inline-block',
              width: 24,
              height: 3,
              background: '#f5222d',
              borderRadius: 2,
            }}
          />
        </div>
      </Space>
    </ProCard>
  );
}
