"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  Box,
  Button,
  Chip,
  CircularProgress,
  Divider,
  IconButton,
  Stack,
  Tab,
  Tabs,
  Tooltip,
  Typography,
  Drawer,
  Slider,
} from "@mui/material";
import {
  Refresh,
  ShowChart,
  TableChart,
  CleaningServices,
  ChevronLeft,
  ChevronRight,
} from "@mui/icons-material";
import { DataGrid, GridColDef } from "@mui/x-data-grid";
import { LineChart } from "@mui/x-charts";
import "dayjs/locale/zh-cn"; // 引入中文包
import dayjs, { Dayjs } from "dayjs";
import utc from "dayjs/plugin/utc";
import timezone from "dayjs/plugin/timezone";
import { AdapterDayjs } from "@mui/x-date-pickers/AdapterDayjs";
import { DateTimePicker, LocalizationProvider } from "@mui/x-date-pickers";
import config, { NETWORK_NAME } from "@/config/config";
import { GeoJSON } from "ol/format";
import { useGetIdentity } from "@refinedev/core";
import { useNotification } from "@refinedev/core";
import axios from "axios";

dayjs.extend(utc);
dayjs.extend(timezone);

type IUser = {
  id: number;
  name: string;
};

export interface TimeSeriesPoint {
  /** ISO8601 时间戳 */
  timestamp: string;
  /** 每个设备对应的值 */
  values: Record<string, number | null | undefined>;
}

export interface SCADADataPanelProps {
  /** 选中的设备 ID 列表 */
  deviceIds: string[];
  /** 自定义数据获取器，默认使用后端 API */
  fetchTimeSeriesData?: (
    deviceIds: string[],
    range: { from: Date; to: Date }
  ) => Promise<TimeSeriesPoint[]>;
  /** 可选：控制浮窗显示 */
  visible?: boolean;
  /** 默认展示的选项卡 */
  defaultTab?: "chart" | "table";
  /** Y 轴数值的小数位数 */
  fractionDigits?: number;
  /** 是否显示清洗功能 */
  showCleaning?: boolean;
  /** 清洗数据的回调 */
  onCleanData?: () => void;
}

type PanelTab = "chart" | "table";

type LoadingState = "idle" | "loading" | "success" | "error";

/**
 * 从后端 API 获取 SCADA 数据
 */
