"use client";

import React, {
  useCallback,
  useEffect,
  useMemo,
  useRef,
  useState,
} from "react";
import Draggable from "react-draggable";

import {
  Box,
  Button,
  Chip,
  CircularProgress,
  Divider,
  Stack,
  Tab,
  Tabs,
  Tooltip,
  Typography,
} from "@mui/material";
import { Refresh, ShowChart, TableChart } 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";

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

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

export interface SCADADataPanelProps {
  /** 选中的要素信息列表，格式为 [[id, type], [id, type]] */
  featureInfos: [string, string][];
  /** 数据类型: realtime-查询模拟值和监测值, none-仅查询监测值, scheme-查询策略模拟值和监测值 */
  type?: "realtime" | "scheme" | "none";
  /** 策略类型 */
  scheme_type?: string;
  /** 策略名称 */
  scheme_name?: string;
  /** 默认展示的选项卡 */
  defaultTab?: "chart" | "table";
  /** Y 轴数值的小数位数 */
  fractionDigits?: number;
}

type PanelTab = "chart" | "table";

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

/**
 * 从后端 API 获取 SCADA 数据
 */
const fetchFromBackend = async (
  featureInfos: [string, string][],
  range: { from: Date; to: Date },
  type: "realtime" | "scheme" | "none",
  scheme_type?: string,
  scheme_name?: string
): Promise<TimeSeriesPoint[]> => {
  if (featureInfos.length === 0) {
    return [];
  }

  // 提取设备 ID 列表
  const featureIds = featureInfos.map(([id]) => id);

  const feature_ids = featureIds.join(",");
  const start_time = dayjs(range.from).toISOString();
  const end_time = dayjs(range.to).toISOString();

  // 将 featureInfos 转换为后端期望的格式: id1:type1,id2:type2
  const feature_infos = featureInfos
    .map(([id, type]) => `${id}:${type}`)
    .join(",");

  // 监测值数据接口（use_cleaned=false）
  const rawDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-scada?element_id=${feature_ids}&start_time=${start_time}&end_time=${end_time}&use_cleaned=false`;
  // 清洗数据接口（use_cleaned=true）
  const cleanedDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-scada?element_id=${feature_ids}&start_time=${start_time}&end_time=${end_time}&use_cleaned=true`;
  // 模拟数据接口
  const simulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-simulation?feature_infos=${feature_infos}&start_time=${start_time}&end_time=${end_time}`;
  // 策略模拟数据接口
  const schemeSimulationDataUrl = `${config.BACKEND_URL}/api/v1/composite/element-simulation?feature_infos=${feature_infos}&start_time=${start_time}&end_time=${end_time}&scheme_type=${scheme_type}&scheme_name=${scheme_name}`;

  try {
    if (type === "none") {
      // 查询清洗值和监测值
      const [cleanedRes, rawRes] = await Promise.all([
        fetch(cleanedDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
        fetch(rawDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
      ]);

      const cleanedData = transformBackendData(cleanedRes, featureIds);
      // 如果清洗数据有值，则不显示原始监测值
      const rawData =
        cleanedData.length > 0 ? [] : transformBackendData(rawRes, featureIds);

      return mergeTimeSeriesData(
        cleanedData,
        rawData,
        featureIds,
        "clean",
        "raw"
      );
    } else if (type === "scheme") {
      // 查询策略模拟值、清洗值和监测值
      const [cleanedRes, rawRes, schemeSimRes] = await Promise.all([
        fetch(cleanedDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
        fetch(rawDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
        fetch(schemeSimulationDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
      ]);

      const cleanedData = transformBackendData(cleanedRes, featureIds);
      // 如果清洗数据有值，则不显示原始监测值
      const rawData =
        cleanedData.length > 0 ? [] : transformBackendData(rawRes, featureIds);
      const schemeSimData = transformBackendData(schemeSimRes, featureIds);

      // 合并三组数据
      const timeMap = new Map<string, Record<string, number | null>>();

      [cleanedData, rawData, schemeSimData].forEach((data, index) => {
        const suffix = ["clean", "raw", "scheme_sim"][index];
        data.forEach((point) => {
          if (!timeMap.has(point.timestamp)) {
            timeMap.set(point.timestamp, {});
          }
          const values = timeMap.get(point.timestamp)!;
          featureIds.forEach((deviceId) => {
            const value = point.values[deviceId];
            if (value !== undefined) {
              values[`${deviceId}_${suffix}`] = value;
            }
          });
        });
      });

      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;
    } else {
      // realtime: 查询模拟值、清洗值和监测值
      const [cleanedRes, rawRes, simulationRes] = await Promise.all([
        fetch(cleanedDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
        fetch(rawDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
        fetch(simulationDataUrl)
          .then((r) => (r.ok ? r.json() : null))
          .catch(() => null),
      ]);

      const cleanedData = transformBackendData(cleanedRes, featureIds);
      // 如果清洗数据有值，则不显示原始监测值
      const rawData =
        cleanedData.length > 0 ? [] : transformBackendData(rawRes, featureIds);
      const simulationData = transformBackendData(simulationRes, featureIds);

      // 合并三组数据
      const timeMap = new Map<string, Record<string, number | null>>();

      [cleanedData, rawData, simulationData].forEach((data, index) => {
        const suffix = ["clean", "raw", "sim"][index];
        data.forEach((point) => {
          if (!timeMap.has(point.timestamp)) {
            timeMap.set(point.timestamp, {});
          }
          const values = timeMap.get(point.timestamp)!;
          featureIds.forEach((deviceId) => {
            const value = point.values[deviceId];
            if (value !== undefined) {
              values[`${deviceId}_${suffix}`] = value;
            }
          });
        });
      });

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

/**
 * 转换后端数据格式
 * 根据实际后端返回的数据结构进行调整
 */
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
) => {
  return points.map((point) => {
    const entry: Record<string, any> = {
      time: dayjs(point.timestamp).toDate(),
      label: formatTimestamp(point.timestamp),
    };

    deviceIds.forEach((id) => {
      ["clean", "raw", "sim", "scheme_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> = ({
  featureInfos,
  type = "none",
  scheme_type = "burst_Analysis",
  scheme_name,
  defaultTab = "chart",
  fractionDigits = 2,
}) => {
  // 从 featureInfos 中提取设备 ID 列表
  const deviceIds = useMemo(
    () => featureInfos.map(([id]) => id),
    [featureInfos]
  );

  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 [selectedSource, setSelectedSource] = useState<
    "raw" | "clean" | "sim" | "all"
  >(() => (featureInfos.length === 1 ? "all" : "clean"));
  const draggableRef = useRef<HTMLDivElement>(null);

  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),
    [timeSeries, deviceIds, fractionDigits]
  );

  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 fetchFromBackend(
          featureInfos,
          {
            from: rangeFrom.toDate(),
            to: rangeTo.toDate(),
          },
          type,
          scheme_type,
          scheme_name
        );
        setTimeSeries(result);
        setLoadingState("success");
      } catch (err) {
        setError(err instanceof Error ? err.message : "未知错误");
        setLoadingState("error");
      }
    },
    [featureInfos, hasDevices, normalizedRange, type, scheme_type, scheme_name]
  );

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

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

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

    const dynamic = (() => {
      const cols: GridColDef[] = [];

      deviceIds.forEach((id) => {
        // 为每个设备的每种数据类型创建列
        const suffixes = [
          { key: "clean", name: "清洗值" },
          { key: "raw", name: "监测值" },
          { key: "sim", name: "模拟值" },
          { key: "scheme_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: `${id} (${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, 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 = () => {
      return deviceIds.flatMap((id, index) => {
        const series = [];
        ["clean", "raw", "sim", "scheme_sim"].forEach((suffix, sIndex) => {
          const key = `${id}_${suffix}`;
          const hasData = dataset.some(
            (item) => item[key] !== null && item[key] !== undefined
          );
          if (hasData) {
            const displayName =
              suffix === "clean"
                ? "清洗值"
                : suffix === "raw"
                ? "监测值"
                : suffix === "sim"
                ? "模拟"
                : "方案模拟";

            series.push({
              name: `${id} (${displayName})`,
              type: "line",
              symbol: "none",
              sampling: "lttb",
              connectNulls: true,
              itemStyle: {
                color: colors[(index * 4 + sIndex) % colors.length],
              },
              data: dataset.map((item) => item[key]),
              areaStyle: {
                color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                  {
                    offset: 0,
                    color: colors[(index * 4 + sIndex) % colors.length],
                  },
                  {
                    offset: 1,
                    color: "rgba(255, 255, 255, 0)",
                  },
                ]),
                opacity: 0.3,
              },
            });
          }
        });
        // 如果没有任何数据，则使用fallback
        if (series.length === 0) {
          series.push({
            name: id,
            type: "line",
            symbol: "none",
            sampling: "lttb",
            connectNulls: true,
            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}
        localeText={zhCN.components.MuiDataGrid.defaultProps.localeText}
        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 (
    <>
      {/* 主面板 */}
      <Draggable nodeRef={draggableRef} handle=".drag-handle">
        <Box
          ref={draggableRef}
          sx={{
            position: "absolute",
            right: "1rem",
            top: "1rem",
            width: "min(920px, calc(100vw - 2rem))",
            maxWidth: "100vw",
            height: "860px",
            maxHeight: "calc(100vh - 2rem)",
            boxSizing: "border-box",
            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: "opacity 0.3s ease-in-out",
            border: "none",
            display: "flex",
            flexDirection: "column",
            zIndex: 1300,
            backgroundColor: "white",
            overflow: "hidden",
            "&:hover": {
              opacity: 1,
            },
          }}
        >
          <Box
            className="flex flex-col h-full rounded-xl"
            sx={{ height: "100%", width: "100%" }}
          >
            {/* Header */}
            <Box
              className="drag-handle"
              sx={{
                p: 2,
                borderBottom: 1,
                borderColor: "divider",
                backgroundColor: "primary.main",
                color: "primary.contrastText",
                cursor: "move",
              }}
            >
              <Stack
                direction="row"
                alignItems="center"
                justifyContent="space-between"
              >
                <Stack direction="row" spacing={1} alignItems="center">
                  <ShowChart fontSize="small" />
                  <Typography variant="h6" sx={{ fontWeight: "bold" }}>
                    历史数据
                  </Typography>
                  <Chip
                    size="small"
                    label={`${featureInfos.length}`}
                    sx={{
                      backgroundColor: "rgba(255,255,255,0.2)",
                      color: "primary.contrastText",
                      fontWeight: "bold",
                    }}
                  />
                </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}>
                      <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>
                </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>
        </Box>
      </Draggable>
    </>
  );
};

export default SCADADataPanel;
