import { onMounted, ref, computed, watch, markRaw, inject } from "vue";
import { getDashboardDevice } from "@/apis/dashboard";
import useSearchParams from "@/hooks/useSearchParam";
import useSystemHeatmap from "./useSystemHeatmap";

export default function useSystemStatusByBaja() {
  const rawData = ref([]);
  const forgeViewer = ref(null);
  const visibleDbid = ref([]);
  const heatmapDevices = ref([]);

  const urn = ref("");
  const lightColorMap = {
    1: "#009100",
    2: "#c9bf00",
    4: "#ff1212",
  };
  const { searchParams } = useSearchParams();

  // DataVisualization 擴充套件的全域變數
  let dataVizExtn = null;
  let spriteAnimations = new Map(); // 用 Map 來追蹤多個動畫 {dbId: {interval, arrow, viewable}}
  let cameraEventAdded = false; // 追蹤是否已經添加了相機事件監聽器

  const initialData = ref(null);
  const pipeList = ref(null);
  const subscribeData = ref({});

  const updateInitialData = (data = false) => {
    initialData.value = data;
    if (data && Array.isArray(data.dbid_list)) {
      visibleDbid.value = data.dbid_list.map((d) => d.forge_dbid);
      heatmapDevices.value = data.dbid_list.filter((d) => d.room_dbid !== null);
    } else {
      visibleDbid.value = [];
    }
  };

  function updatePipeData(data) {
    const newDbids = data.map((item) => item.forge_dbid);
    const oldDbids = pipeList.value
      ? pipeList.value.map((item) => item.forge_dbid)
      : [];
    const toHide = oldDbids.filter((dbid) => !newDbids.includes(dbid));
    console.log("更新水管數據", forgeViewer.value, data);
    if (forgeViewer.value) {
      if (toHide.length > 0 && forgeViewer.value.hide)
        forgeViewer.value.hide(toHide);
      if (newDbids.length > 0 && forgeViewer.value.show)
        forgeViewer.value.show(newDbids);
    }

    pipeList.value = data;
    clearSprites(); // 清理之前的 Sprites
    // 如果有特定的 dbid 需要顯示動畫，則創建動畫
    if (forgeViewer.value && pipeList.value.length > 0) {
      pipeList.value.forEach(({ forge_dbid, reverse }) => {
        if (reverse !== null) {
          createSprites(forgeViewer.value, forge_dbid, reverse);
        }
      });
    }
  }

  const { updateHeatMapData, initHeatMap, updateTemp } = useSystemHeatmap();

  const updateForgeViewer = async (viewer) => {
    if (!viewer) {
      forgeViewer.value = null;
      return;
    }
    forgeViewer.value = markRaw(viewer);
    await initHeatMap(viewer); // 等待初始化完成
    updateHeatMapData(heatmapDevices.value);
    updatePipeData(pipeList.value || []);
  };

  // subscribe from baja
  const booleanPointFacets = ref({});
  const updateFacets = (point, facets) => {
    booleanPointFacets.value = {
      ...booleanPointFacets,
      [point]: facets,
    };
  };

  const subComponents = ref(null);

  const updateMeterPositions = (meterList) => {
    if (!forgeViewer.value || !meterList) return new Map();

    const viewer = forgeViewer.value;
    const tree = viewer.model?.getData()?.instanceTree;
    const fragList = viewer.model?.getFragmentList();

    if (!tree || !fragList) return new Map();

    const newPositions = new Map();

    meterList.forEach((meter) => {
      if (meter.forge_dbid) {
        try {
          const nodebBox = new window.THREE.Box3();

          // 取得物件的 bounding box
          tree.enumNodeFragments(
            meter.forge_dbid,
            (fragId) => {
              const fragbBox = new window.THREE.Box3();
              fragList.getWorldBounds(fragId, fragbBox);
              nodebBox.union(fragbBox);
            },
            true
          );

          if (!nodebBox.isEmpty()) {
            const center = nodebBox.getCenter(new window.THREE.Vector3());
            const pos2d = viewer.worldToClient(center);
            newPositions.set(meter.main_id, {
              x: pos2d.x,
              y: pos2d.y - 100, // 往上偏移 100px
              visible: viewer.isNodeVisible(meter.forge_dbid),
            });
          }
        } catch (error) {
          console.warn(`無法計算 dbid ${meter.forge_dbid} 的位置:`, error);
        }
      }
    });

    return newPositions;
  };

  const fitToView = () => {
    const { x, y, z } = JSON.parse(searchParams.value.camera_position);
    const newPosition = new THREE.Vector3(x, y, z);
    const {
      x: x1,
      y: y1,
      z: z1,
    } = JSON.parse(searchParams.value.target_position);
    const newTarget = new THREE.Vector3(x1, y1, z1);
    forgeViewer.value.navigation.setView(newPosition, newTarget);
    // 強制 up vector 為 Z 軸朝上，確保視角水平
    forgeViewer.value.navigation.setCameraUpVector(new THREE.Vector3(0, 0, 1));
  };

  const hideAllObjects = (instanceTree, filDbids = []) => {
    if (!forgeViewer.value || !instanceTree) return;
    const allDbIds = Object.keys(instanceTree.nodeAccess.dbIdToIndex).map(
      Number
    );

    forgeViewer.value.hide(allDbIds);
    if (filDbids.length > 0) {
      forgeViewer.value.show(filDbids);
    }
    forgeViewer.value.impl.invalidate(true);
  };

  const loadModel = (viewer, filePath) => {
    return new Promise(function (resolve, reject) {
      // 使用 loadModel 直接加載本地 .svf 文件
      viewer.loadModel(
        filePath,
        {},
        (model) => {
          viewer.setGroundShadow(false);
          viewer.setLightPreset(18);

          viewer.impl.renderer().setClearAlpha(0); // 清除 alpha 通道
          viewer.impl.glrenderer().setClearColor(0xffffff, 0); // 設置透明背景，顏色碼無關緊要
          viewer.impl.invalidate(true); // 觸發渲染
          resolve(model);
        },
        (error) => {
          console.error("模型加載失敗: ", error);
          reject(error);
        }
      );
    });
  };

  const reloadModal = () => {};

  let themingInterval = null;
  let blinkingInterval = null; // 計時器 ID 的引用

  // 增強版：停止閃爍並徹底清理
  const stopBlinking = () => {
    console.log("正在停止基於 Selection 的閃爍效果...");
    if (blinkingInterval) {
      clearInterval(blinkingInterval);
      blinkingInterval = null;
    }
    if (forgeViewer.value) {
      // 核心清理：取消所有選取
      forgeViewer.value.clearSelection();
    }
  };

  const startBlinking = (dbidToBlink) => {
    console.log(`正在為 dbId: ${dbidToBlink} 啟動基於 Selection 的閃爍...`);
    if (!forgeViewer.value) return;

    // 步驟 1: 設定一次我們希望的閃爍顏色和樣式
    const blinkColor = new THREE.Color(0x00aaff); // 水藍色
    forgeViewer.value.setSelectionColor(
      blinkColor,
      Autodesk.Viewing.SelectionType.OVERLAYED
    );

    let isSelected = false; // 用一個旗標來追蹤目前的選取狀態

    blinkingInterval = setInterval(() => {
      // 在計時器內部也要檢查 viewer 是否還存在
      if (!forgeViewer.value) {
        stopBlinking();
        return;
      }

      if (isSelected) {
        // 如果已選取，就取消選取 (閃爍 OFF)
        forgeViewer.value.clearSelection();
      } else {
        // 如果未選取，就選取目標物件 (閃爍 ON)
        // 注意：select 方法需要傳入 model 物件
        forgeViewer.value.select(
          dbidToBlink,
          forgeViewer.value.model,
          Autodesk.Viewing.SelectionType.OVERLAYED
        );
      }

      // 切換狀態，為下一次循環做準備
      isSelected = !isSelected;
    }, 700); // 我們可以稍微調整一下頻率，例如 700 毫秒
  };

  watch([forgeViewer, visibleDbid], ([viewer, dbids]) => {
    console.log("監聽到 forgeViewer 或 visibleDbid 的變化", viewer, dbids);

    if (viewer) {
      hideAllObjects(viewer.model.getData().instanceTree, dbids);
    }
  });

  watch(
    [forgeViewer, () => searchParams.value.camera_position],
    ([viewer, newValue]) => {
      if (viewer && newValue) {
        fitToView();
      }
    }
  );

  // 動態Sprites創建函數
  const createSprites = async (viewer, dbId, reverse = false) => {
    try {
      // 先清理這個 dbId 的舊 Sprite（如果存在）
      clearSingleSprite(dbId);

      // 1. 載入 DataVisualization 擴充套件
      if (!dataVizExtn) {
        dataVizExtn = await viewer.loadExtension("Autodesk.DataVisualization");
      }

      // 2. 建立 ViewableStyle
      const DataVizCore = Autodesk.DataVisualization.Core;
      const viewableType = DataVizCore.ViewableType.SPRITE;
      const spriteColor = new THREE.Color(0x00ffff);
      const spriteIconUrl = "spot.svg";
      const style = new DataVizCore.ViewableStyle(
        viewableType,
        spriteColor,
        spriteIconUrl
      );
      const viewableData = new DataVizCore.ViewableData();
      viewableData.spriteSize = 12;

      // 3. 取得 dbId 的 3D 位置
      viewer.getObjectTree(function (instanceTree) {
        const fragList = viewer.model.getFragmentList();
        let fragIds = [];
        instanceTree.enumNodeFragments(dbId, function (fragId) {
          fragIds.push(fragId);
        });

        if (fragIds.length > 0) {
          let box = new THREE.Box3();
          fragIds.forEach((fragId) => {
            let fragBox = new THREE.Box3();
            fragList.getWorldBounds(fragId, fragBox);
            box.union(fragBox);
          });

          // 算出主軸方向
          const size = new THREE.Vector3();
          box.getSize(size);
          // 找出最長的軸
          let axis = "x";
          if (size.y >= size.x && size.y >= size.z) axis = "y";
          if (size.z >= size.x && size.z >= size.y) axis = "z";

          // 取得所有 fragment 的中心點
          let centers = fragIds.map((fragId) => {
            let fragBox = new THREE.Box3();
            fragList.getWorldBounds(fragId, fragBox);
            return fragBox.getCenter(new THREE.Vector3());
          });

          // 找出距離最遠的兩點作為動畫路徑
          let maxDist = 0;
          let animStart = centers[0],
            animEnd = centers[0];
          for (let i = 0; i < centers.length; i++) {
            for (let j = i + 1; j < centers.length; j++) {
              let dist = centers[i].distanceTo(centers[j]);
              if (dist > maxDist) {
                maxDist = dist;
                animStart = centers[i];
                animEnd = centers[j];
              }
            }
          }

          // fallback: 若只有一個 fragment 或所有中心點重疊，改用主軸方向的端點
          if (centers.length < 2 || maxDist === 0) {
            const boxCenter = box.getCenter(new THREE.Vector3());
            const halfSize = size.clone().multiplyScalar(0.5);

            animStart = boxCenter.clone();
            animEnd = boxCenter.clone();

            // 根據主軸設定起點和終點
            if (axis === "x") {
              animStart.x -= halfSize.x;
              animEnd.x += halfSize.x;
            } else if (axis === "y") {
              animStart.y -= halfSize.y;
              animEnd.y += halfSize.y;
            } else {
              // z軸
              animStart.z -= halfSize.z;
              animEnd.z += halfSize.z;
            }
          }

          // === 依主軸方向排序，確保動畫方向一致 ===
          // 根據主軸來排序起點和終點，確保動畫方向一致
          if (axis === "x" && animStart.x > animEnd.x) {
            const tmp = animStart;
            animStart = animEnd;
            animEnd = tmp;
          }
          if (axis === "y" && animStart.y > animEnd.y) {
            const tmp = animStart;
            animStart = animEnd;
            animEnd = tmp;
          }
          if (axis === "z" && animStart.z > animEnd.z) {
            const tmp = animStart;
            animStart = animEnd;
            animEnd = tmp;
          }

          // === 若 reverse 為 true，則反向 ===
          if (reverse) {
            const tmp = animStart;
            animStart = animEnd;
            animEnd = tmp;
          }

          // 4. 建立 SpriteViewable，初始在 animStart
          const viewable = new DataVizCore.SpriteViewable(
            animStart.clone(),
            style,
            dbId
          );
          viewableData.addViewable(viewable);
          viewableData.finish().then(() => {
            dataVizExtn.addViewables(viewableData);

            // 5. 單向從起點移動到終點，然後重頭再來
            // === 新增 HTML箭頭動畫，會跟隨Sprite移動並指向終點 ===
            let arrow = document.createElement("img");
            arrow.src = "arrow.png";
            arrow.style.position = "absolute";
            arrow.style.width = "22px";
            arrow.style.height = "22px";
            arrow.style.pointerEvents = "none";
            arrow.style.zIndex = 10;
            arrow.className = `custom-3d-arrow-${dbId}`; // 加上 dbId 作為唯一識別
            viewer.container.appendChild(arrow);

            function updateArrow(pos) {
              const pos2d = viewer.worldToClient(pos.clone());
              const end2d = viewer.worldToClient(animEnd.clone());
              arrow.style.left = `${pos2d.x - 16}px`;
              arrow.style.top = `${pos2d.y - 16}px`;
              // 算角度：pos 指向 animEnd
              const dx = end2d.x - pos2d.x;
              const dy = end2d.y - pos2d.y;
              const angle = (Math.atan2(dy, dx) * 180) / Math.PI;
              arrow.style.transform = `rotate(${angle}deg)`;
            }

            // 動畫主程式
            let t = 0;
            let currentPos = animStart.clone();
            const animationInterval = setInterval(() => {
              t += 0.01;
              if (t > 1) t = 0; // 到終點就重頭
              currentPos = animStart.clone().lerp(animEnd, t);
              dataVizExtn.invalidateViewables([dbId], (v) => {
                return {
                  position: {
                    x: currentPos.x,
                    y: currentPos.y,
                    z: currentPos.z,
                  },
                };
              });
              updateArrow(currentPos);

              // 更新保存的 currentPos
              if (spriteAnimations.has(dbId)) {
                spriteAnimations.get(dbId).currentPos = currentPos;
              }
            }, 30);

            // 保存這個 dbId 的動畫資訊
            spriteAnimations.set(dbId, {
              interval: animationInterval,
              arrow: arrow,
              viewable: viewable,
              updateArrow: updateArrow,
              currentPos: currentPos,
            });
          });
        }
      });
    } catch (error) {
      console.error("創建動態Sprites時發生錯誤:", error);
    }
  };

  // 清理單個 Sprite 的函數
  const clearSingleSprite = (dbId) => {
    if (spriteAnimations.has(dbId)) {
      const animation = spriteAnimations.get(dbId);

      // 清理動畫計時器
      if (animation.interval) {
        clearInterval(animation.interval);
      }

      // 清理箭頭元素
      if (animation.arrow && animation.arrow.parentNode) {
        animation.arrow.parentNode.removeChild(animation.arrow);
      }

      // 移除這個 dbId 的記錄
      spriteAnimations.delete(dbId);
    }
  };

  // 清理所有 Sprites 和相關資源的函數
  const clearSprites = () => {
    // 清理所有動畫
    spriteAnimations.forEach((animation, dbId) => {
      clearSingleSprite(dbId);
    });

    // 清理所有 viewables
    if (dataVizExtn) {
      dataVizExtn.removeAllViewables();
    }

    // 重置相機事件標記
    cameraEventAdded = false;

    console.log("已清理所有 Sprites 和相關資源");
  };

  return {
    subscribeData,
    visibleDbid,
    updateMeterPositions,
    hideAllObjects,
    updateForgeViewer,
    updatePipeData,
    forgeViewer,
    loadModel,
    urn,
    updateInitialData,
    subComponents,
    createSprites,
    clearSprites,
    clearSingleSprite,
    updateTemp,
    fitToView,
  };
}
