"use client";

import React, { useState, useEffect, useRef, useCallback, useMemo } from "react";
import { useNotification } from "@refinedev/core";
import Draggable from "react-draggable";

import {
  Box,
  Button,
  Slider,
  Typography,
  Paper,
  MenuItem,
  Select,
  FormControl,
  InputLabel,
  IconButton,
  Stack,
  Tooltip,
} from "@mui/material";
import { DatePicker } from "@mui/x-date-pickers/DatePicker";
import { LocalizationProvider } from "@mui/x-date-pickers/LocalizationProvider";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import "dayjs/locale/zh-cn"; // 引入中文包
import dayjs from "dayjs";
import { PlayArrow, Pause, Stop, Refresh } from "@mui/icons-material";
import { TbRewindBackward15, TbRewindForward15 } from "react-icons/tb";
import { FiSkipBack, FiSkipForward } from "react-icons/fi";
import { useData } from "../MapComponent";
import { config, NETWORK_NAME } from "@/config/config";
import { apiFetch } from "@/lib/apiFetch";
import { permissionCodes } from "@/lib/permissions";
import { useAccessStore } from "@/store/accessStore";
import { useMap } from "../MapComponent";
import {
  formatTimelineTime,
  getRoundedCurrentTimelineMinutes,
  getTimelineDisabledRangePercentages,
  normalizeTimelineMinutes,
} from "./timelineTime";
import { useTimelineTimeConfig } from "./useTimelineTimeConfig";

interface TimelineProps {
  schemeDate?: Date;
  timeRange?: { start: Date; end: Date };
  disableDateSelection?: boolean;
  schemeName?: string;
  schemeType?: string;
}

const timelineIconButtonSx = {
  width: 32,
  height: 32,
  borderRadius: "50%",
  flexShrink: 0,
  overflow: "hidden",
  "&:hover": {
    borderRadius: "50%",
  },
  "&.Mui-focusVisible": {
    borderRadius: "50%",
  },
  "& .MuiTouchRipple-root": {
    borderRadius: "50%",
  },
} as const;

const NOOP_SET_CURRENT_TIME = (_: any) => undefined;
const NOOP_SET_SELECTED_DATE = (_: any) => undefined;
const BASE_CALCULATED_INTERVAL_OPTIONS = [
  { value: 1440, label: "1 天" },
  { value: 60, label: "1 小时" },
  { value: 30, label: "30 分钟" },
  { value: 15, label: "15 分钟" },
  { value: 5, label: "5 分钟" },
];

