import { _objectSpread2 } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
import { TOPOLOGY_DEVICES_DATA_SOURCE_KEY, TOPOLOGY_DEVICE_KIND_PREFIX, TOPOLOGY_MAIN_CANVAS_ID } from "../topologyFloorPlanConstants.js";
import { ensureShopFloorPlanByCode, toastFloorPlanLoadError, unsubscribeShopFloorPlanCodeQuery } from "./topologyFloorPlanApi.js";
import { useCallback, useEffect, useRef, useState } from "react";
import { getUniqueId } from "@pisell/utils";
import { parseLayoutFieldToViewConfigPatch, shopLayoutToSceneElements, useShopFloorPlanSubscription } from "@pisell/materials";
//#region src/plus/pisellTopology/floorPlan/useTopologyFloorPlan.ts
/**
* 拉取拓扑 floor-plan：把远端 layout 解析成已保存的 sceneElements / edges。
*
* 设计点：
* - 不再混入 mock shell，调用方直接拿到「已保存」的 sceneElements / edges 用于对账
* - 区分「未加载」「已加载但为空」「已加载且有内容」三态：未加载时 savedSceneElements = undefined
*/
const TOPOLOGY_UNKNOWN_KIND = `${TOPOLOGY_DEVICE_KIND_PREFIX}unknown`;
/** 创建空的默认 floor-plan post body（首次创建时使用，不放任何 mock 节点） */
function buildEmptyTopologyFloorPlanPostBody(code) {
	const trimmed = code === null || code === void 0 ? void 0 : code.trim();
	if (!trimmed) throw new Error("floor plan code is required");
	return {
		code: trimmed,
		name: { "zh-CN": "拓扑" },
		layout: {
			canvases: [{
				id: "main",
				name: "Devices",
				order: 0,
				enabled: true
			}],
			canvasUi: {
				canCreate: false,
				canEdit: false
			},
			sceneElements: [],
			edges: []
		},
		canvas_width: 1920,
		canvas_height: 1080
	};
}
function useTopologyFloorPlan(options) {
	const { floorPlanCode, enabled = true, subscribeFloorPlanPush = false } = options;
	const [floorPlanRemoteId, setFloorPlanRemoteId] = useState(null);
	const [savedSceneElements, setSavedSceneElements] = useState(void 0);
	const [savedEdges, setSavedEdges] = useState(void 0);
	const subscriberIdRef = useRef(getUniqueId("topology-floor-plan-code"));
	/**
	* 必须稳定引用：`useShopFloorPlanSubscription` 的 effect 依赖 ensureByCode，
	* 若每次 render 新建内联函数会反复 unsubscribe → 再订阅，形成 pisell_topology 与
	* unsubscribe 交替刷屏。
	*/
	const ensureByCode = useCallback((code, opts) => ensureShopFloorPlanByCode(code, _objectSpread2(_objectSpread2({}, opts), {}, { buildDefaultPostBody: buildEmptyTopologyFloorPlanPostBody })), []);
	const applyDetail = useCallback((detail) => {
		if (typeof detail.id === "number" && Number.isFinite(detail.id)) setFloorPlanRemoteId(Math.trunc(detail.id));
		const fromLayoutField = parseLayoutFieldToViewConfigPatch(detail.layout);
		if (fromLayoutField) {
			var _fromLayoutField$scen, _fromLayoutField$edge;
			setSavedSceneElements((_fromLayoutField$scen = fromLayoutField.sceneElements) !== null && _fromLayoutField$scen !== void 0 ? _fromLayoutField$scen : []);
			setSavedEdges((_fromLayoutField$edge = fromLayoutField.edges) !== null && _fromLayoutField$edge !== void 0 ? _fromLayoutField$edge : []);
			return;
		}
		/**
		* 兼容预约同款扁平 layout 数组（后端常存 ShopFloorPlanLayoutItem[]）。
		* 若按 ViewConfig 解析失败但 layout 是数组，则转成 sceneElements 再对账。
		*/
		if (Array.isArray(detail.layout)) {
			setSavedSceneElements(detail.layout.length > 0 ? shopLayoutToSceneElements(detail.layout, {
				canvasId: TOPOLOGY_MAIN_CANVAS_ID,
				dataSourceKey: TOPOLOGY_DEVICES_DATA_SOURCE_KEY,
				rectElementKind: TOPOLOGY_UNKNOWN_KIND,
				circleElementKind: TOPOLOGY_UNKNOWN_KIND
			}) : []);
			setSavedEdges([]);
			return;
		}
		setSavedSceneElements([]);
		setSavedEdges([]);
	}, []);
	/**
	* 关闭时清空，否则切换 code 时旧数据会泄漏成新 code 的 saved 基线。
	*/
	useEffect(() => {
		if (!enabled) {
			setFloorPlanRemoteId(null);
			setSavedSceneElements(void 0);
			setSavedEdges(void 0);
		}
	}, [enabled, floorPlanCode]);
	/** 非 WebPOS：单次 ensure（GET + 404 自动创建），不注册推送订阅 */
	useEffect(() => {
		if (!enabled || !floorPlanCode || subscribeFloorPlanPush) return;
		let cancelled = false;
		ensureByCode(floorPlanCode).then((detail) => {
			if (cancelled || !detail) return;
			applyDetail(detail);
		}).catch((err) => {
			if (!cancelled) toastFloorPlanLoadError(err);
		});
		return () => {
			cancelled = true;
		};
	}, [
		enabled,
		floorPlanCode,
		subscribeFloorPlanPush,
		ensureByCode,
		applyDetail
	]);
	useShopFloorPlanSubscription({
		enabled: enabled && !!floorPlanCode && subscribeFloorPlanPush,
		code: floorPlanCode,
		subscriberId: subscriberIdRef.current,
		ensureByCode,
		unsubscribeQuery: unsubscribeShopFloorPlanCodeQuery,
		onDetail: applyDetail,
		onLoadError: toastFloorPlanLoadError
	});
	const applyLocalSave = useCallback((params) => {
		setSavedSceneElements(params.sceneElements);
		setSavedEdges(params.edges);
	}, []);
	const setRemoteFloorPlanView = useCallback((patch) => {
		if (patch == null) {
			setSavedSceneElements(void 0);
			setSavedEdges(void 0);
			return;
		}
		if (patch.sceneElements != null) setSavedSceneElements(patch.sceneElements);
		if (patch.edges != null) setSavedEdges(patch.edges);
	}, []);
	return {
		floorPlanRemoteId,
		savedSceneElements,
		savedEdges,
		isLoaded: savedSceneElements !== void 0,
		applyLocalSave,
		setRemoteFloorPlanView
	};
}
//#endregion
export { useTopologyFloorPlan };
