require("../../../../_virtual/_rolldown/runtime.js");
const require_objectSpread2 = require("../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
const require_asyncToGenerator = require("../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js");
const require_peripheralRuntime = require("../utils/peripheralRuntime.js");
const require_peripheralConnectionService = require("../services/peripheralConnectionService.js");
let react = require("react");
let _pisell_materials = require("@pisell/materials");
let ahooks = require("ahooks");
//#region src/plus/saasDevice/appPeripheral/hooks/usePeripheralRuntime.ts
const isLabelPrinter = (connection) => {
	var _connection$target_de;
	return ((_connection$target_de = connection.target_device) === null || _connection$target_de === void 0 ? void 0 : _connection$target_de.type_code) === "label_printer";
};
const hasPeripheralUsage = (row) => Boolean(row.usage);
const usePeripheralRuntime = ({ row, getAppInstance, getText, onPhysicalChange, onUsageChange }) => {
	const [runtimeState, setRuntimeState] = (0, react.useState)();
	const [physicalSelect, setPhysicalSelect] = (0, react.useState)();
	const [printUsageSelect, setPrintUsageSelect] = (0, react.useState)();
	const inspectingRef = (0, react.useRef)(/* @__PURE__ */ new Set());
	const bootstrappedRef = (0, react.useRef)(/* @__PURE__ */ new Set());
	const markedDisconnectedRef = (0, react.useRef)(/* @__PURE__ */ new Set());
	/** 监听回调中读取最新 row，避免闭包拿到旧 physical/usage。 */
	const rowRef = (0, react.useRef)(row);
	/** 外设插件只在 runtime hook 内访问，UI 层不感知插件细节。 */
	const getPeripheralPlugin = (0, ahooks.useMemoizedFn)(() => {
		var _getAppInstance, _getAppInstance$getPl;
		return (_getAppInstance = getAppInstance()) === null || _getAppInstance === void 0 || (_getAppInstance$getPl = _getAppInstance.getPlugin) === null || _getAppInstance$getPl === void 0 ? void 0 : _getAppInstance$getPl.call(_getAppInstance, "peripheral");
	});
	/** 当前卡片内的瞬时状态，父级 rows 只保存稳定的 physical/usage。 */
	const patchRuntimeState = (0, ahooks.useMemoizedFn)((state) => {
		setRuntimeState((prev) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, prev), state));
	});
	/** 服务层写入云端/SQLite 后，将稳定状态同步回父级 row。 */
	const applyBinding = (0, ahooks.useMemoizedFn)((nextRow, binding) => {
		onPhysicalChange(nextRow.id, binding.physical_device);
		onUsageChange(nextRow.id, binding.peripheral_usage);
		patchRuntimeState({
			status: binding.is_connect ? "connected" : "disconnected",
			physicalDevice: binding.physical_device,
			loading: false
		});
	});
	/** 连接、断开、测试都以 row.physical 为优先物理设备来源。 */
	const getKnownPhysicalDevice = (0, ahooks.useMemoizedFn)((targetRow) => (runtimeState === null || runtimeState === void 0 ? void 0 : runtimeState.physicalDevice) || targetRow.physical);
	/** 按 connection 配置调用插件查找物理设备，结果只返回给 runtime 流程。 */
	const findPhysicalDevices = (0, ahooks.useMemoizedFn)(function() {
		var _ref = require_asyncToGenerator._asyncToGenerator(function* (targetConnection, uuid) {
			const plugin = getPeripheralPlugin();
			if (!(plugin === null || plugin === void 0 ? void 0 : plugin.findList)) throw new Error("Peripheral plugin is not available.");
			const requests = ["CONNECTED", "NOT_CONNECT"].map((status) => require_peripheralRuntime.buildFindListParams(targetConnection, status, uuid)).filter(Boolean);
			if (!requests.length) return [];
			return require_peripheralRuntime.uniquePeripheralDevices((yield Promise.allSettled(requests.map((params) => {
				var _plugin$findList;
				return (_plugin$findList = plugin.findList) === null || _plugin$findList === void 0 ? void 0 : _plugin$findList.call(plugin, params);
			}))).flatMap((result) => {
				var _result$value;
				if (result.status !== "fulfilled") return [];
				const devices = (_result$value = result.value) === null || _result$value === void 0 ? void 0 : _result$value.data;
				return Array.isArray(devices) ? devices : [];
			}));
		});
		return function(_x, _x2) {
			return _ref.apply(this, arguments);
		};
	}());
	/** 同一轮自动探测中，同一个 row 只静默上报一次 disconnected。 */
	const markDisconnectedOnce = (0, ahooks.useMemoizedFn)(function() {
		var _ref2 = require_asyncToGenerator._asyncToGenerator(function* (targetRow, physicalDevice) {
			if (markedDisconnectedRef.current.has(targetRow.id)) return;
			markedDisconnectedRef.current.add(targetRow.id);
			applyBinding(targetRow, (yield require_peripheralConnectionService.disconnectPeripheralConnection({
				app: getAppInstance(),
				connection: targetRow.connection,
				physicalDevice: physicalDevice || getKnownPhysicalDevice(targetRow)
			})).binding);
		});
		return function(_x3, _x4) {
			return _ref2.apply(this, arguments);
		};
	}());
	/** 统一处理连接失败提示，自动流程默认静默。 */
	const showConnectFailed = (0, ahooks.useMemoizedFn)((silent) => {
		if (silent) return;
		(0, _pisell_materials.PisellToast)({
			content: getText("pisell2.saas.app-peripheral.connect-failed"),
			duration: 2
		});
	});
	/** 调用插件 connect，并把成功结果写入云端、SQLite 和父级 row。 */
	const connectPhysicalDevice = (0, ahooks.useMemoizedFn)(function() {
		var _ref3 = require_asyncToGenerator._asyncToGenerator(function* (targetRow, physicalDevice, peripheralUsage, options = {}) {
			patchRuntimeState({
				status: "connecting",
				physicalDevice: "is_connect" in physicalDevice ? physicalDevice : void 0,
				loading: true
			});
			try {
				const nextUsage = peripheralUsage !== null && peripheralUsage !== void 0 ? peripheralUsage : isLabelPrinter(targetRow.connection) ? rowRef.current.usage : void 0;
				const result = yield require_peripheralConnectionService.connectPeripheralConnection({
					app: getAppInstance(),
					plugin: getPeripheralPlugin(),
					connection: targetRow.connection,
					target: physicalDevice,
					peripheralUsage: nextUsage
				});
				markedDisconnectedRef.current.delete(targetRow.id);
				applyBinding(targetRow, result.binding);
				patchRuntimeState({
					status: "connected",
					physicalDevice: result.physicalDevice,
					loading: false
				});
				const needsUsage = isLabelPrinter(targetRow.connection) && !peripheralUsage && !hasPeripheralUsage(targetRow);
				if (needsUsage && options.promptUsage) setPrintUsageSelect({
					row: targetRow,
					physicalDevice: result.physicalDevice
				});
				if (!options.silent && !needsUsage) (0, _pisell_materials.PisellToast)({
					content: getText("pisell2.saas.app-peripheral.connect-success"),
					duration: 2
				});
				return result;
			} catch (e) {
				patchRuntimeState({
					status: "disconnected",
					physicalDevice: "is_connect" in physicalDevice ? physicalDevice : void 0,
					loading: false
				});
				throw e;
			}
		});
		return function(_x5, _x6, _x7) {
			return _ref3.apply(this, arguments);
		};
	}());
	/** 连接失败时静默/手动上报 disconnected，保证云端状态收敛。 */
	const connectOrMarkDisconnected = (0, ahooks.useMemoizedFn)(function() {
		var _ref4 = require_asyncToGenerator._asyncToGenerator(function* (targetRow, target, options = {}) {
			try {
				yield connectPhysicalDevice(targetRow, target, void 0, options);
			} catch (e) {
				yield markDisconnectedOnce(targetRow, "is_connect" in target ? target : void 0);
				showConnectFailed(options.silent);
			}
		});
		return function(_x8, _x9) {
			return _ref4.apply(this, arguments);
		};
	}());
	/** 用户从多候选物理设备中选择后，复用同一套连接流程。 */
	const connectSelectedPhysicalDevice = (0, ahooks.useMemoizedFn)(function() {
		var _ref5 = require_asyncToGenerator._asyncToGenerator(function* (targetRow, physicalDevice) {
			yield connectOrMarkDisconnected(targetRow, physicalDevice, { promptUsage: true });
		});
		return function(_x10, _x11) {
			return _ref5.apply(this, arguments);
		};
	}());
	/** 卡片 mount 和手动 Connect 的主入口：优先 uuid，其次手动 ip，最后自动发现。 */
	const handleConnectPeripheral = (0, ahooks.useMemoizedFn)(function() {
		var _ref6 = require_asyncToGenerator._asyncToGenerator(function* (targetRow, auto = false) {
			if (inspectingRef.current.has(targetRow.id)) return;
			if (auto && bootstrappedRef.current.has(targetRow.id)) return;
			if (auto) bootstrappedRef.current.add(targetRow.id);
			inspectingRef.current.add(targetRow.id);
			patchRuntimeState({
				status: "connecting",
				loading: true
			});
			try {
				var _targetRow$connection;
				const knownPhysicalDevice = getKnownPhysicalDevice(targetRow);
				const effectiveUuid = (knownPhysicalDevice === null || knownPhysicalDevice === void 0 ? void 0 : knownPhysicalDevice.uuid) || require_peripheralRuntime.getPeripheralUuid(targetRow.connection);
				const ip = (knownPhysicalDevice === null || knownPhysicalDevice === void 0 ? void 0 : knownPhysicalDevice.ip) || require_peripheralRuntime.getPeripheralIp(targetRow.connection);
				const options = {
					silent: auto,
					promptUsage: !auto
				};
				if (effectiveUuid) {
					yield connectOrMarkDisconnected(targetRow, (yield findPhysicalDevices(targetRow.connection, effectiveUuid)).find((device) => device.uuid === effectiveUuid) || knownPhysicalDevice || {
						uuid: effectiveUuid,
						ip
					}, options);
					return;
				}
				if (ip && ((_targetRow$connection = targetRow.connection.config) === null || _targetRow$connection === void 0 ? void 0 : _targetRow$connection.connection_method) === "manual") {
					yield connectOrMarkDisconnected(targetRow, { ip }, options);
					return;
				}
				const devices = yield findPhysicalDevices(targetRow.connection);
				const matchedDevices = ip ? devices.filter((device) => device.ip === ip) : devices;
				const candidates = matchedDevices.length ? matchedDevices : devices;
				if (!candidates.length) {
					yield markDisconnectedOnce(targetRow);
					showConnectFailed(auto);
					return;
				}
				if (candidates.length === 1) {
					yield connectOrMarkDisconnected(targetRow, candidates[0], options);
					return;
				}
				patchRuntimeState({
					status: "select",
					candidates,
					loading: false
				});
			} catch (e) {
				patchRuntimeState({
					status: "disconnected",
					loading: false
				});
				showConnectFailed(auto);
			} finally {
				inspectingRef.current.delete(targetRow.id);
			}
		});
		return function(_x12) {
			return _ref6.apply(this, arguments);
		};
	}());
	/** 已连接 label_printer 缺 usage 时打开用途选择。 */
	const handleOpenUsageSelect = (0, ahooks.useMemoizedFn)((targetRow) => {
		const physicalDevice = getKnownPhysicalDevice(targetRow);
		if (!physicalDevice) return;
		setPrintUsageSelect({
			row: targetRow,
			physicalDevice
		});
	});
	/** usage 只更新 SQLite 和 row，不重复调用插件 connect。 */
	const handleSelectPeripheralUsage = (0, ahooks.useMemoizedFn)(function() {
		var _ref7 = require_asyncToGenerator._asyncToGenerator(function* (usage) {
			if (!printUsageSelect) return;
			const nextState = printUsageSelect;
			const physicalDevice = "is_connect" in nextState.physicalDevice ? nextState.physicalDevice : getKnownPhysicalDevice(nextState.row);
			patchRuntimeState({
				status: "connected",
				physicalDevice,
				loading: true
			});
			try {
				const result = yield require_peripheralConnectionService.updatePeripheralUsage({
					app: getAppInstance(),
					connection: nextState.row.connection,
					physicalDevice,
					peripheralUsage: usage
				});
				applyBinding(nextState.row, result.binding);
				setPrintUsageSelect(void 0);
				(0, _pisell_materials.PisellToast)({
					content: getText("pisell2.saas.app-peripheral.connect-success"),
					duration: 2
				});
			} catch (e) {
				(0, _pisell_materials.PisellToast)({
					content: getText("pisell2.saas.app-peripheral.connect-failed"),
					duration: 2
				});
				patchRuntimeState({
					status: "connected",
					physicalDevice,
					loading: false
				});
			}
		});
		return function(_x13) {
			return _ref7.apply(this, arguments);
		};
	}());
	/** 用户确认断开后，更新云端、SQLite 和当前 row 的 physical。 */
	const handleDisconnectPeripheral = (0, ahooks.useMemoizedFn)(function() {
		var _ref8 = require_asyncToGenerator._asyncToGenerator(function* (targetRow) {
			try {
				const result = yield require_peripheralConnectionService.disconnectPeripheralConnection({
					app: getAppInstance(),
					connection: targetRow.connection,
					physicalDevice: getKnownPhysicalDevice(targetRow)
				});
				markedDisconnectedRef.current.add(targetRow.id);
				applyBinding(targetRow, result.binding);
				patchRuntimeState({
					status: "disconnected",
					physicalDevice: result.physicalDevice,
					loading: false
				});
				(0, _pisell_materials.PisellToast)({
					content: getText("pisell2.saas.app-peripheral.disconnect-success"),
					duration: 2
				});
			} catch (e) {
				(0, _pisell_materials.PisellToast)({
					content: getText("pisell2.saas.app-peripheral.disconnect-failed"),
					duration: 2
				});
			}
		});
		return function(_x14) {
			return _ref8.apply(this, arguments);
		};
	}());
	(0, react.useEffect)(() => {
		rowRef.current = row;
	}, [row]);
	/** 父级订阅同步 row.physical 后，非交互态 overlay 跟随稳定状态。 */
	(0, react.useEffect)(() => {
		setRuntimeState((prev) => {
			var _prev$physicalDevice, _prev$physicalDevice2, _prev$physicalDevice3;
			if (!prev || prev.loading || prev.status === "select") return prev;
			if (!row.physical) return void 0;
			const nextStatus = row.physical.is_connect ? "connected" : "disconnected";
			if (prev.status === nextStatus && ((_prev$physicalDevice = prev.physicalDevice) === null || _prev$physicalDevice === void 0 ? void 0 : _prev$physicalDevice.uuid) === row.physical.uuid && ((_prev$physicalDevice2 = prev.physicalDevice) === null || _prev$physicalDevice2 === void 0 ? void 0 : _prev$physicalDevice2.is_connect) === row.physical.is_connect && ((_prev$physicalDevice3 = prev.physicalDevice) === null || _prev$physicalDevice3 === void 0 ? void 0 : _prev$physicalDevice3.status_code) === row.physical.status_code) return prev;
			return {
				status: nextStatus,
				physicalDevice: row.physical,
				loading: false
			};
		});
	}, [row.physical]);
	/** 每张卡片只在首次 mount 时自动检查一次物理设备状态。 */
	(0, react.useEffect)(() => {
		handleConnectPeripheral(row, true);
	}, [row.id, handleConnectPeripheral]);
	return {
		runtimeState,
		physicalSelect,
		printUsageSelect,
		isRuntimeSubmitting: Boolean(runtimeState === null || runtimeState === void 0 ? void 0 : runtimeState.loading),
		setPhysicalSelect,
		setPrintUsageSelect,
		handleConnectPeripheral,
		handleDisconnectPeripheral,
		handleOpenUsageSelect,
		handleSelectPeripheralUsage,
		connectSelectedPhysicalDevice
	};
};
//#endregion
exports.usePeripheralRuntime = usePeripheralRuntime;
