"use client";
import { config } from "@/config/config";
import React, {
  createContext,
  useContext,
  useState,
  useEffect,
  useRef,
} from "react";
import { Map as OlMap, VectorTile } from "ol";
import View from "ol/View.js";
import "ol/ol.css";
import MapTools from "./MapTools";

// 导入 DeckLayer
import { DeckLayer } from "@utils/layers";
import VectorTileSource from "ol/source/VectorTile";
import WebGLVectorTileLayer from "ol/layer/WebGLVectorTile";
import MVT from "ol/format/MVT";
import { FlatStyleLike } from "ol/style/flat";
import { toLonLat } from "ol/proj";
import { along, bearing, lineString, length, toMercator } from "@turf/turf";
import { Deck } from "@deck.gl/core";
import { TextLayer } from "@deck.gl/layers";
import { TripsLayer } from "@deck.gl/geo-layers";
import { CollisionFilterExtension } from "@deck.gl/extensions";
import VectorSource from "ol/source/Vector";
import GeoJson from "ol/format/GeoJSON";
import VectorLayer from "ol/layer/Vector";
import { Icon, Style } from "ol/style.js";
import { FeatureLike } from "ol/Feature";
import { Point } from "ol/geom";
import { ContourLayer } from "deck.gl";

interface MapComponentProps {
  children?: React.ReactNode;
}
interface DataContextType {
  currentTime?: number; // 当前时间
  setCurrentTime?: React.Dispatch<React.SetStateAction<number>>;
  selectedDate?: Date; // 选择的日期
  schemeName?: string; // 当前方案名称
  setSchemeName?: React.Dispatch<React.SetStateAction<string>>;
  setSelectedDate?: React.Dispatch<React.SetStateAction<Date>>;
  currentJunctionCalData?: any[]; // 当前计算结果
  setCurrentJunctionCalData?: React.Dispatch<React.SetStateAction<any[]>>;
  currentPipeCalData?: any[]; // 当前计算结果
  setCurrentPipeCalData?: React.Dispatch<React.SetStateAction<any[]>>;
  showJunctionText?: boolean; // 是否显示节点文本
  showPipeText?: boolean; // 是否显示管道文本
  showJunctionId?: boolean; // 是否显示节点ID
  showPipeId?: boolean; // 是否显示管道ID
  setShowJunctionTextLayer?: React.Dispatch<React.SetStateAction<boolean>>;
  setShowPipeTextLayer?: React.Dispatch<React.SetStateAction<boolean>>;
  setShowJunctionId?: React.Dispatch<React.SetStateAction<boolean>>;
  setShowPipeId?: React.Dispatch<React.SetStateAction<boolean>>;
  setShowContourLayer?: React.Dispatch<React.SetStateAction<boolean>>;
  isContourLayerAvailable?: boolean;
  setShowWaterflowLayer?: React.Dispatch<React.SetStateAction<boolean>>;
  setContourLayerAvailable?: React.Dispatch<React.SetStateAction<boolean>>;
  isWaterflowLayerAvailable?: boolean;
  setWaterflowLayerAvailable?: React.Dispatch<React.SetStateAction<boolean>>;
  junctionText: string;
  pipeText: string;
  setJunctionText?: React.Dispatch<React.SetStateAction<string>>;
  setPipeText?: React.Dispatch<React.SetStateAction<string>>;
  setContours?: React.Dispatch<React.SetStateAction<any[]>>;
  deckLayer?: DeckLayer;
  diameterRange?: [number, number];
  elevationRange?: [number, number];
}

// 跨组件传递
const MapContext = createContext<OlMap | undefined>(undefined);
const DataContext = createContext<DataContextType | undefined>(undefined);

const MAP_EXTENT = config.MAP_EXTENT as [number, number, number, number];
const MAP_URL = config.MAP_URL;
const MAP_WORKSPACE = config.MAP_WORKSPACE;
const MAP_VIEW_STORAGE_KEY = `${MAP_WORKSPACE}_map_view`; // 持久化 key
// 添加防抖函数
function debounce<F extends (...args: any[]) => any>(func: F, waitFor: number) {
  let timeout: ReturnType<typeof setTimeout> | null = null;

  return (...args: Parameters<F>): void => {
    if (timeout !== null) {
      clearTimeout(timeout);
    }
    timeout = setTimeout(() => func(...args), waitFor);
  };
}

export const useMap = () => {
  return useContext(MapContext);
};
export const useData = () => {
  return useContext(DataContext);
};

