"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  Box,
  Button,
  Chip,
  CircularProgress,
  Divider,
  IconButton,
  Stack,
  Tab,
  Tabs,
  Tooltip,
  Typography,
  Drawer,
} from "@mui/material";
import {
  Refresh,
  ShowChart,
  TableChart,
  CleaningServices,
  ChevronLeft,
  ChevronRight,
} from "@mui/icons-material";
import { DataGrid, GridColDef } from "@mui/x-data-grid";
import { zhCN } from "@mui/x-data-grid/locales";
import ReactECharts from "echarts-for-react";
import * as echarts from "echarts";
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 { zhCN as pickerZhCN } from "@mui/x-date-pickers/locales";
import config from "@/config/config";
import { useGetIdentity } from "@refinedev/core";
import { useNotification } from "@refinedev/core";
import { api } from "@/lib/api";
import { apiFetch } from "@/lib/apiFetch";

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

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

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

export interface SCADADataPanelProps {
  /** 选中的设备 ID 列表 */
  deviceIds: string[];
  /** 可选：控制浮窗显示 */
  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 device_ids = deviceIds.join(",");
  const start_time = dayjs(range.from).toISOString();
  const end_time = dayjs(range.to).toISOString();
  // 清洗数据接口
  const cleaningDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`;
  // 原始数据
  const rawDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`;
  // 模拟数据接口
  const simulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`;
  try {
    // 优先查询清洗数据和模拟数据
    const [cleaningRes, simulationRes] = await Promise.all([
      apiFetch(cleaningDataUrl)
        .then((r) => (r.ok ? r.json() : null))
        .catch(() => null),
      apiFetch(simulationDataUrl)
        .then((r) => (r.ok ? r.json() : null))
        .catch(() => null),
    ]);

    const cleaningData = transformBackendData(cleaningRes, deviceIds);
    const simulationData = transformBackendData(simulationRes, deviceIds);

    // 如果清洗数据有数据，返回清洗和模拟数据
    if (cleaningData.length > 0) {
      return mergeTimeSeriesData(
        cleaningData,
        simulationData,
        deviceIds,
        "clean",
        "sim",
      );
    } else {
      // 如果清洗数据没有数据，查询原始数据，返回模拟和原始数据
      const rawRes = await apiFetch(rawDataUrl)
        .then((r) => (r.ok ? r.json() : null))
        .catch(() => null);
      const rawData = transformBackendData(rawRes, deviceIds);
      return mergeTimeSeriesData(
        simulationData,
        rawData,
        deviceIds,
        "sim",
        "raw",
      );
    }
  } 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 mergeTimeSeriesData = (
  data1: TimeSeriesPoint[],
  data2: TimeSeriesPoint[],
  deviceIds: string[],
  suffix1: string,
  suffix2: string,
): TimeSeriesPoint[] => {
  const timeMap = new Map<string, Record<string, number | null>>();

  const processData = (data: TimeSeriesPoint[], suffix: string) => {
    data.forEach((point) => {
      if (!timeMap.has(point.timestamp)) {
        timeMap.set(point.timestamp, {});
      }
      const values = timeMap.get(point.timestamp)!;
      deviceIds.forEach((deviceId) => {
        const value = point.values[deviceId];
        if (value !== undefined) {
          values[`${deviceId}_${suffix}`] = value;
        }
      });
    });
  };

  processData(data1, suffix1);
  processData(data2, suffix2);

  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;
};

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) => {
        ["raw", "clean", "sim"].forEach((suffix) => {
          const key = `${id}_${suffix}`;
          const value = point.values[key];
          if (value !== undefined && value !== null) {
            entry[key] =
              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,
  visible = true,
  defaultTab = "chart",
  fractionDigits = 2,
  showCleaning = false,
  onCleanData,
}) => {
  const { open } = useNotification();
  const { data: user } = useGetIdentity<IUser>();

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

    return async (
      deviceIds: string[],
      range: { from: Date; to: Date },
    ): Promise<TimeSeriesPoint[]> => {
      const device_ids = deviceIds.join(",");
      const start_time = dayjs(range.from).toISOString();
      const end_time = dayjs(range.to).toISOString();

      // 清洗数据接口
      const cleaningDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=cleaned_value&start_time=${start_time}&end_time=${end_time}`;
      // 原始数据
      const rawDataUrl = `${config.BACKEND_URL}/api/v1/scada/by-ids-field-time-range?device_ids=${device_ids}&field=monitored_value&start_time=${start_time}&end_time=${end_time}`;
      // 模拟数据接口
      const simulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/scada-simulation?device_ids=${device_ids}&start_time=${start_time}&end_time=${end_time}`;
      try {
        const [cleanRes, rawRes, simRes] = await Promise.all([
          apiFetch(cleaningDataUrl)
            .then((r) => (r.ok ? r.json() : null))
            .catch(() => null),
          apiFetch(rawDataUrl)
            .then((r) => (r.ok ? r.json() : null))
            .catch(() => null),
          apiFetch(simulationDataUrl)
            .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]);

  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 [isCleaning, setIsCleaning] = useState<boolean>(false);
  const [selectedSource, setSelectedSource] = useState<
    "raw" | "clean" | "sim" | "all"
  >(() => (deviceIds.length === 1 ? "all" : "clean"));

  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 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.id) {
      open?.({
        type: "error",
        message: "用户信息无效，请重新登录",
      });
      return;
    }

    setIsCleaning(true);

    try {
      const { from: rangeFrom, to: rangeTo } = normalizedRange;
      const startTime = dayjs(rangeFrom).toISOString();
      const endTime = dayjs(rangeTo).toISOString();

      // 调用后端清洗接口
      const response = await api.post(
        `${
          config.BACKEND_URL
        }/api/v1/composite/clean-scada?device_ids=${deviceIds.join(
          ",",
        )}&start_time=${startTime}&end_time=${endTime}`,
      );

      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");
    }
  }, [deviceIds.length, selectedSource]);

  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: `${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: `${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: `${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: 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 {
        // 非清洗模式：显示所有设备的所有有数据的列
        const cols: GridColDef[] = [];

        deviceIds.forEach((id) => {
          const deviceName = id;

          // 为每个设备的每种数据类型创建列
          const suffixes = [
            { key: "raw", name: "原始值" },
            { key: "clean", name: "清洗值" },
            { key: "sim", name: "模拟值" },
          ];

          suffixes.forEach(({ key, name }) => {
            const fieldKey = `${id}_${key}`;
            // 检查是否有该字段的数据
            const hasData = dataset.some(
              (item) => item[fieldKey] !== null && item[fieldKey] !== undefined,
            );

            if (hasData) {
              cols.push({
                field: fieldKey,
                headerName: `${deviceName} (${name})`,
                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 cols;
      }
    })();

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

  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 xData = dataset.map((item) => item.label);

    const getSeries = () => {
      if (showCleaning) {
        if (selectedSource === "all") {
          return deviceIds.flatMap((id, index) => [
            {
              name: `${id} (原始)`,
              type: "line",
              symbol: "none",
              connectNulls: true,
              sampling: "lttb",
              itemStyle: { color: colors[index % colors.length] },
              data: dataset.map((item) => item[`${id}_raw`]),
            },
            {
              name: `${id} (清洗)`,
              type: "line",
              symbol: "none",
              connectNulls: true,
              sampling: "lttb",
              itemStyle: { color: colors[(index + 3) % colors.length] },
              data: dataset.map((item) => item[`${id}_clean`]),
            },
            {
              name: `${id} (模拟)`,
              type: "line",
              symbol: "none",
              connectNulls: true,
              sampling: "lttb",
              itemStyle: { color: colors[(index + 6) % colors.length] },
              data: dataset.map((item) => item[`${id}_sim`]),
            },
          ]);
        } else {
          return deviceIds.map((id, index) => ({
            name: id,
            type: "line",
            symbol: "none",
            connectNulls: true,
            sampling: "lttb",
            itemStyle: { color: colors[index % colors.length] },
            data: dataset.map((item) => item[`${id}_${selectedSource}`]),
          }));
        }
      } else {
        return deviceIds.flatMap((id, index) => {
          const series = [];
          ["raw", "clean", "sim"].forEach((suffix, sIndex) => {
            const key = `${id}_${suffix}`;
            const hasData = dataset.some(
              (item) => item[key] !== null && item[key] !== undefined,
            );
            if (hasData) {
              series.push({
                name: `${id} (${
                  suffix === "raw"
                    ? "原始"
                    : suffix === "clean"
                    ? "清洗"
                    : "模拟"
                })`,
                type: "line",
                symbol: "none",
                connectNulls: true,
                sampling: "lttb",
                itemStyle: {
                  color: colors[(index * 3 + sIndex) % colors.length],
                },
                data: dataset.map((item) => item[key]),
                areaStyle: {
                  color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                    {
                      offset: 0,
                      color: colors[(index * 3 + sIndex) % colors.length],
                    },
                    {
                      offset: 1,
                      color: "rgba(255, 255, 255, 0)",
                    },
                  ]),
                  opacity: 0.3,
                },
              });
            }
          });
          // 如果没有clean/raw/sim数据，则使用fallback
          if (series.length === 0) {
            series.push({
              name: id,
              type: "line",
              symbol: "none",
              connectNulls: true,
              sampling: "lttb",
              itemStyle: { color: colors[index % colors.length] },
              data: dataset.map((item) => item[id]),
              areaStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  {
                    offset: 0,
                    color: colors[index % colors.length],
                  },
                  {
                    offset: 1,
                    color: "rgba(255, 255, 255, 0)",
                  },
                ]),
                opacity: 0.3,
              },
            });
          }
          return series;
        });
      }
    };

    const option = {
      // animation: false,
      animationDuration: 500,
      tooltip: {
        trigger: "axis",
        confine: true,
        position: function (pt: any[]) {
          return [pt[0], "10%"];
        },
      },
      legend: {
        top: "top",
      },
      grid: {
        left: "5%",
        right: "5%",
        bottom: "11%",
        containLabel: true,
      },
      toolbox: {
        feature: {
          dataZoom: {
            yAxisIndex: "none",
          },
          restore: {},
          saveAsImage: {},
        },
      },
      xAxis: {
        type: "category",
        boundaryGap: false,
        data: xData,
      },
      yAxis: {
        type: "value",
        scale: true,
      },
      dataZoom: [
        {
          type: "inside",
          start: 0,
          end: 100,
        },
        {
          start: 0,
          end: 100,
        },
      ],
      series: getSeries(),
    };

    return (
      <Box
        sx={{
          width: "100%",
          height: "100%",
          display: "flex",
          flexDirection: "column",
          overflow: "hidden",
        }}
      >
        <ReactECharts
          option={option}
          style={{ height: "100%", width: "100%" }}
          notMerge={true}
          lazyUpdate={true}
        />
      </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}
        localeText={zhCN.components.MuiDataGrid.defaultProps.localeText}
        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"
              localeText={
                pickerZhCN.components.MuiLocalizationProvider.defaultProps
                  .localeText
              }
            >
              <Stack spacing={1.5}>
                <Stack direction="row" spacing={1} alignItems="center">
                  <DateTimePicker
                    label="开始时间"
                    value={from}
                    onChange={(value) => {
                      if (value && dayjs.isDayjs(value) && value.isValid()) {
                        setFrom(value);
                      }
                    }}
                    onAccept={(value) => {
                      if (
                        value &&
                        dayjs.isDayjs(value) &&
                        value.isValid() &&
                        hasDevices
                      ) {
                        handleFetch("date-change");
                      }
                    }}
                    maxDateTime={to}
                    slotProps={{
                      textField: { fullWidth: true, size: "small" },
                    }}
                  />
                  <DateTimePicker
                    label="结束时间"
                    value={to}
                    onChange={(value) => {
                      if (value && dayjs.isDayjs(value) && value.isValid()) {
                        setTo(value);
                      }
                    }}
                    onAccept={(value) => {
                      if (
                        value &&
                        dayjs.isDayjs(value) &&
                        value.isValid() &&
                        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;