const fetchFromBackend = async (
  deviceIds: string[],
  range: { from: Date; to: Date }
): Promise<TimeSeriesPoint[]> => {
  if (deviceIds.length === 0) {
    return [];
  }

  const ids = deviceIds.join(",");
  const starttime = dayjs(range.from).format("YYYY-MM-DD HH:mm:ss");
  const endtime = dayjs(range.to).format("YYYY-MM-DD HH:mm:ss");
  // 清洗数据接口
  const cleaningSCADAUrl = `${config.BACKEND_URL}/querycleaningscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
  // 原始数据
  const rawSCADAUrl = `${config.BACKEND_URL}/queryscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
  // 模拟数据接口
  const simulationSCADAUrl = `${config.BACKEND_URL}/querysimulationscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
  try {
    let response;
    response = await fetch(cleaningSCADAUrl);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    let transformedData = transformBackendData(data, deviceIds);

    // 如果清洗数据接口返回空结果，使用原始数据接口
    if (transformedData.length === 0) {
      console.log("[SCADADataPanel] 清洗数据接口无结果，使用原始数据接口");
      response = await fetch(rawSCADAUrl);
      if (!response.ok) {
        throw new Error(`HTTP error! status: ${response.status}`);
      }
      const data = await response.json();
      transformedData = transformBackendData(data, deviceIds);
    }
    return transformedData;
  } catch (error) {
    console.error("[SCADADataPanel] 从后端获取数据失败:", error);
    throw error;
  }
};

/**
 * 转换后端数据格式
 * 根据实际后端返回的数据结构进行调整
 */
const transformBackendData = (
  backendData: any,
  deviceIds: string[]
): TimeSeriesPoint[] => {
  // 处理后端返回的对象格式: { deviceId: [{time: "...", value: ...}] }
  if (backendData && !Array.isArray(backendData)) {
    // 检查是否是设备ID为键的对象格式
    const hasDeviceKeys = deviceIds.some((id) => id in backendData);

    if (hasDeviceKeys) {
      // 获取所有时间点的集合
      const timeMap = new Map<string, Record<string, number | null>>();

      deviceIds.forEach((deviceId) => {
        const deviceData = backendData[deviceId];
        if (Array.isArray(deviceData)) {
          deviceData.forEach((item: any) => {
            const timestamp = item.time || item.timestamp || item._time;
            if (timestamp) {
              if (!timeMap.has(timestamp)) {
                timeMap.set(timestamp, {});
              }
              const values = timeMap.get(timestamp)!;
              values[deviceId] =
                typeof item.value === "number" ? item.value : null;
            }
          });
        }
      });

      // 转换为 TimeSeriesPoint 数组并按时间排序
      const result = Array.from(timeMap.entries()).map(
        ([timestamp, values]) => ({
          timestamp,
          values,
        })
      );

      result.sort(
        (a, b) =>
          new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
      );

      return result;
    }
  }
  // 默认返回空数组
  console.warn("[SCADADataPanel] 未知的后端数据格式:", backendData);
  return [];
};

const defaultFetcher = fetchFromBackend;

const formatTimestamp = (timestamp: string) =>
  dayjs(timestamp).tz("Asia/Shanghai").format("YYYY-MM-DD HH:mm");

const ensureValidRange = (
  from: Dayjs,
  to: Dayjs
): { from: Dayjs; to: Dayjs } => {
  if (from.isAfter(to)) {
    return { from: to, to: from };
  }
  return { from, to };
};

const buildDataset = (
  points: TimeSeriesPoint[],
  deviceIds: string[],
  fractionDigits: number,
  showCleaning: boolean
) => {
  return points.map((point) => {
    const entry: Record<string, any> = {
      time: dayjs(point.timestamp).toDate(),
      label: formatTimestamp(point.timestamp),
    };

    if (showCleaning) {
      deviceIds.forEach((id) => {
        ["raw", "clean", "sim"].forEach((suffix) => {
          const key = `${id}_${suffix}`;
          const value = point.values[key];
          entry[key] =
            typeof value === "number"
              ? Number.isFinite(value)
                ? parseFloat(value.toFixed(fractionDigits))
                : null
              : value ?? null;
        });
      });
    } else {
      deviceIds.forEach((id) => {
        const value = point.values[id];
        entry[id] =
          typeof value === "number"
            ? Number.isFinite(value)
              ? parseFloat(value.toFixed(fractionDigits))
              : null
            : value ?? null;
      });
    }

    return entry;
  });
};

const emptyStateMessages: Record<
  PanelTab,
  { title: string; subtitle: string }
> = {
  chart: {
    title: "暂无时序数据",
    subtitle: "请切换时间段来获取曲线",
  },
  table: {
    title: "暂无表格数据",
    subtitle: "请切换时间段来获取记录",
  },
};

const SCADADataPanel: React.FC<SCADADataPanelProps> = ({
  deviceIds,
  fetchTimeSeriesData = defaultFetcher,
  visible = true,
  defaultTab = "chart",
  fractionDigits = 2,
  showCleaning = false,
  onCleanData,
}) => {
  const { open } = useNotification();
  const { data: user } = useGetIdentity<IUser>();

  const customFetcher = useMemo(() => {
    if (!showCleaning) {
      return fetchTimeSeriesData;
    }

    return async (
      deviceIds: string[],
      range: { from: Date; to: Date }
    ): Promise<TimeSeriesPoint[]> => {
      const ids = deviceIds.join(",");
      const starttime = dayjs(range.from).format("YYYY-MM-DD HH:mm:ss");
      const endtime = dayjs(range.to).format("YYYY-MM-DD HH:mm:ss");

      const cleaningUrl = `${config.BACKEND_URL}/querycleaningscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
      const rawUrl = `${config.BACKEND_URL}/queryscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;
      const simUrl = `${config.BACKEND_URL}/querysimulationscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;

      try {
        const [cleanRes, rawRes, simRes] = await Promise.all([
          fetch(cleaningUrl)
            .then((r) => (r.ok ? r.json() : null))
            .catch(() => null),
          fetch(rawUrl)
            .then((r) => (r.ok ? r.json() : null))
            .catch(() => null),
          fetch(simUrl)
            .then((r) => (r.ok ? r.json() : null))
            .catch(() => null),
        ]);

        const timeMap = new Map<string, Record<string, number | null>>();

        const processData = (data: any, suffix: string) => {
          if (!data) return;
          deviceIds.forEach((deviceId) => {
            const deviceData = data[deviceId];
            if (Array.isArray(deviceData)) {
              deviceData.forEach((item: any) => {
                const timestamp = item.time || item.timestamp || item._time;
                if (timestamp) {
                  if (!timeMap.has(timestamp)) {
                    timeMap.set(timestamp, {});
                  }
                  const values = timeMap.get(timestamp)!;
                  values[`${deviceId}_${suffix}`] =
                    typeof item.value === "number" ? item.value : null;
                }
              });
            }
          });
        };

        processData(cleanRes, "clean");
        processData(rawRes, "raw");
        processData(simRes, "sim");

        const result = Array.from(timeMap.entries()).map(
          ([timestamp, values]) => ({
            timestamp,
            values,
          })
        );

        result.sort(
          (a, b) =>
            new Date(a.timestamp).getTime() - new Date(b.timestamp).getTime()
        );

        return result;
      } catch (error) {
        console.error("[SCADADataPanel] 获取三种数据失败:", error);
        throw error;
      }
    };
  }, [showCleaning, fetchTimeSeriesData]);

  const [from, setFrom] = useState<Dayjs>(() => dayjs().subtract(1, "day"));
  const [to, setTo] = useState<Dayjs>(() => dayjs());
  const [activeTab, setActiveTab] = useState<PanelTab>(defaultTab);
  const [timeSeries, setTimeSeries] = useState<TimeSeriesPoint[]>([]);
  const [loadingState, setLoadingState] = useState<LoadingState>("idle");
  const [error, setError] = useState<string | null>(null);
  const [isExpanded, setIsExpanded] = useState<boolean>(true);
  const [deviceLabels, setDeviceLabels] = useState<Record<string, string>>({});
  const [isCleaning, setIsCleaning] = useState<boolean>(false);
  const [selectedSource, setSelectedSource] = useState<
    "raw" | "clean" | "sim" | "all"
  >("all");

  // 滑块状态：用于图表缩放
  const [zoomRange, setZoomRange] = useState<[number, number]>([0, 100]);

  // 获取 SCADA 设备信息，生成 deviceLabels
  useEffect(() => {
    const fetchDeviceLabels = async () => {
      try {
        const url = `${config.MAP_URL}/${config.MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${config.MAP_WORKSPACE}:geo_scada&outputFormat=application/json`;
        const response = await fetch(url);
        if (!response.ok) return;

        const json = await response.json();
        const features = new GeoJSON().readFeatures(json);

        const labels = features.reduce<Record<string, string>>(
          (acc, feature) => {
            const id = feature.get("id") || feature.getId();
            const name = feature.get("name") || id;
            acc[id] = name;
            return acc;
          },
          {}
        );

        setDeviceLabels(labels);
      } catch (error) {
        console.error("[SCADADataPanel] 获取设备标签失败:", error);
      }
    };

    fetchDeviceLabels();
  }, []);

  useEffect(() => {
    setActiveTab(defaultTab);
  }, [defaultTab]);

  const normalizedRange = useMemo(() => ensureValidRange(from, to), [from, to]);

  const hasDevices = deviceIds.length > 0;
  const hasData = timeSeries.length > 0;

  const dataset = useMemo(
    () => buildDataset(timeSeries, deviceIds, fractionDigits, showCleaning),
    [timeSeries, deviceIds, fractionDigits, showCleaning]
  );

  // 根据滑块范围过滤数据集
  const filteredDataset = useMemo(() => {
    if (dataset.length === 0) return dataset;

    const startIndex = Math.floor((zoomRange[0] / 100) * dataset.length);
    const endIndex = Math.ceil((zoomRange[1] / 100) * dataset.length);

    return dataset.slice(startIndex, endIndex);
  }, [dataset, zoomRange]);

  // 重置滑块范围当数据变化时
  useEffect(() => {
    setZoomRange([0, 100]);
  }, [timeSeries]);

  const handleFetch = useCallback(
    async (reason: string) => {
      if (!hasDevices) {
        setTimeSeries([]);
        setLoadingState("idle");
        setError(null);
        return;
      }

      setLoadingState("loading");
      setError(null);
      try {
        const { from: rangeFrom, to: rangeTo } = normalizedRange;
        const result = await customFetcher(deviceIds, {
          from: rangeFrom.toDate(),
          to: rangeTo.toDate(),
        });
        setTimeSeries(result);
        setLoadingState("success");
      } catch (err) {
        setError(err instanceof Error ? err.message : "未知错误");
        setLoadingState("error");
      }
    },
    [deviceIds, customFetcher, hasDevices, normalizedRange]
  );

  // 处理数据清洗
  const handleCleanData = useCallback(async () => {
    if (!hasDevices) {
      open?.({
        type: "error",
        message: "请先选择设备",
      });
      return;
    }

    if (!user || !user.name) {
      open?.({
        type: "error",
        message: "用户信息无效，请重新登录",
      });
      return;
    }

    setIsCleaning(true);

    try {
      const { from: rangeFrom, to: rangeTo } = normalizedRange;
      const startTime = dayjs(rangeFrom).format("YYYY-MM-DD HH:mm:ss");
      const endTime = dayjs(rangeTo).format("YYYY-MM-DD HH:mm:ss");

      // 调用后端清洗接口
      const response = await axios.post(
        `${config.BACKEND_URL}/scadadevicedatacleaning/`,
        null,
        {
          params: {
            network: NETWORK_NAME,
            ids_list: deviceIds.join(","), // 修改：将数组转为逗号分隔字符串
            start_time: startTime,
            end_time: endTime,
            user_name: user.name,
          },
        }
      );

      console.log("[SCADADataPanel] 清洗响应:", response.data);

      // 处理成功响应
      if (response.data === "success" || response.data?.success === true) {
        open?.({
          type: "success",
          message: "数据清洗成功",
          description: `已完成 ${deviceIds.length} 个设备的数据清洗`,
        });

        // 清洗完成后自动刷新数据
        await handleFetch("after-cleaning");

        // 如果父组件提供了回调，也调用它
        onCleanData?.();
      } else {
        throw new Error(response.data?.message || "清洗失败");
      }
    } catch (err: any) {
      console.error("[SCADADataPanel] 数据清洗失败:", err);
      open?.({
        type: "error",
        message: "数据清洗失败",
        description: err.response?.data?.message || err.message || "未知错误",
      });
    } finally {
      setIsCleaning(false);
    }
  }, [
    deviceIds,
    hasDevices,
    normalizedRange,
    user,
    open,
    onCleanData,
    handleFetch,
  ]);

  // 设备变化时自动查询
  useEffect(() => {
    if (hasDevices) {
      handleFetch("device-change");
    } else {
      setTimeSeries([]);
    }
  }, [deviceIds.join(",")]);

  // 当设备数量变化时，调整数据源选择
  useEffect(() => {
    if (deviceIds.length > 1 && selectedSource === "all") {
      setSelectedSource("clean");
    }
    // else if (deviceIds.length === 1 && selectedSource !== "all") {
    //   setSelectedSource("all");
    // }
  }, [deviceIds.length]);

  const columns: GridColDef[] = useMemo(() => {
    const base: GridColDef[] = [
      {
        field: "label",
        headerName: "时间",
        minWidth: 180,
        flex: 1,
      },
    ];

    const dynamic = (() => {
      if (showCleaning) {
        if (selectedSource === "all") {
          // 全部模式：显示所有设备的三种数据
          return deviceIds.flatMap<GridColDef>((id) => [
            {
              field: `${id}_raw`,
              headerName: `${deviceLabels?.[id] ?? id} (原始)`,
              minWidth: 140,
              flex: 1,
              valueFormatter: (value: any) => {
                if (value === null || value === undefined) return "--";
                if (Number.isFinite(Number(value))) {
                  return Number(value).toFixed(fractionDigits);
                }
                return String(value);
              },
            },
            {
              field: `${id}_clean`,
              headerName: `${deviceLabels?.[id] ?? id} (清洗)`,
              minWidth: 140,
              flex: 1,
              valueFormatter: (value: any) => {
                if (value === null || value === undefined) return "--";
                if (Number.isFinite(Number(value))) {
                  return Number(value).toFixed(fractionDigits);
                }
                return String(value);
              },
            },
            {
              field: `${id}_sim`,
              headerName: `${deviceLabels?.[id] ?? id} (模拟)`,
              minWidth: 140,
              flex: 1,
              valueFormatter: (value: any) => {
                if (value === null || value === undefined) return "--";
                if (Number.isFinite(Number(value))) {
                  return Number(value).toFixed(fractionDigits);
                }
                return String(value);
              },
            },
          ]);
        } else {
          // 单一数据源模式：只显示选中的数据源
          return deviceIds.map<GridColDef>((id) => ({
            field: `${id}_${selectedSource}`,
            headerName: deviceLabels?.[id] ?? id,
            minWidth: 140,
            flex: 1,
            valueFormatter: (value: any) => {
              if (value === null || value === undefined) return "--";
              if (Number.isFinite(Number(value))) {
                return Number(value).toFixed(fractionDigits);
              }
              return String(value);
            },
          }));
        }
      } else {
        return deviceIds.map<GridColDef>((id) => ({
          field: id,
          headerName: deviceLabels?.[id] ?? id,
          minWidth: 140,
          flex: 1,
          valueFormatter: (value: any) => {
            if (value === null || value === undefined) return "--";
            if (Number.isFinite(Number(value))) {
              return Number(value).toFixed(fractionDigits);
            }
            return String(value);
          },
        }));
      }
    })();

    return [...base, ...dynamic];
  }, [deviceIds, deviceLabels, fractionDigits, showCleaning, selectedSource]);

  const rows = useMemo(
    () =>
      dataset.map((item, index) => ({
        id: `${
          item.time instanceof Date ? item.time.getTime() : index
        }-${index}`,
        ...item,
      })),
    [dataset]
  );

  const renderEmpty = () => {
    const message = emptyStateMessages[activeTab];
    return (
      <Box
        sx={{
          flex: 1,
          display: "flex",
          flexDirection: "column",
          alignItems: "center",
          justifyContent: "center",
          py: 8,
          color: "text.secondary",
          height: "100%",
        }}
      >
        <ShowChart sx={{ fontSize: 64, mb: 2, opacity: 0.3 }} />
        <Typography variant="h6" gutterBottom sx={{ fontWeight: 500 }}>
          {message.title}
        </Typography>
        <Typography variant="body2" color="text.secondary">
          {message.subtitle}
        </Typography>
      </Box>
    );
  };

  const renderChart = () => {
    if (!hasData) return renderEmpty();

    // 为每个设备生成独特的颜色和样式
    const colors = [
      "#1976d2", // 蓝色
      "#dc004e", // 粉红色
      "#ff9800", // 橙色
      "#4caf50", // 绿色
      "#9c27b0", // 紫色
      "#00bcd4", // 青色
      "#f44336", // 红色
      "#8bc34a", // 浅绿色
      "#ff5722", // 深橙色
      "#3f51b5", // 靛蓝色
    ];

    // 获取当前显示范围的时间边界
    const getTimeRangeLabel = () => {
      if (filteredDataset.length === 0) return "";
      const firstTime = filteredDataset[0].time;
      const lastTime = filteredDataset[filteredDataset.length - 1].time;
      if (firstTime instanceof Date && lastTime instanceof Date) {
        return `${dayjs(firstTime).format("MM-DD HH:mm")} ~ ${dayjs(
          lastTime
        ).format("MM-DD HH:mm")}`;
      }
      return "";
    };

    return (
      <Box
        sx={{
          width: "100%",
          height: "100%",
          display: "flex",
          flexDirection: "column",
        }}
      >
        <Box sx={{ flex: 1 }}>
          <LineChart
            dataset={filteredDataset}
            height={480}
            margin={{ left: 70, right: 40, top: 30, bottom: 90 }}
            xAxis={[
              {
                dataKey: "time",
                scaleType: "time",
                valueFormatter: (value) =>
                  value instanceof Date
                    ? dayjs(value).format("MM-DD HH:mm")
                    : String(value),
                tickLabelStyle: {
                  angle: -45,
                  textAnchor: "end",
                  fontSize: 11,
                  fill: "#666",
                },
              },
            ]}
            yAxis={[
              {
                label: "压力/流量值",
                labelStyle: {
                  fontSize: 13,
                  fill: "#333",
                  fontWeight: 500,
                },
                tickLabelStyle: {
                  fontSize: 11,
                  fill: "#666",
                },
              },
            ]}
            series={(() => {
              if (showCleaning) {
                if (selectedSource === "all") {
                  // 全部模式：显示所有设备的三种数据
                  return deviceIds.flatMap((id, index) => [
                    {
                      dataKey: `${id}_raw`,
                      label: `${deviceLabels?.[id] ?? id} (原始)`,
                      showMark: dataset.length < 50,
                      curve: "catmullRom",
                      color: colors[index % colors.length],
                      valueFormatter: (value: number | null) =>
                        value !== null ? value.toFixed(fractionDigits) : "--",
                      area: false,
                      stack: undefined,
                    },
                    {
                      dataKey: `${id}_clean`,
                      label: `${deviceLabels?.[id] ?? id} (清洗)`,
                      showMark: dataset.length < 50,
                      curve: "catmullRom",
                      color: colors[(index + 3) % colors.length],
                      valueFormatter: (value: number | null) =>
                        value !== null ? value.toFixed(fractionDigits) : "--",
                      area: false,
                      stack: undefined,
                    },
                    {
                      dataKey: `${id}_sim`,
                      label: `${deviceLabels?.[id] ?? id} (模拟)`,
                      showMark: dataset.length < 50,
                      curve: "catmullRom",
                      color: colors[(index + 6) % colors.length],
                      valueFormatter: (value: number | null) =>
                        value !== null ? value.toFixed(fractionDigits) : "--",
                      area: false,
                      stack: undefined,
                    },
                  ]);
                } else {
                  // 单一数据源模式：只显示选中的数据源
                  return deviceIds.map((id, index) => ({
                    dataKey: `${id}_${selectedSource}`,
                    label: deviceLabels?.[id] ?? id,
                    showMark: dataset.length < 50,
                    curve: "catmullRom",
                    color: colors[index % colors.length],
                    valueFormatter: (value: number | null) =>
                      value !== null ? value.toFixed(fractionDigits) : "--",
                    area: false,
                    stack: undefined,
                  }));
                }
              } else {
                return deviceIds.map((id, index) => ({
                  dataKey: id,
                  label: deviceLabels?.[id] ?? id,
                  showMark: dataset.length < 50,
                  curve: "catmullRom",
                  color: colors[index % colors.length],
                  valueFormatter: (value: number | null) =>
                    value !== null ? value.toFixed(fractionDigits) : "--",
                  area: false,
                  stack: undefined,
                }));
              }
            })()}
            grid={{ vertical: true, horizontal: true }}
            sx={{
              "& .MuiLineElement-root": {
                strokeWidth: 2.5,
                strokeLinecap: "round",
                strokeLinejoin: "round",
              },
              "& .MuiMarkElement-root": {
                scale: "0.8",
                strokeWidth: 2,
              },
              "& .MuiChartsAxis-line": {
                stroke: "#e0e0e0",
                strokeWidth: 1,
              },
              "& .MuiChartsAxis-tick": {
                stroke: "#e0e0e0",
                strokeWidth: 1,
              },
              "& .MuiChartsGrid-line": {
                stroke: "#d0d0d0",
                strokeWidth: 0.8,
                strokeDasharray: "4 4",
              },
            }}
            slotProps={{
              legend: {
                direction: "row",
                position: { horizontal: "middle", vertical: "bottom" },
                padding: { bottom: 2, left: 0, right: 0 },
                itemMarkWidth: 16,
                itemMarkHeight: 3,
                markGap: 8,
                itemGap: 16,
                labelStyle: {
                  fontSize: 12,
                  fill: "#333",
                  fontWeight: 500,
                },
              },
              loadingOverlay: {
                style: { backgroundColor: "rgba(255, 255, 255, 0.7)" },
              },
            }}
            tooltip={{
              trigger: "axis",
            }}
          />
        </Box>

        {/* 时间范围滑块 */}
        <Box sx={{ px: 3, pb: 2, pt: 1 }}>
          <Stack direction="row" spacing={2} alignItems="center">
            <Typography
              variant="body2"
              sx={{ minWidth: 60, color: "text.secondary", fontSize: "0.8rem" }}
            >
              时间范围
            </Typography>
            <Slider
              value={zoomRange}
              onChange={(_, newValue) =>
                setZoomRange(newValue as [number, number])
              }
              valueLabelDisplay="auto"
              valueLabelFormat={(value) => {
                const index = Math.floor((value / 100) * dataset.length);
                if (dataset[index] && dataset[index].time instanceof Date) {
                  return dayjs(dataset[index].time).format("MM-DD HH:mm");
                }
                return `${value}%`;
              }}
              marks={[
                {
                  value: 0,
                  label:
                    dataset.length > 0 && dataset[0].time instanceof Date
                      ? dayjs(dataset[0].time).format("MM-DD HH:mm")
                      : "起始",
                },
                {
                  value: 100,
                  label:
                    dataset.length > 0 &&
                    dataset[dataset.length - 1].time instanceof Date
                      ? dayjs(dataset[dataset.length - 1].time).format(
                          "MM-DD HH:mm"
                        )
                      : "结束",
                },
              ]}
              sx={{
                flex: 1,
                "& .MuiSlider-thumb": {
                  width: 16,
                  height: 16,
                },
                "& .MuiSlider-markLabel": {
                  fontSize: "0.7rem",
                  color: "text.secondary",
                },
              }}
            />
            <Button
              size="small"
              variant="outlined"
              onClick={() => setZoomRange([0, 100])}
              sx={{ minWidth: 60, fontSize: "0.75rem" }}
            >
              重置
            </Button>
          </Stack>
          {getTimeRangeLabel() && (
            <Typography
              variant="caption"
              sx={{
                color: "primary.main",
                display: "block",
                textAlign: "center",
                mt: 0.5,
              }}
            >
              当前显示: {getTimeRangeLabel()} (共 {filteredDataset.length}{" "}
              个数据点)
            </Typography>
          )}
        </Box>
      </Box>
    );
  };

  const renderTable = () => {
    if (!hasData) return renderEmpty();

    console.debug("[SCADADataPanel] 表格数据:", {
      rowsCount: rows.length,
      columnsCount: columns.length,
      sampleRow: rows[0],
      columns: columns.map((c) => c.field),
    });

    return (
      <DataGrid
        rows={rows}
        columns={columns}
        columnBufferPx={100}
        initialState={{
          pagination: {
            paginationModel: { pageSize: 50, page: 0 },
          },
        }}
        pageSizeOptions={[25, 50, 100]}
        sx={{
          border: "none",
          height: "100%",
          "& .MuiDataGrid-cell": {
            borderColor: "#f0f0f0",
          },
          "& .MuiDataGrid-columnHeaders": {
            backgroundColor: "#fafafa",
            fontWeight: 600,
            fontSize: "0.875rem",
          },
          "& .MuiDataGrid-row:hover": {
            backgroundColor: "#f5f5f5",
          },
          "& .MuiDataGrid-columnHeaderTitle": {
            fontWeight: 600,
          },
        }}
        disableRowSelectionOnClick
      />
    );
  };

  return (
    <>
      {/* 收起时的触发按钮 */}
      {!isExpanded && hasDevices && (
        <Box
          className="absolute top-20 right-4 bg-white shadow-2xl rounded-lg cursor-pointer hover:shadow-xl transition-all duration-300 opacity-95 hover:opacity-100"
          onClick={() => setIsExpanded(true)}
          sx={{ zIndex: 1300 }}
        >
          <Box className="flex flex-col items-center py-3 px-3 gap-1">
            <ShowChart className="text-[#257DD4] w-5 h-5" />
            <Typography
              variant="caption"
              className="text-gray-700 font-semibold my-1 text-xs"
              style={{ writingMode: "vertical-rl" }}
            >
              历史数据
            </Typography>
            <ChevronLeft className="text-gray-600 w-4 h-4" />
          </Box>
        </Box>
      )}

      {/* 主面板 */}
      <Drawer
        anchor="right"
        open={isExpanded && visible}
        variant="persistent"
        hideBackdrop
        sx={{
          width: 0,
          flexShrink: 0,
          "& .MuiDrawer-paper": {
            width: "min(920px, calc(100vw - 2rem))",
            boxSizing: "border-box",
            position: "absolute",
            top: 80,
            right: 16,
            height: "860px",
            borderRadius: "12px",
            boxShadow:
              "0 20px 25px -5px rgba(0, 0, 0, 0.1), 0 10px 10px -5px rgba(0, 0, 0, 0.04)",
            backdropFilter: "blur(8px)",
            opacity: 0.95,
            transition: "transform 0.3s ease-in-out, opacity 0.3s ease-in-out",
            border: "none",
            "&:hover": {
              opacity: 1,
            },
          },
        }}
      >
        <Box className="flex flex-col h-full bg-white rounded-xl overflow-hidden">
          {/* Header */}
          <Box
            sx={{
              p: 2,
              borderBottom: 1,
              borderColor: "divider",
              backgroundColor: "primary.main",
              color: "primary.contrastText",
            }}
          >
            <Stack
              direction="row"
              alignItems="center"
              justifyContent="space-between"
            >
              <Stack direction="row" spacing={1} alignItems="center">
                <ShowChart fontSize="small" />
                <Typography variant="h6" sx={{ fontWeight: "bold" }}>
                  SCADA 历史数据
                </Typography>
                <Chip
                  size="small"
                  label={`${deviceIds.length}`}
                  sx={{
                    backgroundColor: "rgba(255,255,255,0.2)",
                    color: "primary.contrastText",
                    fontWeight: "bold",
                  }}
                />
              </Stack>
              <Stack direction="row" spacing={1}>
                <Tooltip title="收起">
                  <IconButton
                    size="small"
                    onClick={() => setIsExpanded(false)}
                    sx={{ color: "primary.contrastText" }}
                  >
                    <ChevronRight fontSize="small" />
                  </IconButton>
                </Tooltip>
              </Stack>
            </Stack>
          </Box>

          {/* Controls */}
          <Box sx={{ p: 2, backgroundColor: "grey.50" }}>
            <LocalizationProvider
              dateAdapter={AdapterDayjs}
              adapterLocale="zh-cn"
            >
              <Stack spacing={1.5}>
                <Stack direction="row" spacing={1} alignItems="center">
                  <DateTimePicker
                    label="开始时间"
                    value={from}
                    onChange={(value) =>
                      value && dayjs.isDayjs(value) && setFrom(value)
                    }
                    onAccept={(value) => {
                      if (value && dayjs.isDayjs(value) && hasDevices) {
                        handleFetch("date-change");
                      }
                    }}
                    maxDateTime={to}
                    slotProps={{
                      textField: { fullWidth: true, size: "small" },
                    }}
                  />
                  <DateTimePicker
                    label="结束时间"
                    value={to}
                    onChange={(value) =>
                      value && dayjs.isDayjs(value) && setTo(value)
                    }
                    onAccept={(value) => {
                      if (value && dayjs.isDayjs(value) && hasDevices) {
                        handleFetch("date-change");
                      }
                    }}
                    minDateTime={from}
                    slotProps={{
                      textField: { fullWidth: true, size: "small" },
                    }}
                  />
                </Stack>
                <Stack
                  direction="row"
                  spacing={1}
                  alignItems="center"
                  justifyContent="space-between"
                >
                  <Tabs
                    value={activeTab}
                    onChange={(_, value: PanelTab) => setActiveTab(value)}
                    variant="fullWidth"
                  >
                    <Tab
                      value="chart"
                      icon={<ShowChart fontSize="small" />}
                      iconPosition="start"
                      label="曲线"
                    />
                    <Tab
                      value="table"
                      icon={<TableChart fontSize="small" />}
                      iconPosition="start"
                      label="表格"
                    />
                  </Tabs>
                  <Stack direction="row" spacing={1}>
                    {showCleaning && (
                      <Tooltip title="清洗数据">
                        <span>
                          <Button
                            variant="outlined"
                            size="small"
                            color="secondary"
                            startIcon={
                              isCleaning ? (
                                <CircularProgress size={16} />
                              ) : (
                                <CleaningServices fontSize="small" />
                              )
                            }
                            disabled={
                              !hasDevices ||
                              loadingState === "loading" ||
                              isCleaning
                            }
                            onClick={handleCleanData}
                          >
                            {isCleaning ? "清洗中..." : "清洗"}
                          </Button>
                        </span>
                      </Tooltip>
                    )}
                    <Tooltip title="刷新数据">
                      <span>
                        <Button
                          variant="outlined"
                          size="small"
                          color="primary"
                          startIcon={<Refresh fontSize="small" />}
                          disabled={!hasDevices || loadingState === "loading"}
                          onClick={() => handleFetch("manual")}
                        >
                          刷新
                        </Button>
                      </span>
                    </Tooltip>
                  </Stack>
                </Stack>
                {showCleaning && hasDevices && (
                  <Stack direction="row" spacing={1} alignItems="center">
                    <Typography variant="body2" sx={{ fontWeight: 500 }}>
                      数据源:
                    </Typography>
                    <Tabs
                      value={selectedSource}
                      onChange={(_, value: "raw" | "clean" | "sim" | "all") =>
                        setSelectedSource(value)
                      }
                    >
                      {deviceIds.length === 1 && (
                        <Tab value="all" label="全部" />
                      )}
                      <Tab value="clean" label="清洗" />
                      <Tab value="raw" label="原始" />
                      <Tab value="sim" label="模拟" />
                    </Tabs>
                  </Stack>
                )}
              </Stack>
            </LocalizationProvider>

            {!hasDevices && (
              <Typography
                variant="caption"
                color="warning.main"
                sx={{ mt: 1, display: "block" }}
              >
                未选择任何设备，无法获取数据。
              </Typography>
            )}
            {error && (
              <Typography
                variant="caption"
                color="error"
                sx={{ mt: 1, display: "block" }}
              >
                获取数据失败：{error}
              </Typography>
            )}
          </Box>

          <Divider />

          {/* Content */}
          <Box sx={{ flex: 1, position: "relative", p: 2, overflow: "auto" }}>
            {loadingState === "loading" && (
              <Box
                sx={{
                  position: "absolute",
                  inset: 0,
                  backgroundColor: "rgba(255,255,255,0.6)",
                  display: "flex",
                  alignItems: "center",
                  justifyContent: "center",
                  zIndex: 1,
                }}
              >
                <CircularProgress size={48} />
              </Box>
            )}

            {activeTab === "chart" ? renderChart() : renderTable()}
          </Box>
        </Box>
      </Drawer>
    </>
  );
};

export default SCADADataPanel;