const Timeline: React.FC<TimelineProps> = ({
  schemeDate,
  timeRange,
  disableDateSelection = false,
  schemeName = "",
  schemeType = "burst_analysis",
}) => {
  const data = useData();
  const canRunSimulation = useAccessStore((state) =>
    state.permissions.includes(permissionCodes.simulationRun),
  );
  const fallbackSelectedDateRef = useRef(new Date());
  const hasTimelineState =
    data &&
    data.setCurrentTime !== undefined &&
    data.currentTime !== undefined &&
    data.selectedDate !== undefined &&
    data.setSelectedDate !== undefined;
  const currentTime = data?.currentTime ?? -1;
  const setCurrentTime = data?.setCurrentTime ?? NOOP_SET_CURRENT_TIME;
  const selectedDate = data?.selectedDate ?? fallbackSelectedDateRef.current;
  const setSelectedDate = data?.setSelectedDate ?? NOOP_SET_SELECTED_DATE;
  const setCurrentJunctionCalData = data?.setCurrentJunctionCalData;
  const setCurrentPipeCalData = data?.setCurrentPipeCalData;
  const setCompareJunctionCalData = data?.setCompareJunctionCalData;
  const setComparePipeCalData = data?.setComparePipeCalData;
  const isCompareMode = data?.isCompareMode ?? false;
  const junctionText = data?.junctionText ?? "";
  const pipeText = data?.pipeText ?? "";
  const setForceStyleAutoApplyVersion = data?.setForceStyleAutoApplyVersion;
  const { open } = useNotification();
  const { durationMinutes, stepMinutes } = useTimelineTimeConfig();
  const [isPlaying, setIsPlaying] = useState<boolean>(false);
  const [playInterval, setPlayInterval] = useState<number>(15000); // 毫秒
  const [calculatedInterval, setCalculatedInterval] =
    useState<number>(stepMinutes); // 分钟
  const [isCalculating, setIsCalculating] = useState<boolean>(false);
  const [sliderPreviewTime, setSliderPreviewTime] = useState<number | null>(null);

  // 计算时间轴范围
  const minTime = timeRange
    ? normalizeTimelineMinutes(
        timeRange.start.getHours() * 60 + timeRange.start.getMinutes(),
        0,
        durationMinutes,
      )
    : 0;
  const maxTime = timeRange
    ? normalizeTimelineMinutes(
        timeRange.end.getHours() * 60 + timeRange.end.getMinutes(),
        0,
        durationMinutes,
      )
    : durationMinutes;
  const timelineCurrentTime = normalizeTimelineMinutes(
    currentTime,
    minTime,
    maxTime,
  );
  const disabledRangePercentages = getTimelineDisabledRangePercentages(
    minTime,
    maxTime,
    durationMinutes,
  );
  useEffect(() => {
    if (schemeDate) {
      setSelectedDate(schemeDate);
    }
  }, [schemeDate, setSelectedDate]);
  // 新增：用于 Draggable 的 nodeRef
  const draggableRef = useRef<HTMLDivElement>(null);

  const intervalRef = useRef<NodeJS.Timeout | null>(null);
  const timelineRef = useRef<HTMLDivElement>(null);
  // 添加缓存引用
  const nodeCacheRef = useRef<Map<string, any[]>>(new Map());
  const linkCacheRef = useRef<Map<string, any[]>>(new Map());
  const frameRequestRevisionRef = useRef(0);
  const frameAbortControllerRef = useRef<AbortController | null>(null);

  const updateDataStates = useCallback(
    (
      nodeResults: any[],
      linkResults: any[],
      target: "primary" | "compare" = "primary"
    ) => {
      const setNodeData =
        target === "compare"
          ? setCompareJunctionCalData
          : setCurrentJunctionCalData;
      const setLinkData =
        target === "compare" ? setComparePipeCalData : setCurrentPipeCalData;

      setNodeData?.(nodeResults);
      setLinkData?.(linkResults);
    },
    [
      setCompareJunctionCalData,
      setComparePipeCalData,
      setCurrentJunctionCalData,
      setCurrentPipeCalData,
    ]
  );

  const buildCacheKey = useCallback(
    (
      queryTime: string,
      property: string,
      sourceType: "scheme" | "realtime",
      resultType: "node" | "link",
      targetSchemeName: string,
      targetSchemeType: string
    ) =>
      [
        queryTime,
        sourceType,
        resultType,
        property,
        targetSchemeName || "default",
        targetSchemeType || "default",
      ].join("::"),
    []
  );

  const fetchDataBySource = useCallback(
    async ({
      queryTime,
      junctionProperties,
      pipeProperties,
      sourceType,
      target,
      schemeName,
      schemeType,
      signal,
    }: {
      queryTime: Date;
      junctionProperties: string;
      pipeProperties: string;
      sourceType: "scheme" | "realtime";
      target: "primary" | "compare";
      schemeName?: string;
      schemeType?: string;
      signal?: AbortSignal;
    }) => {
      const query_time = queryTime.toISOString();
      let nodeRecords: any = { results: [] };
      let linkRecords: any = { results: [] };
      const requests: Promise<Response>[] = [];
      let nodePromise: Promise<Response> | null = null;
      let linkPromise: Promise<Response> | null = null;

      if (junctionProperties !== "" && junctionProperties !== "elevation") {
        const nodeCacheKey = buildCacheKey(
          query_time,
          junctionProperties,
          sourceType,
          "node",
          schemeName || "",
          schemeType || ""
        );
        if (nodeCacheRef.current.has(nodeCacheKey)) {
          nodeRecords = nodeCacheRef.current.get(nodeCacheKey)!;
        } else {
          nodePromise =
            sourceType === "scheme" && schemeName
              ? apiFetch(
                  `${config.BACKEND_URL}/api/v1/timeseries/schemes/records?scheme_type=${schemeType}&scheme_name=${schemeName}&query_time=${query_time}&type=node&property=${junctionProperties}`,
                  { signal },
                )
              : apiFetch(
                  `${config.BACKEND_URL}/api/v1/timeseries/realtime/records?query_time=${query_time}&type=node&property=${junctionProperties}`,
                  { signal },
                );
          requests.push(nodePromise);
        }
      }

      const normalizedPipeProperties =
        pipeProperties === "unit_headloss" ? "headloss" : pipeProperties;

      if (normalizedPipeProperties !== "" && normalizedPipeProperties !== "diameter") {
        const linkCacheKey = buildCacheKey(
          query_time,
          normalizedPipeProperties,
          sourceType,
          "link",
          schemeName || "",
          schemeType || ""
        );
        if (linkCacheRef.current.has(linkCacheKey)) {
          linkRecords = linkCacheRef.current.get(linkCacheKey)!;
        } else {
          linkPromise =
            sourceType === "scheme" && schemeName
              ? apiFetch(
                  `${config.BACKEND_URL}/api/v1/timeseries/schemes/records?scheme_type=${schemeType}&scheme_name=${schemeName}&query_time=${query_time}&type=link&property=${normalizedPipeProperties}`,
                  { signal },
                )
              : apiFetch(
                  `${config.BACKEND_URL}/api/v1/timeseries/realtime/records?query_time=${query_time}&type=link&property=${normalizedPipeProperties}`,
                  { signal },
                );
          requests.push(linkPromise);
        }
      }

      const responses = await Promise.all(requests);

      if (nodePromise) {
        const nodeResponse = responses.shift()!;
        if (!nodeResponse.ok) {
          throw new Error(`Node fetch failed: ${nodeResponse.status}`);
        }
        nodeRecords = await nodeResponse.json();
        nodeCacheRef.current.set(
          buildCacheKey(
            query_time,
            junctionProperties,
            sourceType,
            "node",
            schemeName || "",
            schemeType || ""
          ),
          nodeRecords || []
        );
      }

      if (linkPromise) {
        const linkResponse = responses.shift()!;
        if (!linkResponse.ok) {
          throw new Error(`Link fetch failed: ${linkResponse.status}`);
        }
        linkRecords = await linkResponse.json();
        linkCacheRef.current.set(
          buildCacheKey(
            query_time,
            normalizedPipeProperties,
            sourceType,
            "link",
            schemeName || "",
            schemeType || ""
          ),
          linkRecords || []
        );
      }

      return {
        target,
        nodeResults: nodeRecords.results || [],
        linkResults: linkRecords.results || [],
      };
    },
    [buildCacheKey]
  );

  const fetchFrameData = useCallback(
    async (
      queryTime: Date,
      junctionProperties: string,
      pipeProperties: string,
      schemeName: string,
      schemeType: string
    ) => {
      const revision = frameRequestRevisionRef.current + 1;
      frameRequestRevisionRef.current = revision;
      frameAbortControllerRef.current?.abort();
      const abortController = new AbortController();
      frameAbortControllerRef.current = abortController;
      const primarySourceType =
        disableDateSelection && schemeName ? "scheme" : "realtime";
      const tasks = [
        fetchDataBySource({
          queryTime,
          junctionProperties,
          pipeProperties,
          sourceType: primarySourceType,
          target: "primary",
          schemeName,
          schemeType,
          signal: abortController.signal,
        }),
      ];

      if (isCompareMode && disableDateSelection && schemeName) {
        tasks.push(
          fetchDataBySource({
            queryTime,
            junctionProperties,
            pipeProperties,
            sourceType: "realtime",
            target: "compare",
            signal: abortController.signal,
          })
        );
      }

      try {
        const frames = await Promise.all(tasks);
        if (
          abortController.signal.aborted ||
          revision !== frameRequestRevisionRef.current
        ) {
          return;
        }
        frames.forEach(({ nodeResults, linkResults, target }) => {
          updateDataStates(nodeResults, linkResults, target);
        });
      } catch (error) {
        if ((error as Error).name !== "AbortError") {
          console.error("Timeline frame fetch failed:", error);
        }
      }
    },
    [disableDateSelection, fetchDataBySource, isCompareMode, updateDataStates]
  );

  // 格式化时间显示
  const formatTime = useCallback((minutes: number): string => {
    return formatTimelineTime(minutes, minTime, maxTime);
  }, [maxTime, minTime]);

  const timeMarks = useMemo(() => {
    const marks = [];
    const markInterval = 120;
    for (let value = 0; value <= durationMinutes; value += markInterval) {
      marks.push({
        value,
        label: formatTime(value),
      });
    }
    if (marks.at(-1)?.value !== durationMinutes) {
      marks.push({
        value: durationMinutes,
        label: formatTime(durationMinutes),
      });
    }
    return marks;
  }, [durationMinutes, formatTime]);

  const currentTimeToDate = useCallback((selectedDate: Date, minutes: number): Date => {
    const date = new Date(selectedDate);
    const normalizedMinutes = normalizeTimelineMinutes(minutes, minTime, maxTime);
    const hours = Math.floor(normalizedMinutes / 60);
    const mins = normalizedMinutes % 60;
    date.setHours(hours, mins, 0, 0);
    return date;
  }, [maxTime, minTime]);

  // 播放时间间隔选项
  const intervalOptions = [
    { value: 5000, label: "5秒" },
    { value: 10000, label: "10秒" },
    { value: 15000, label: "15秒" },
    { value: 20000, label: "20秒" },
  ];
  // 强制计算时间段选项
  const resolvedCalculatedIntervalOptions = useMemo(() => {
    const options = BASE_CALCULATED_INTERVAL_OPTIONS.filter(
      (option) => option.value >= stepMinutes,
    );
    if (!options.some((option) => option.value === stepMinutes)) {
      options.push({ value: stepMinutes, label: `${stepMinutes} 分钟` });
    }
    return options.sort((a, b) => b.value - a.value);
  }, [stepMinutes]);

  const advanceTimelineTime = useCallback(
    (previousTime: number, direction: 1 | -1 = 1) => {
      const baseTime = Number.isFinite(previousTime) ? previousTime : minTime;
      let next = baseTime + stepMinutes * direction;
      if (timeRange) {
        if (next > maxTime) next = minTime;
        if (next < minTime) next = maxTime;
      } else {
        if (next > durationMinutes) next = 0;
        if (next < 0) next = durationMinutes;
      }
      return next;
    },
    [durationMinutes, maxTime, minTime, stepMinutes, timeRange],
  );

  // 处理时间轴滑动
  const handleSliderChange = useCallback(
    (event: Event, newValue: number | number[]) => {
      const value = Array.isArray(newValue) ? newValue[0] : newValue;
      // 如果有时间范围限制，只允许在范围内拖动
      if (timeRange && (value < minTime || value > maxTime)) {
        return;
      }
      setSliderPreviewTime(value);
    },
    [timeRange, minTime, maxTime],
  );

  const handleSliderChangeCommitted = useCallback(
    (_event: Event | React.SyntheticEvent, newValue: number | number[]) => {
      const value = Array.isArray(newValue) ? newValue[0] : newValue;
      setSliderPreviewTime(null);
      setCurrentTime(value);
    },
    [setCurrentTime],
  );

  // 播放控制
  const handlePlay = useCallback(() => {
    if (!isPlaying) {
      // if (junctionText === "" && pipeText === "") {
      //   open?.({
      //     type: "error",
      //     message: "请至少设定并应用一个图层的样式。",
      //   });
      // return;
      // }
      setIsPlaying(true);

      intervalRef.current = setInterval(() => {
        setCurrentTime((prev) => {
          return advanceTimelineTime(prev);
        });
      }, playInterval);
    }
  }, [advanceTimelineTime, isPlaying, playInterval, setCurrentTime]);

  const handlePause = useCallback(() => {
    setIsPlaying(false);
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
  }, []);

  const handleStop = useCallback(() => {
    setIsPlaying(false);
    // 设置为当前时间
    setCurrentTime(
      getRoundedCurrentTimelineMinutes(new Date(), stepMinutes, durationMinutes),
    ); // 重置为当前时间
    if (intervalRef.current) {
      clearInterval(intervalRef.current);
      intervalRef.current = null;
    }
  }, [durationMinutes, setCurrentTime, stepMinutes]);

  // 步进控制
  const handleDayStepBackward = useCallback(() => {
    setSelectedDate((prev) => {
      const newDate = new Date(prev);
      newDate.setDate(newDate.getDate() - 1);
      return newDate;
    });
  }, [setSelectedDate]);
  const handleDayStepForward = useCallback(() => {
    setSelectedDate((prev) => {
      const newDate = new Date(prev);
      newDate.setDate(newDate.getDate() + 1);
      return newDate;
    });
  }, [setSelectedDate]);
  const handleStepBackward = useCallback(() => {
    setCurrentTime((prev) => {
      return advanceTimelineTime(prev, -1);
    });
  }, [advanceTimelineTime, setCurrentTime]);

  const handleStepForward = useCallback(() => {
    setCurrentTime((prev) => {
      return advanceTimelineTime(prev);
    });
  }, [advanceTimelineTime, setCurrentTime]);

  // 日期选择处理
  const handleDateChange = useCallback((newDate: Date | null) => {
    if (newDate) {
      setSelectedDate(newDate);
    }
  }, [setSelectedDate]);

  // 播放间隔改变处理
  const handleIntervalChange = useCallback(
    (event: any) => {
      const newInterval = event.target.value;
      setPlayInterval(newInterval);

      // 如果正在播放，重新启动定时器
      if (isPlaying && intervalRef.current) {
        clearInterval(intervalRef.current);
        intervalRef.current = setInterval(() => {
          setCurrentTime((prev) => {
            return advanceTimelineTime(prev);
          });
        }, newInterval);
      }
    },
    [advanceTimelineTime, isPlaying, setCurrentTime],
  );
  // 计算时间段改变处理
  const handleCalculatedIntervalChange = useCallback((event: any) => {
    const newInterval = event.target.value;
    setCalculatedInterval(newInterval);
  }, []);

  useEffect(() => {
    setCalculatedInterval(stepMinutes);
  }, [stepMinutes]);

  // 添加 useEffect 来监听 currentTime 和 selectedDate 的变化，并获取数据
  useEffect(() => {
    // 首次加载时，如果 selectedDate 或 currentTime 未定义，则跳过执行，避免报错
    if (selectedDate && currentTime !== undefined && currentTime !== -1) {
      // 检查至少一个属性有值
      // const junctionProperties = junctionText;
      // const pipeProperties = pipeText;
      // if (junctionProperties === "" && pipeProperties === "") {
      //   open?.({
      //     type: "error",
      //     message: "请至少设定并应用一个图层的样式。",
      //   });
      //   return;
      // }
      fetchFrameData(
        currentTimeToDate(selectedDate, timelineCurrentTime),
        junctionText,
        pipeText,
        schemeName,
        schemeType,
      );
    }
  }, [
    fetchFrameData,
    junctionText,
    pipeText,
    currentTime,
    currentTimeToDate,
    timelineCurrentTime,
    selectedDate,
    schemeName,
    schemeType,
  ]);

  // 组件卸载时清理定时器和防抖
  useEffect(() => {
    // 设置为当前时间
    setCurrentTime(
      getRoundedCurrentTimelineMinutes(new Date(), stepMinutes, durationMinutes),
    ); // 初始化为当前时间

    return () => {
      if (intervalRef.current) {
        clearInterval(intervalRef.current);
      }
      frameAbortControllerRef.current?.abort();
    };
  }, [durationMinutes, setCurrentTime, stepMinutes]);

  // 当 timeRange 改变时，设置 currentTime 到 minTime
  useEffect(() => {
    if (timeRange) {
      setCurrentTime(minTime);
    }
  }, [timeRange, minTime, setCurrentTime]);
  // 获取地图实例
  const map = useMap();
  // 这里防止地图缩放时，瓦片重新加载引起的属性更新出错
  useEffect(() => {
    // 监听地图缩放事件，缩放时停止播放
    if (map) {
      const onZoom = () => {
        handlePause();
      };
      map.getView().on("change:resolution", onZoom);

      // 清理事件监听
      return () => {
        map.getView().un("change:resolution", onZoom);
      };
    }
  }, [map, handlePause]);
  // 清除当天当前时间点后的缓存并重新获取数据
  const clearCacheAndRefetch = (date: Date, timeInMinutes: number) => {
    const dateStr = date.toISOString().split("T")[0];

    const clearCache = (
      cacheRef: ReturnType<typeof useRef<Map<string, any[]>>>,
    ) => {
      if (!cacheRef.current) return;
      const cacheKeys = Array.from(cacheRef.current.keys());
      cacheKeys.forEach((key) => {
        const cacheTimeKey = key.split("::")[0];
        const cacheDate = cacheTimeKey.split("T")[0];
        const cacheTimeStr = cacheTimeKey.split("T")[1];

        if (cacheDate === dateStr && cacheTimeStr) {
          const [hours, minutes] = cacheTimeStr.split(":");
          const cacheTimeInMinutes =
            (parseInt(hours) + 8) * 60 + parseInt(minutes);

          if (cacheTimeInMinutes >= timeInMinutes && cacheRef.current) {
            cacheRef.current.delete(key);
          }
        }
      });
    };

    clearCache(nodeCacheRef);
    clearCache(linkCacheRef);
    // 重新获取当前时刻的新数据
    fetchFrameData(
      currentTimeToDate(selectedDate, timelineCurrentTime),
      junctionText,
      pipeText,
      schemeName,
      schemeType,
    );
  };

  const handleForceCalculate = async () => {
    if (!NETWORK_NAME) {
      open?.({
        type: "error",
        message: "管网名称缺失，无法进行强制计算。",
      });
      return;
    }

    // 提前提取日期和时间值，避免异步操作期间被时间轴拖动改变
    const calculationDate = selectedDate;
    const calculationTime = timelineCurrentTime;
    const calculationDateTime = currentTimeToDate(
      calculationDate,
      calculationTime
    );

    setIsCalculating(true);
    // 显示处理中的通知
    open?.({
      type: "progress",
      message: "正在强制计算，请稍候...",
      undoableTimeout: 3,
    });
    try {
      const body = {
        start_time: dayjs(calculationDateTime).format("YYYY-MM-DDTHH:mm:ssZ"),
        duration: calculatedInterval,
      };

      const response = await apiFetch(
        `${config.BACKEND_URL}/api/v1/simulation-runs`,
        {
          method: "POST",
          headers: {
            "Content-Type": "application/json",
          },
          body: JSON.stringify(body),
        },
      );

      const result = await response.json().catch(() => null);

      if (response.ok && result?.status === "success") {
        open?.({
          type: "success",
          message: "重新计算成功",
        });
        // 清空当天当前时刻及之后的缓存并重新获取数据
        clearCacheAndRefetch(calculationDate, calculationTime);
        setForceStyleAutoApplyVersion?.((prev) => prev + 1);
      } else {
        const errorMessage =
          result?.detail || result?.message || "重新计算失败";
        open?.({
          type: "error",
          message: errorMessage,
        });
      }
    } catch (error) {
      console.error("Recalculation failed:", error);
      open?.({
        type: "error",
        message: "重新计算时发生错误",
      });
    } finally {
      setIsCalculating(false);
    }
  };

  if (!hasTimelineState) {
    return <div>Loading...</div>;
  }

  return (
    <Draggable nodeRef={draggableRef} handle=".drag-handle">
      <div
        ref={draggableRef}
        className="absolute bottom-4 left-1/2 z-20 w-[950px] max-w-[calc(100vw-2rem)] -translate-x-1/2 opacity-90 transition-opacity duration-300 hover:opacity-100"
      >
        <LocalizationProvider dateAdapter={AdapterDayjs} adapterLocale="zh-cn">
          <Paper
            elevation={3}
            sx={{
              position: "absolute",
              bottom: 0,
              left: 0,
              right: 0,
              zIndex: 1000,
              p: 2,
              pt: 1, // 减小顶部内边距，为拖拽柄留出空间
              backgroundColor: "rgba(255, 255, 255, 0.95)",
              backdropFilter: "blur(10px)",
            }}
          >
            {/* 拖拽柄区域 */}
            <Box
              className="drag-handle"
              sx={{
                width: "100%",
                height: "16px",
                display: "flex",
                justifyContent: "center",
                alignItems: "center",
                cursor: "move",
                mb: 1,
                borderRadius: "4px 4px 0 0",
                "&:hover": {
                  backgroundColor: "rgba(0, 0, 0, 0.05)",
                },
              }}
            >
              <Box
                sx={{
                  width: "40px",
                  height: "4px",
                  backgroundColor: "grey.400",
                  borderRadius: "2px",
                }}
              />
            </Box>
            <Box sx={{ width: "100%" }}>
              {/* 控制按钮栏 */}
              <Stack
                direction="row"
                spacing={2}
                alignItems="center"
                sx={{ mb: 2, flexWrap: "wrap", gap: 1 }}
              >
                <Tooltip title="后退一天">
                  <span>
                    <IconButton
                      color="primary"
                      onClick={handleDayStepBackward}
                      size="small"
                      disabled={disableDateSelection}
                      sx={timelineIconButtonSx}
                    >
                      <FiSkipBack />
                    </IconButton>
                  </span>
                </Tooltip>
                {/* 日期选择器 */}
                <DatePicker
                  label="模拟数据日期选择"
                  value={dayjs(selectedDate)}
                  onChange={(value) =>
                    value && handleDateChange(value.toDate())
                  }
                  enableAccessibleFieldDOMStructure={false}
                  format="YYYY-MM-DD"
                  sx={{ width: 180 }}
                  slotProps={{
                    textField: {
                      size: "small",
                    },
                  }}
                  maxDate={dayjs(new Date())} // 禁止选取未来的日期
                  disabled={disableDateSelection}
                />
                <Tooltip title="前进一天">
                  <span>
                    <IconButton
                      color="primary"
                      onClick={handleDayStepForward}
                      size="small"
                      disabled={
                        disableDateSelection ||
                        selectedDate.toDateString() ===
                          new Date().toDateString()
                      }
                      sx={timelineIconButtonSx}
                    >
                      <FiSkipForward />
                    </IconButton>
                  </span>
                </Tooltip>
                {/* 播放控制按钮 */}
                <Box sx={{ display: "flex", gap: 1 }} className="ml-4">
                  {/* 播放间隔选择 */}
                  <FormControl size="small" sx={{ minWidth: 100 }}>
                    <InputLabel>播放间隔</InputLabel>
                    <Select
                      value={playInterval}
                      label="播放间隔"
                      onChange={handleIntervalChange}
                    >
                      {intervalOptions.map((option) => (
                        <MenuItem key={option.value} value={option.value}>
                          {option.label}
                        </MenuItem>
                      ))}
                    </Select>
                  </FormControl>

                  <Tooltip title="后退一步">
                    <IconButton
                      color="primary"
                      onClick={handleStepBackward}
                      size="small"
                      sx={timelineIconButtonSx}
                    >
                      <TbRewindBackward15 />
                    </IconButton>
                  </Tooltip>

                  <Tooltip title={isPlaying ? "暂停" : "播放"}>
                    <IconButton
                      color="primary"
                      onClick={isPlaying ? handlePause : handlePlay}
                      size="small"
                      sx={timelineIconButtonSx}
                    >
                      {isPlaying ? <Pause /> : <PlayArrow />}
                    </IconButton>
                  </Tooltip>

                  <Tooltip title="前进一步">
                    <IconButton
                      color="primary"
                      onClick={handleStepForward}
                      size="small"
                      sx={timelineIconButtonSx}
                    >
                      <TbRewindForward15 />
                    </IconButton>
                  </Tooltip>

                  <Tooltip title="停止">
                    <IconButton
                      color="secondary"
                      onClick={handleStop}
                      size="small"
                      sx={timelineIconButtonSx}
                    >
                      <Stop />
                    </IconButton>
                  </Tooltip>
                </Box>
                {canRunSimulation && (
                  <Box sx={{ display: "flex", gap: 1 }} className="ml-4">
                    <FormControl size="small" sx={{ minWidth: 100 }}>
                      <InputLabel>计算时间段</InputLabel>
                      <Select
                        value={calculatedInterval}
                        label="强制计算时间段"
                        onChange={handleCalculatedIntervalChange}
                      >
                        {resolvedCalculatedIntervalOptions.map((option) => (
                          <MenuItem key={option.value} value={option.value}>
                            {option.label}
                          </MenuItem>
                        ))}
                      </Select>
                    </FormControl>

                    <Tooltip title="强制计算">
                      <Button
                        variant="outlined"
                        startIcon={<Refresh />}
                        onClick={handleForceCalculate}
                        disabled={isCalculating}
                      >
                        强制计算
                      </Button>
                    </Tooltip>
                  </Box>
                )}

                {/* 当前时间显示 */}
                <Typography
                  variant="h6"
                  sx={{
                    ml: "auto",
                    fontWeight: "bold",
                    color: "primary.main",
                  }}
                >
                  {formatTime(timelineCurrentTime)}
                </Typography>
              </Stack>

              <Box ref={timelineRef} sx={{ px: 2, position: "relative" }}>
                <Slider
                  value={sliderPreviewTime ?? timelineCurrentTime}
                  min={0}
                  max={durationMinutes}
                  step={stepMinutes}
                  marks={timeMarks}
                  onChange={handleSliderChange}
                  onChangeCommitted={handleSliderChangeCommitted}
                  valueLabelDisplay="auto"
                  valueLabelFormat={formatTime}
                  sx={{
                    zIndex: 10,
                    height: 8,
                    "& .MuiSlider-track": {
                      backgroundColor: "primary.main",
                      height: 6,
                      display: timeRange ? "none" : "block",
                    },
                    "& .MuiSlider-rail": {
                      backgroundColor: "grey.300",
                      height: 6,
                    },
                    "& .MuiSlider-thumb": {
                      height: 20,
                      width: 20,
                      backgroundColor: "primary.main",
                      border: "2px solid #fff",
                      boxShadow: "0 2px 8px rgba(0,0,0,0.2)",
                      "&:hover": {
                        boxShadow: "0 4px 12px rgba(0,0,0,0.3)",
                      },
                    },
                    "& .MuiSlider-mark": {
                      backgroundColor: "grey.400",
                      height: 4,
                      width: 2,
                    },
                    "& .MuiSlider-markActive": {
                      backgroundColor: "primary.main",
                    },
                    "& .MuiSlider-markLabel": {
                      fontSize: "0.75rem",
                      color: "grey.600",
                    },
                  }}
                />
                {/* 禁用区域遮罩 */}
                {timeRange && (
                  <Box
                    sx={{
                      position: "absolute",
                      left: 16,
                      right: 16,
                      top: "30%",
                      transform: "translateY(-50%)",
                      height: "20px",
                      pointerEvents: "none",
                    }}
                  >
                    {/* 左侧禁用区域 */}
                    {minTime > 0 && (
                      <Box
                        sx={{
                          position: "absolute",
                          left: 0,
                          width: `${disabledRangePercentages.leftWidth}%`,
                          height: "100%",
                          backgroundColor: "rgba(189, 189, 189, 0.4)",
                          backdropFilter: "blur(1px)",
                          borderRadius: "2.5px",
                        }}
                      />
                    )}
                    {/* 右侧禁用区域 */}
                    {maxTime < durationMinutes && (
                      <Box
                        sx={{
                          position: "absolute",
                          left: `${disabledRangePercentages.rightLeft}%`,
                          width: `${disabledRangePercentages.rightWidth}%`,
                          height: "100%",
                          backgroundColor: "rgba(189, 189, 189, 0.4)",
                          backdropFilter: "blur(1px)",
                          borderRadius: "2.5px",
                        }}
                      />
                    )}
                  </Box>
                )}
              </Box>
            </Box>
          </Paper>
        </LocalizationProvider>
      </div>
    </Draggable>
  );
};

export default Timeline;
