"use client";

import React, { useCallback, useEffect, useMemo, useState } from "react";
import {
  Box,
  Button,
  Chip,
  CircularProgress,
  Divider,
  IconButton,
  Paper,
  Stack,
  Tab,
  Tabs,
  Tooltip,
  Typography,
  Collapse,
} from "@mui/material";
import {
  Close,
  Refresh,
  ShowChart,
  TableChart,
  ExpandLess,
  ExpandMore,
} from "@mui/icons-material";
import { DataGrid, GridColDef } from "@mui/x-data-grid";
import { LineChart } from "@mui/x-charts";
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 clsx from "clsx";
import config from "@/config/config";
import { GeoJSON } from "ol/format";

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

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;
  /** 可选：关闭浮窗的回调 */
  onClose?: () => void;
  /** 默认展示的选项卡 */
  defaultTab?: "chart" | "table";
  /** Y 轴数值的小数位数 */
  fractionDigits?: number;
}

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 url = `${config.backendUrl}/querycleaningscadadatabydeviceidandtimerange/?ids=${ids}&starttime=${starttime}&endtime=${endtime}`;

  try {
    const response = await fetch(url);
    if (!response.ok) {
      throw new Error(`HTTP error! status: ${response.status}`);
    }
    const data = await response.json();
    return transformBackendData(data, deviceIds);
  } catch (error) {
    console.error("[SCADADataPanel] 从后端获取数据失败:", error);
    throw error;
  }
};

/**
 * 转换后端数据格式
 * 根据实际后端返回的数据结构进行调整
 */
const transformBackendData = (
  backendData: any,
  deviceIds: string[]
): TimeSeriesPoint[] => {
  // 处理后端返回的对象格式: { deviceId: [{time: "...", value: ...}] }
  if (
    backendData &&
    typeof backendData === "object" &&
    !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;
    }
  }

  // 如果后端返回的是数组格式，每个元素包含时间戳和各设备值
  if (Array.isArray(backendData)) {
    return backendData.map((item: any) => ({
      timestamp: item.timestamp || item.time || item._time,
      values: deviceIds.reduce<Record<string, number | null>>((acc, id) => {
        acc[id] = item[id] ?? item.values?.[id] ?? null;
        return acc;
      }, {}),
    }));
  }

  // 如果后端返回的是对象格式，包含 timestamps 和 data
  if (backendData && backendData.timestamps && backendData.data) {
    return backendData.timestamps.map((timestamp: string, index: number) => {
      const values = deviceIds.reduce<Record<string, number | null>>(
        (acc, id) => {
          acc[id] = backendData.data[id]?.[index] ?? null;
          return acc;
        },
        {}
      );
      return { timestamp, values };
    });
  }

  // 默认返回空数组
  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
) => {
  return points.map((point) => {
    const entry: Record<string, any> = {
      time: dayjs(point.timestamp).toDate(),
      label: formatTimestamp(point.timestamp),
    };

    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,
  onClose,
  defaultTab = "chart",
  fractionDigits = 2,
}) => {
  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>>({});

  // 获取 SCADA 设备信息，生成 deviceLabels
  useEffect(() => {
    const fetchDeviceLabels = async () => {
      try {
        const url = `${config.mapUrl}/TJWater/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=TJWater: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),
    [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 fetchTimeSeriesData(deviceIds, {
          from: rangeFrom.toDate(),
          to: rangeTo.toDate(),
        });
        setTimeSeries(result);
        setLoadingState("success");
        console.debug(
          `[SCADADataPanel] 数据刷新成功 (${reason})，共 ${result.length} 条记录。`
        );
      } catch (err) {
        console.error("[SCADADataPanel] 获取时序数据失败", err);
        setError(err instanceof Error ? err.message : "未知错误");
        setLoadingState("error");
      }
    },
    [deviceIds, fetchTimeSeriesData, hasDevices, normalizedRange]
  );

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

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

    const dynamic = 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]);

  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: 420,
        }}
      >
        <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", // 靛蓝色
    ];

    return (
      <Box sx={{ width: "100%", height: 420 }}>
        <LineChart
          dataset={dataset}
          height={420}
          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={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: "#f5f5f5",
              strokeWidth: 1,
              strokeDasharray: "3 3",
            },
          }}
          slotProps={{
            legend: {
              direction: "row",
              position: { horizontal: "middle", vertical: "bottom" },
              padding: { top: 20, bottom: 10, 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>
    );
  };

  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: "420px",
          "& .MuiDataGrid-cell": {
            borderColor: "#f0f0f0",
          },
          "& .MuiDataGrid-columnHeaders": {
            backgroundColor: "#fafafa",
            fontWeight: 600,
            fontSize: "0.875rem",
          },
          "& .MuiDataGrid-row:hover": {
            backgroundColor: "#f5f5f5",
          },
          "& .MuiDataGrid-columnHeaderTitle": {
            fontWeight: 600,
          },
        }}
        disableRowSelectionOnClick
      />
    );
  };

  return (
    <Paper
      className={clsx(
        "absolute right-4 top-20 bg-white rounded-xl shadow-lg overflow-hidden flex flex-col transition-all duration-300",
        visible ? "opacity-95 hover:opacity-100" : "opacity-0 -z-10"
      )}
      sx={{
        width: "min(920px, calc(100vw - 2rem))",
        maxHeight: "calc(100vh - 100px)",
      }}
    >
      {/* 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(!isExpanded)}
                sx={{ color: "primary.contrastText" }}
              >
                {isExpanded ? <ExpandLess /> : <ExpandMore />}
              </IconButton>
            </Tooltip>
            <Tooltip title="关闭">
              <IconButton
                size="small"
                onClick={onClose}
                sx={{ color: "primary.contrastText" }}
              >
                <Close fontSize="small" />
              </IconButton>
            </Tooltip>
          </Stack>
        </Stack>
      </Box>

      <Collapse in={isExpanded}>
        {/* Controls */}
        <Box sx={{ p: 2, backgroundColor: "grey.50" }}>
          <LocalizationProvider dateAdapter={AdapterDayjs}>
            <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>
                <Tooltip title="刷新数据">
                  <span>
                    <Button
                      variant="contained"
                      size="small"
                      color="primary"
                      startIcon={<Refresh fontSize="small" />}
                      disabled={!hasDevices || loadingState === "loading"}
                      onClick={() => handleFetch("manual")}
                    >
                      刷新
                    </Button>
                  </span>
                </Tooltip>
              </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>
      </Collapse>
    </Paper>
  );
};

export default SCADADataPanel;