const MapComponent: React.FC<MapComponentProps> = ({ children }) => {
  const mapRef = useRef<HTMLDivElement | null>(null);
  const deckLayerRef = useRef<DeckLayer | null>(null);

  const [map, setMap] = useState<OlMap>();
  const [deckLayer, setDeckLayer] = useState<DeckLayer>();
  // currentCalData 用于存储当前计算结果
  const [currentTime, setCurrentTime] = useState<number>(-1); // 默认选择当前时间
  // const [selectedDate, setSelectedDate] = useState<Date>(new Date("2025-9-17"));
  const [selectedDate, setSelectedDate] = useState<Date>(new Date()); // 默认今天
  const [schemeName, setSchemeName] = useState<string>(""); // 当前方案名称
  // 记录 id、对应属性的计算值
  const [currentJunctionCalData, setCurrentJunctionCalData] = useState<any[]>(
    []
  );
  const [currentPipeCalData, setCurrentPipeCalData] = useState<any[]>([]);
  // junctionData 和 pipeData 分别缓存瓦片解析后节点和管道的数据，用于 deck.gl 定位、标签渲染
  // currentJunctionCalData 和 currentPipeCalData 变化时会新增并更新 junctionData 和 pipeData 的计算属性值
  const [junctionData, setJunctionDataState] = useState<any[]>([]);
  const [pipeData, setPipeDataState] = useState<any[]>([]);
  const junctionDataIds = useRef(new Set<string>());
  const pipeDataIds = useRef(new Set<string>());
  const tileJunctionDataBuffer = useRef<any[]>([]);
  const tilePipeDataBuffer = useRef<any[]>([]);

  const [showJunctionTextLayer, setShowJunctionTextLayer] = useState(false); // 控制节点文本图层显示
  const [showPipeTextLayer, setShowPipeTextLayer] = useState(false); // 控制管道文本图层显示
  const [showJunctionId, setShowJunctionId] = useState(false); // 控制节点ID显示
  const [showPipeId, setShowPipeId] = useState(false); // 控制管道ID显示
  const [showContourLayer, setShowContourLayer] = useState(false); // 控制等高线图层显示
  const [junctionText, setJunctionText] = useState("pressure");
  const [pipeText, setPipeText] = useState("flow");
  const [contours, setContours] = useState<any[]>([]);
  const flowAnimation = useRef(false); // 添加动画控制标志
  const [isContourLayerAvailable, setContourLayerAvailable] = useState(false); // 控制等高线图层显示
  const [isWaterflowLayerAvailable, setWaterflowLayerAvailable] =
    useState(true); // 控制等高线图层显示
  const [showWaterflowLayer, setShowWaterflowLayer] = useState(false); // 控制等高线图层显示
  const [currentZoom, setCurrentZoom] = useState(11); // 当前缩放级别

  const [diameterRange, setDiameterRange] = useState<
    [number, number] | undefined
  >();
  const [elevationRange, setElevationRange] = useState<
    [number, number] | undefined
  >();

  // 防抖更新函数
  const debouncedUpdateData = useRef(
    debounce(() => {
      if (tileJunctionDataBuffer.current.length > 0) {
        setJunctionData(tileJunctionDataBuffer.current);
        tileJunctionDataBuffer.current = [];
      }
      if (tilePipeDataBuffer.current.length > 0) {
        setPipeData(tilePipeDataBuffer.current);
        tilePipeDataBuffer.current = [];
      }
    }, 100)
  );

  const setJunctionData = (newData: any[]) => {
    const uniqueNewData = newData.filter((item) => {
      if (!item || !item.id) return false;
      if (!junctionDataIds.current.has(item.id)) {
        junctionDataIds.current.add(item.id);
        return true;
      }
      return false;
    });
    if (uniqueNewData.length > 0) {
      setJunctionDataState((prev) => prev.concat(uniqueNewData));
      setElevationRange((prev) => {
        const elevations = uniqueNewData
          .map((d) => d.elevation)
          .filter((v) => typeof v === "number");
        if (elevations.length === 0) return prev;

        let newMin = elevations[0];
        let newMax = elevations[0];
        for (let i = 1; i < elevations.length; i++) {
          if (elevations[i] < newMin) newMin = elevations[i];
          if (elevations[i] > newMax) newMax = elevations[i];
        }

        if (!prev) {
          return [newMin, newMax];
        }
        return [Math.min(prev[0], newMin), Math.max(prev[1], newMax)];
      });
    }
  };
  const setPipeData = (newData: any[]) => {
    const uniqueNewData = newData.filter((item) => {
      if (!item || !item.id) return false;
      if (!pipeDataIds.current.has(item.id)) {
        pipeDataIds.current.add(item.id);
        return true;
      }
      return false;
    });
    if (uniqueNewData.length > 0) {
      setPipeDataState((prev) => prev.concat(uniqueNewData));
      setDiameterRange((prev) => {
        const diameters = uniqueNewData
          .map((d) => d.diameter)
          .filter((v) => typeof v === "number");
        if (diameters.length === 0) return prev;

        let newMin = diameters[0];
        let newMax = diameters[0];
        for (let i = 1; i < diameters.length; i++) {
          if (diameters[i] < newMin) newMin = diameters[i];
          if (diameters[i] > newMax) newMax = diameters[i];
        }

        if (!prev) {
          return [newMin, newMax];
        }
        return [Math.min(prev[0], newMin), Math.max(prev[1], newMax)];
      });
    }
  };
  // 配置地图数据源、图层和样式
  const defaultFlatStyle: FlatStyleLike = config.MAP_DEFAULT_STYLE;
  // 定义 SCADA 图层的样式函数，根据 type 字段选择不同图标
  const scadaStyle = (feature: any) => {
    const type = feature.get("type");
    const scadaPressureIcon = "/icons/scada_pressure.svg";
    const scadaFlowIcon = "/icons/scada_flow.svg";
    // 如果 type 不匹配，可以设置默认图标或不显示
    return new Style({
      image: new Icon({
        src: type === "pipe_flow" ? scadaFlowIcon : scadaPressureIcon,
        scale: 0.1, // 根据需要调整图标大小
        anchor: [0.5, 0.5], // 图标锚点居中
      }),
    });
  };
  // 定义 reservoirs 图层的样式函数，使用固定图标
  const reservoirStyle = () => {
    const reserviorIcon = "/icons/reservior.svg";
    return new Style({
      image: new Icon({
        src: reserviorIcon,
        scale: 0.1, // 根据需要调整图标大小
        anchor: [0.5, 0.5], // 图标锚点居中
      }),
    });
  };
  // 定义 tanks 图层的样式函数，使用固定图标
  const tankStyle = () => {
    const tankIcon = "/icons/tank.svg";
    return new Style({
      image: new Icon({
        src: tankIcon,
        scale: 0.1, // 根据需要调整图标大小
        anchor: [0.5, 0.5], // 图标锚点居中
      }),
    });
  };
  const valveStyle = {
    "icon-src": "/icons/valve.svg",
    "icon-scale": 0.1,
  };
  // 定义 pumps 图层的样式函数，使用固定图标
  const pumpStyle = function (feature: FeatureLike) {
    const styles = [];
    const pumpIcon = "/icons/pump.svg";

    const geometry = feature.getGeometry();
    const lineCoords =
      geometry?.getType() === "LineString"
        ? (geometry as any).getCoordinates()
        : null;
    if (geometry) {
      const lineCoordsWGS84 = lineCoords.map((coord: []) => {
        const [lon, lat] = toLonLat(coord);
        return [lon, lat];
      });
      // 计算中点
      const lineStringFeature = lineString(lineCoordsWGS84);
      const lineLength = length(lineStringFeature);
      const midPoint = along(lineStringFeature, lineLength / 2).geometry
        .coordinates;
      // 在中点添加 icon 样式
      const midPointMercator = toMercator(midPoint);
      styles.push(
        new Style({
          geometry: new Point(midPointMercator),
          image: new Icon({
            src: pumpIcon,
            scale: 0.12,
            anchor: [0.5, 0.5],
          }),
        })
      );
    }
    return styles;
  };
  // 矢量瓦片数据源和图层
  const junctionSource = new VectorTileSource({
    url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_junctions@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
    format: new MVT(),
    projection: "EPSG:3857",
  });
  const pipeSource = new VectorTileSource({
    url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_pipes@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
    format: new MVT(),
    projection: "EPSG:3857",
  });
  const valveSource = new VectorTileSource({
    url: `${MAP_URL}/gwc/service/tms/1.0.0/${MAP_WORKSPACE}:geo_valves@WebMercatorQuad@pbf/{z}/{x}/{-y}.pbf`, // 替换为你的 MVT 瓦片服务 URL
    format: new MVT(),
    projection: "EPSG:3857",
  });
  const reservoirSource = new VectorSource({
    url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_reservoirs&outputFormat=application/json`,
    format: new GeoJson(),
  });
  const pumpSource = new VectorSource({
    url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_pumps&outputFormat=application/json`,
    format: new GeoJson(),
  });
  const tankSource = new VectorSource({
    url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_tanks&outputFormat=application/json`,
    format: new GeoJson(),
  });
  const scadaSource = new VectorSource({
    url: `${MAP_URL}/${MAP_WORKSPACE}/ows?service=WFS&version=1.0.0&request=GetFeature&typeName=${MAP_WORKSPACE}:geo_scada&outputFormat=application/json`,
    format: new GeoJson(),
  });

  // WebGL 渲染优化显示
  const junctionsLayer = new WebGLVectorTileLayer({
    source: junctionSource as any, // 使用 WebGL 渲染
    style: defaultFlatStyle,
    extent: MAP_EXTENT, // 设置图层范围
    maxZoom: 24,
    minZoom: 11,
    properties: {
      name: "节点", // 设置图层名称
      value: "junctions",
      type: "point",
      properties: [
        // { name: "需求量", value: "demand" },
        { name: "高程", value: "elevation" },
        // 计算属性
        { name: "实际需水量", value: "actual_demand" },
        { name: "水头", value: "total_head" },
        { name: "压力", value: "pressure" },
        { name: "水质", value: "quality" },
      ],
    },
  });
  const pipesLayer = new WebGLVectorTileLayer({
    source: pipeSource as any, // 使用 WebGL 渲染
    style: defaultFlatStyle,
    extent: MAP_EXTENT, // 设置图层范围
    maxZoom: 24,
    minZoom: 11,
    properties: {
      name: "管道", // 设置图层名称
      value: "pipes",
      type: "linestring",
      properties: [
        { name: "管径", value: "diameter" },
        // { name: "粗糙度", value: "roughness" },
        // { name: "局部损失", value: "minor_loss" },
        // 计算属性
        { name: "流量", value: "flow" },
        { name: "摩阻系数", value: "friction" },
        { name: "水头损失", value: "headloss" },
        { name: "单位水头损失", value: "unit_headloss" },
        { name: "水质", value: "quality" },
        { name: "反应速率", value: "reaction" },
        { name: "设置值", value: "setting" },
        { name: "状态", value: "status" },
        { name: "流速", value: "velocity" },
      ],
    },
  });
  const valvesLayer = new WebGLVectorTileLayer({
    source: valveSource as any,
    style: valveStyle,
    extent: MAP_EXTENT, // 设置图层范围
    maxZoom: 24,
    minZoom: 16,
    properties: {
      name: "阀门", // 设置图层名称
      value: "valves",
      type: "linestring",
      properties: [],
    },
  });
  const reservoirsLayer = new VectorLayer({
    source: reservoirSource,
    style: reservoirStyle,
    extent: MAP_EXTENT, // 设置图层范围
    maxZoom: 24,
    minZoom: 11,
    properties: {
      name: "水库", // 设置图层名称
      value: "reservoirs",
      type: "point",
      properties: [],
    },
  });
  const pumpsLayer = new VectorLayer({
    source: pumpSource,
    style: pumpStyle,
    extent: MAP_EXTENT, // 设置图层范围
    maxZoom: 24,
    minZoom: 11,
    properties: {
      name: "水泵", // 设置图层名称
      value: "pumps",
      type: "linestring",
      properties: [],
    },
  });
  const tanksLayer = new VectorLayer({
    source: tankSource,
    style: tankStyle,
    extent: MAP_EXTENT, // 设置图层范围
    maxZoom: 24,
    minZoom: 11,
    properties: {
      name: "水箱", // 设置图层名称
      value: "tanks",
      type: "point",
      properties: [],
    },
  });
  const scadaLayer = new VectorLayer({
    source: scadaSource,
    style: scadaStyle,
    // extent: extent, // 设置图层范围
    maxZoom: 24,
    minZoom: 11,
    properties: {
      name: "SCADA", // 设置图层名称
      value: "scada",
      type: "point",
      properties: [],
    },
  });

  useEffect(() => {
    if (!mapRef.current) return;
    // 缓存 junction、pipe 数据，提供给 deck.gl 提供坐标供标签显示
    junctionSource.on("tileloadend", (event) => {
      try {
        if (event.tile instanceof VectorTile) {
          const renderFeatures = event.tile.getFeatures();
          const data = new Map();

          renderFeatures.forEach((renderFeature) => {
            const props = renderFeature.getProperties();
            const featureId = props.id;
            if (featureId && !junctionDataIds.current.has(featureId)) {
              const geometry = renderFeature.getGeometry();
              if (geometry) {
                const coordinates = geometry.getFlatCoordinates();
                const coordWGS84 = toLonLat(coordinates);
                data.set(featureId, {
                  id: featureId,
                  position: coordWGS84,
                  elevation: props.elevation || 0,
                  demand: props.demand || 0,
                });
              }
            }
          });

          const uniqueData = Array.from(data.values());
          if (uniqueData.length > 0) {
            uniqueData.forEach((item) =>
              tileJunctionDataBuffer.current.push(item)
            );
            debouncedUpdateData.current();
          }
        }
      } catch (error) {
        console.error("Junction tile load error:", error);
      }
    });
    pipeSource.on("tileloadend", (event) => {
      try {
        if (event.tile instanceof VectorTile) {
          const renderFeatures = event.tile.getFeatures();
          const data = new Map();

          renderFeatures.forEach((renderFeature) => {
            try {
              const props = renderFeature.getProperties();
              const featureId = props.id;
              if (featureId && !pipeDataIds.current.has(featureId)) {
                const geometry = renderFeature.getGeometry();
                if (geometry) {
                  const flatCoordinates = geometry.getFlatCoordinates();
                  const stride = geometry.getStride(); // 获取步长，通常为 2
                  // 重建为 LineString GeoJSON 格式的 coordinates: [[x1, y1], [x2, y2], ...]
                  const lineCoords = [];
                  for (let i = 0; i < flatCoordinates.length; i += stride) {
                    lineCoords.push([
                      flatCoordinates[i],
                      flatCoordinates[i + 1],
                    ]);
                  }
                  const lineCoordsWGS84 = lineCoords.map((coord) => {
                    const [lon, lat] = toLonLat(coord);
                    return [lon, lat];
                  });
                  // 添加验证：确保至少有 2 个坐标点
                  if (lineCoordsWGS84.length < 2) return; // 跳过此特征
                  // 计算中点
                  const lineStringFeature = lineString(lineCoordsWGS84);
                  const lineLength = length(lineStringFeature);
                  const midPoint = along(lineStringFeature, lineLength / 2)
                    .geometry.coordinates;
                  // 计算角度
                  const prevPoint = along(lineStringFeature, lineLength * 0.49)
                    .geometry.coordinates;
                  const nextPoint = along(lineStringFeature, lineLength * 0.51)
                    .geometry.coordinates;
                  let lineAngle = bearing(prevPoint, nextPoint);
                  lineAngle = -lineAngle + 90;
                  if (lineAngle < -90 || lineAngle > 90) {
                    lineAngle += 180;
                  }

                  // 计算时间戳（可选）
                  const numSegments = lineCoordsWGS84.length - 1;
                  const timestamps = [0];
                  if (numSegments > 0) {
                    for (let i = 1; i <= numSegments; i++) {
                      timestamps.push((i / numSegments) * 10);
                    }
                  }

                  data.set(featureId, {
                    id: featureId,
                    diameter: props.diameter || 0,
                    path: lineCoordsWGS84, // 使用重建后的坐标
                    position: midPoint,
                    angle: lineAngle,
                    timestamps,
                  });
                }
              }
            } catch (geomError) {
              console.error("Geometry calculation error:", geomError);
            }
          });

          const uniqueData = Array.from(data.values());
          if (uniqueData.length > 0) {
            uniqueData.forEach((item) => tilePipeDataBuffer.current.push(item));
            debouncedUpdateData.current();
          }
        }
      } catch (error) {
        console.error("Pipe tile load error:", error);
      }
    });
    // 监听 junctionsLayer 的 visible 变化
    const handleJunctionVisibilityChange = () => {
      const isVisible = junctionsLayer.getVisible();
      setShowJunctionTextLayer(isVisible);
    };
    // 监听 pipesLayer 的 visible 变化
    const handlePipeVisibilityChange = () => {
      const isVisible = pipesLayer.getVisible();
      setShowPipeTextLayer(isVisible);
    };
    // 添加事件监听器
    junctionsLayer.on("change:visible", handleJunctionVisibilityChange);
    pipesLayer.on("change:visible", handlePipeVisibilityChange);
    const availableLayers: any[] = [];
    config.MAP_AVAILABLE_LAYERS.forEach((layerValue) => {
      switch (layerValue) {
        case "junctions":
          availableLayers.push(junctionsLayer);
          break;
        case "pipes":
          availableLayers.push(pipesLayer);
          break;
        case "valves":
          availableLayers.push(valvesLayer);
          break;
        case "reservoirs":
          availableLayers.push(reservoirsLayer);
          break;
        case "pumps":
          availableLayers.push(pumpsLayer);
          break;
        case "tanks":
          availableLayers.push(tanksLayer);
          break;
        case "scada":
          availableLayers.push(scadaLayer);
          break;
      }
    });
    // 重新排列图层顺序，确保顺序 点>线>面
    availableLayers.sort((a, b) => {
      // 明确顺序（点类优先），这里 valves 特殊处理
      const order = [
        "valves",
        "junctions",
        "scada",
        "reservoirs",
        "pumps",
        "tanks",
        "pipes",
      ].reverse();
      // 取值时做安全检查，兼容不同写法（properties.value 或 直接 value）
      const getValue = (layer: any) => {
        const props = layer.get ? layer.get("properties") : undefined;
        return (props && props.value) || layer.get?.("value") || "";
      };
      const aVal = getValue(a);
      const bVal = getValue(b);
      let ia = order.indexOf(aVal);
      let ib = order.indexOf(bVal);
      // 如果未在 order 中找到，放到末尾
      if (ia === -1) ia = order.length;
      if (ib === -1) ib = order.length;
      return ia - ib;
    });
    const map = new OlMap({
      target: mapRef.current,
      view: new View({
        maxZoom: 24,
        projection: "EPSG:3857",
      }),
      // 图层依面、线、点、标注次序添加
      layers: availableLayers.slice(),
      controls: [],
    });
    setMap(map);

    // 恢复上次视图；如果没有则适配 MAP_EXTENT
    try {
      const stored = localStorage.getItem(MAP_VIEW_STORAGE_KEY);
      if (stored) {
        const viewState = JSON.parse(stored);
        if (
          viewState &&
          Array.isArray(viewState.center) &&
          viewState.center.length === 2 &&
          typeof viewState.zoom === "number" &&
          viewState.zoom >= 11 &&
          viewState.zoom <= 24
        ) {
          map.getView().setCenter(viewState.center);
          map.getView().setZoom(viewState.zoom);
        } else {
          map.getView().fit(MAP_EXTENT, {
            padding: [50, 50, 50, 50],
            duration: 1000,
          });
        }
      } else {
        map.getView().fit(MAP_EXTENT, {
          padding: [50, 50, 50, 50],
          duration: 1000,
        });
      }
    } catch (err) {
      console.warn("Restore map view failed", err);
      map.getView().fit(MAP_EXTENT, {
        padding: [50, 50, 50, 50],
        duration: 1000,
      });
    }
    // 持久化视图（中心点 + 缩放），防抖写入 localStorage
    const persistView = debounce(() => {
      try {
        const view = map.getView();
        const center = view.getCenter();
        const zoom = view.getZoom();
        if (center && typeof zoom === "number") {
          localStorage.setItem(
            MAP_VIEW_STORAGE_KEY,
            JSON.stringify({ center, zoom })
          );
        }
      } catch (err) {
        console.warn("Save map view failed", err);
      }
    }, 250);

    // 监听缩放变化并持久化，同时更新 currentZoom
    const handleViewChange = () => {
      setTimeout(() => {
        const zoom = map.getView().getZoom() || 0;
        setCurrentZoom(zoom);
        persistView();
      }, 250);
    };
    map.getView().on("change", handleViewChange);

    // 初始化当前缩放级别并强制触发瓦片加载
    setTimeout(() => {
      const initialZoom = map.getView().getZoom() || 11;
      setCurrentZoom(initialZoom);
      // 强制触发地图渲染，让瓦片加载事件触发
      map.render();
    }, 100);

    // 初始化 deck.gl
    const deck = new Deck({
      initialViewState: {
        longitude: 0,
        latitude: 0,
        zoom: 1,
      },
      canvas: "deck-canvas",
      controller: false, // 由 OpenLayers 控制视图
      layers: [],
    });
    const deckLayer = new DeckLayer(deck, {
      name: "deckLayer",
      value: "deckLayer",
    });
    deckLayerRef.current = deckLayer;
    setDeckLayer(deckLayer);
    map.addLayer(deckLayer);

    // 清理函数
    return () => {
      junctionsLayer.un("change:visible", handleJunctionVisibilityChange);
      pipesLayer.un("change:visible", handlePipeVisibilityChange);
      map.setTarget(undefined);
      map.dispose();
      deck.finalize();
    };
  }, []);

  // 当数据变化时，更新 deck.gl 图层
  useEffect(() => {
    const deckLayer = deckLayerRef.current;
    if (!deckLayer) return; // 如果 deck 实例还未创建，则退出
    if (!junctionData.length) return;
    if (!pipeData.length) return;
    console.log(showJunctionId, showJunctionTextLayer, junctionText);
    console.log(showPipeId, showPipeTextLayer, pipeText);
    const junctionTextLayer = new TextLayer({
      id: "junctionTextLayer",
      name: "节点文字",
      zIndex: 10,
      data: junctionData,
      getPosition: (d: any) => d.position,
      fontFamily: "Monaco, monospace",
      getText: (d: any) => {
        let idPart = showJunctionId ? d.id : "";
        let propPart = "";
        if (showJunctionTextLayer && d[junctionText] !== undefined) {
          const value = (d[junctionText] as number).toFixed(3);
          // 根据属性类型添加符号前缀
          const prefix =
            {
              pressure: "P:",
              head: "H:",
              quality: "Q:",
              actualdemand: "D:",
            }[junctionText] || "";
          propPart = `${prefix}${value}`;
        }
        if (idPart && propPart) return `${idPart} - ${propPart}`;
        return idPart || propPart;
      },
      getSize: 14,
      fontWeight: "bold",
      getColor: [33, 37, 41], // 深灰色，在灰白背景上清晰可见
      getAngle: 0,
      getTextAnchor: "middle",
      getAlignmentBaseline: "center",
      getPixelOffset: [0, -10],
      visible:
        (showJunctionTextLayer || showJunctionId) &&
        currentZoom >= 15 &&
        currentZoom <= 24,
      updateTriggers: {
        getText: [showJunctionId, showJunctionTextLayer, junctionText],
      },
      extensions: [new CollisionFilterExtension()],
      collisionTestProps: {
        sizeScale: 3,
      },
      characterSet: "auto",
      fontSettings: {
        sdf: true,
        fontSize: 64,
        buffer: 6,
      },
      // outlineWidth: 3,
      // outlineColor: [255, 255, 255, 220],
    });

    const pipeTextLayer = new TextLayer({
      id: "pipeTextLayer",
      name: "管道文字",
      zIndex: 10,
      data: pipeData,
      getPosition: (d: any) => d.position,
      fontFamily: "Monaco, monospace",
      getText: (d: any) => {
        let idPart = showPipeId ? d.id : "";
        let propPart = "";
        if (showPipeTextLayer && d[pipeText] !== undefined) {
          const value = Math.abs(d[pipeText] as number).toFixed(3);
          // 根据属性类型添加符号前缀
          const prefix =
            {
              flow: "F:",
              velocity: "V:",
              headloss: "HL:",
              diameter: "D:",
              friction: "FR:",
            }[pipeText] || "";
          propPart = `${prefix}${value}`;
        }
        if (idPart && propPart) return `${idPart} - ${propPart}`;
        return idPart || propPart;
      },
      getSize: 14,
      fontWeight: "bold",
      getColor: [33, 37, 41], // 深灰色
      getAngle: (d: any) => d.angle || 0,
      getPixelOffset: [0, -8],
      getTextAnchor: "middle",
      getAlignmentBaseline: "bottom",
      visible:
        (showPipeTextLayer || showPipeId) &&
        currentZoom >= 15 &&
        currentZoom <= 24,
      updateTriggers: {
        getText: [showPipeId, showPipeTextLayer, pipeText],
      },
      extensions: [new CollisionFilterExtension()],
      collisionTestProps: {
        sizeScale: 3,
      },
      characterSet: "auto",
      fontSettings: {
        sdf: true,
        fontSize: 64,
        buffer: 6,
      },
      // outlineWidth: 3,
      // outlineColor: [255, 255, 255, 220],
    });

    const contourLayer = new ContourLayer({
      id: "junctionContourLayer",
      name: "等值线",
      data: junctionData,
      aggregation: "MEAN",
      cellSize: 600,
      strokeWidth: 0,
      contours: contours,
      getPosition: (d) => d.position,
      getWeight: (d: any) =>
        (d[junctionText] as number) < 0 ? 0 : (d[junctionText] as number),
      opacity: 1,
      visible: showContourLayer && currentZoom >= 11 && currentZoom <= 24,
    });
    if (deckLayer.getDeckLayerById("junctionTextLayer")) {
      // 传入完整 layer 实例以保证 clone/替换时保留 layer 类型和方法
      deckLayer.updateDeckLayer("junctionTextLayer", junctionTextLayer);
    } else {
      deckLayer.addDeckLayer(junctionTextLayer);
    }
    if (deckLayer.getDeckLayerById("pipeTextLayer")) {
      console.log("更新管道文字图层");
      deckLayer.updateDeckLayer("pipeTextLayer", pipeTextLayer);
    } else {
      deckLayer.addDeckLayer(pipeTextLayer);
    }
    if (deckLayer.getDeckLayerById("junctionContourLayer")) {
      deckLayer.updateDeckLayer("junctionContourLayer", contourLayer);
    } else {
      deckLayer.addDeckLayer(contourLayer);
    }
  }, [
    junctionData,
    pipeData,
    currentZoom,
    showJunctionTextLayer,
    showPipeTextLayer,
    showJunctionId,
    showPipeId,
    showContourLayer,
    junctionText,
    pipeText,
    contours,
  ]);

  // 控制流动动画开关
  useEffect(() => {
    if (pipeText === "flow" && currentPipeCalData.length > 0) {
      flowAnimation.current = true;
    } else {
      flowAnimation.current = false;
    }
    const deckLayer = deckLayerRef.current;
    if (!deckLayer) return; // 如果 deck 实例还未创建，则退出

    let animationFrameId: number; // 保存 requestAnimationFrame 的 ID

    // 动画循环
    const animate = () => {
      if (!flowAnimation.current) {
        try {
          deckLayer.removeDeckLayer("waterflowLayer");
        } catch (error) {
          console.error("Error in animation loop:", error);
        }
        return;
      }
      // 动画总时长（秒）
      if (pipeData.length === 0) {
        animationFrameId = requestAnimationFrame(animate);
        return;
      }
      const animationDuration = 10;
      // 缓冲时间（秒）
      const bufferTime = 2;
      // 完整循环周期
      const loopLength = animationDuration + bufferTime;
      // 确保时间范围与你的时间戳数据匹配
      const currentTime = (Date.now() / 1000) % loopLength; // (0,12) 之间循环
      // console.log("Current Time:", currentTime);
      const waterflowLayer = new TripsLayer({
        id: "waterflowLayer",
        name: "水流",
        data: pipeData,
        getPath: (d) => d.path,
        getTimestamps: (d) => {
          return d.timestamps; // 这些应该是与 currentTime 匹配的数值
        },
        getColor: [0, 220, 255],
        opacity: 0.8,
        visible:
          isWaterflowLayerAvailable &&
          showWaterflowLayer &&
          flowAnimation.current &&
          currentZoom >= 12 &&
          currentZoom <= 24,
        widthMinPixels: 5,
        jointRounded: true, // 拐角变圆
        // capRounded: true, // 端点变圆
        trailLength: 2, // 水流尾迹淡出时间
        currentTime: currentTime,
      });
      // if (deckLayer.getDeckLayerById("waterflowLayer")) {
      //   deckLayer.updateDeckLayer("waterflowLayer", waterflowLayer);
      // } else {
      //   deckLayer.addDeckLayer(waterflowLayer);
      // }
      // 继续请求动画帧，每帧执行一次函数
      animationFrameId = requestAnimationFrame(animate);
    };
    animate();

    // 清理函数:取消动画帧
    return () => {
      if (animationFrameId) {
        cancelAnimationFrame(animationFrameId);
      }
    };
  }, [
    currentZoom,
    currentPipeCalData,
    pipeText,
    pipeData.length,
    isWaterflowLayerAvailable,
    showWaterflowLayer,
  ]);

  // 计算值更新时，更新 junctionData 和 pipeData
  useEffect(() => {
    const junctionProperties = junctionText;
    const pipeProperties = pipeText;

    // 将 nodeRecords 转换为 Map 以提高查找效率
    const nodeMap: Map<string, any> = new Map(
      currentJunctionCalData.map((r: any) => [r.ID, r])
    );
    // 将 linkRecords 转换为 Map 以提高查找效率
    const linkMap: Map<string, any> = new Map(
      currentPipeCalData.map((r: any) => [r.ID, r])
    );
    if (nodeMap.size > 0) {
      // 更新junctionData
      setJunctionDataState((prev: any[]) =>
        prev.map((j) => {
          const record = nodeMap.get(j.id);
          if (record) {
            return {
              ...j,
              [junctionProperties]: record.value,
            };
          }
          return j;
        })
      );
    }
    if (linkMap.size > 0) {
      // 更新pipeData
      setPipeDataState((prev: any[]) =>
        prev.map((p) => {
          const record = linkMap.get(p.id);
          if (record) {
            return {
              ...p,
              flowFlag: pipeProperties === "flow" && record.value < 0 ? -1 : 1,
              path:
                pipeProperties === "flow" && record.value < 0 && p.flowFlag > 0
                  ? p.path.slice().reverse()
                  : p.path,
              // 流量数值
              [pipeProperties]:
                pipeProperties === "flow"
                  ? Math.abs(record.value)
                  : record.value,
            };
          }
          return p;
        })
      );
    }
  }, [currentJunctionCalData, currentPipeCalData]);
  return (
    <>
      <DataContext.Provider
        value={{
          currentTime,
          setCurrentTime,
          selectedDate,
          setSelectedDate,
          schemeName,
          setSchemeName,
          currentJunctionCalData,
          setCurrentJunctionCalData,
          currentPipeCalData,
          setCurrentPipeCalData,
          setShowJunctionTextLayer,
          setShowPipeTextLayer,
          setShowJunctionId,
          setShowPipeId,
          showJunctionId,
          showPipeId,
          setShowContourLayer,
          isContourLayerAvailable,
          setContourLayerAvailable,
          isWaterflowLayerAvailable,
          setWaterflowLayerAvailable,
          setShowWaterflowLayer,
          setJunctionText,
          setPipeText,
          junctionText,
          pipeText,
          setContours,
          deckLayer,
          diameterRange,
          elevationRange,
        }}
      >
        <MapContext.Provider value={map}>
          <div className="relative w-full h-full">
            <div ref={mapRef} className="w-full h-full"></div>
            <MapTools />
            {children}
          </div>
          <canvas id="deck-canvas" />
        </MapContext.Provider>
      </DataContext.Provider>
    </>
  );
};

export default MapComponent;
