/**
 * TimelineController - controls time for viewing historical positions
 */
import { useState, useEffect, useCallback, useRef } from 'react';

export interface TimelineState {
  currentDate: Date;
  isPlaying: boolean;
  speed: number; // days per second
  startDate: Date;
  endDate: Date;
}

interface TimelineControllerProps {
  onTimeChange: (date: Date) => void;
  minDate?: Date;
  maxDate?: Date;
}

export function TimelineController({ onTimeChange, minDate, maxDate }: TimelineControllerProps) {
  // Swap: startDate is now (maxDate), endDate is past (minDate)
  const startDate = maxDate || new Date(); // Start from now
  const endDate = minDate || new Date(Date.now() - 365 * 24 * 60 * 60 * 1000); // End at past

  const [currentDate, setCurrentDate] = useState<Date>(startDate); // Start from now
  const [isPlaying, setIsPlaying] = useState(false);
  const [speed, setSpeed] = useState(1); // 1 day per second
  const animationFrameRef = useRef<number>();
  const lastUpdateRef = useRef<number>(Date.now());

  // Animation loop
  useEffect(() => {
    if (!isPlaying) {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
      return;
    }

    const animate = () => {
      const now = Date.now();
      const deltaSeconds = (now - lastUpdateRef.current) / 1000;
      lastUpdateRef.current = now;

      setCurrentDate((prev) => {
        const newDate = new Date(prev.getTime() - speed * deltaSeconds * 24 * 60 * 60 * 1000); // Subtract to go backward in time

        // Loop back to start (now) if we reach the end (past)
        if (newDate < endDate) {
          return new Date(startDate);
        }

        return newDate;
      });

      animationFrameRef.current = requestAnimationFrame(animate);
    };

    lastUpdateRef.current = Date.now();
    animationFrameRef.current = requestAnimationFrame(animate);

    return () => {
      if (animationFrameRef.current) {
        cancelAnimationFrame(animationFrameRef.current);
      }
    };
  }, [isPlaying, speed, startDate, endDate]);

  // Notify parent of time changes (debounced to avoid excessive updates)
  const lastNotifiedDateRef = useRef<string | null>(null);

  useEffect(() => {
    // 圆整到天，避免同一天被通知多次
    const roundedDate = new Date(currentDate);
    roundedDate.setUTCHours(0, 0, 0, 0);
    const dateKey = roundedDate.toISOString();

    // 只在日期真正变化时通知父组件
    if (lastNotifiedDateRef.current !== dateKey) {
      lastNotifiedDateRef.current = dateKey;
      onTimeChange(roundedDate);
    }
  }, [currentDate, onTimeChange]);

  const handlePlayPause = useCallback(() => {
    setIsPlaying((prev) => !prev);
  }, []);

  const handleSpeedChange = useCallback((newSpeed: number) => {
    setSpeed(newSpeed);
  }, []);

  const handleSliderChange = useCallback((e: React.ChangeEvent<HTMLInputElement>) => {
    const value = parseFloat(e.target.value);
    const totalRange = startDate.getTime() - endDate.getTime(); // Now - Past (positive)
    const newDate = new Date(startDate.getTime() - (value / 100) * totalRange); // Start - progress
    setCurrentDate(newDate);
    setIsPlaying(false);
  }, [startDate, endDate]);

  const currentProgress = ((startDate.getTime() - currentDate.getTime()) / (startDate.getTime() - endDate.getTime())) * 100;

  // Format date as YYYY-MM-DD for top display
  const formatFullDate = (date: Date) => {
    const year = date.getFullYear();
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${year}-${month}-${day}`;
  };

  // Format date as MM/DD for range labels
  const formatShortDate = (date: Date) => {
    const month = String(date.getMonth() + 1).padStart(2, '0');
    const day = String(date.getDate()).padStart(2, '0');
    return `${month}/${day}`;
  };

  return (
    <div className="fixed bottom-20 left-1/2 transform -translate-x-1/2 z-50 bg-black bg-opacity-80 p-4 rounded-lg shadow-lg min-w-96">
      {/* Current date display - full format */}
      <div className="text-center text-white text-sm mb-2 font-mono">
        {formatFullDate(currentDate)}
      </div>

      {/* Date range labels */}
      <div className="flex justify-between text-white text-xs mb-1 px-1">
        <span className="text-gray-400">{formatShortDate(startDate)}</span>
        <span className="text-gray-400">{formatShortDate(endDate)}</span>
      </div>

      {/* Progress bar (standard slider) */}
      <input
        type="range"
        min="0"
        max="100"
        step="0.1"
        value={currentProgress}
        onChange={handleSliderChange}
        className="w-full h-2 bg-gray-700 rounded-lg appearance-none cursor-pointer mb-3"
      />

      {/* Controls */}
      <div className="flex items-center justify-center gap-4">
        {/* Play/Pause button */}
        <button
          onClick={handlePlayPause}
          className="bg-blue-600 hover:bg-blue-700 text-white px-4 py-2 rounded"
        >
          {isPlaying ? '⏸ 暂停' : '▶ 播放'}
        </button>

        {/* Speed control */}
        <div className="flex items-center gap-2">
          <span className="text-white text-xs">速度:</span>
          <select
            value={speed}
            onChange={(e) => handleSpeedChange(Number(e.target.value))}
            className="bg-gray-700 text-white px-2 py-1 rounded text-xs"
          >
            <option value="1">1x (1天/秒)</option>
            <option value="7">7x (1周/秒)</option>
            <option value="30">30x (1月/秒)</option>
            <option value="365">365x (1年/秒)</option>
          </select>
        </div>

        {/* Reset button */}
        <button
          onClick={() => {
            setCurrentDate(new Date(startDate)); // Reset to start (now)
            setIsPlaying(false);
          }}
          className="bg-gray-600 hover:bg-gray-700 text-white px-3 py-2 rounded text-xs"
        >
          ⏮ 重置
        </button>
      </div>
    </div>
  );
}
