var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/plus/saasDevice/appPeripheral/hooks/usePeripheralRuntime.ts
var usePeripheralRuntime_exports = {};
__export(usePeripheralRuntime_exports, {
  usePeripheralRuntime: () => usePeripheralRuntime
});
module.exports = __toCommonJS(usePeripheralRuntime_exports);
var import_react = require("react");
var import_ahooks = require("ahooks");
var import_materials = require("@pisell/materials");
var import_peripheralConnectionService = require("../services/peripheralConnectionService");
var import_peripheralRuntime = require("../utils/peripheralRuntime");
var isLabelPrinter = (connection) => {
  var _a;
  return ((_a = connection.target_device) == null ? void 0 : _a.type_code) === "label_printer";
};
var hasPeripheralUsage = (row) => Boolean(row.usage);
var usePeripheralRuntime = ({
  row,
  getAppInstance,
  getText,
  onPhysicalChange,
  onUsageChange
}) => {
  const [runtimeState, setRuntimeState] = (0, import_react.useState)();
  const [physicalSelect, setPhysicalSelect] = (0, import_react.useState)();
  const [printUsageSelect, setPrintUsageSelect] = (0, import_react.useState)();
  const inspectingRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
  const bootstrappedRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
  const markedDisconnectedRef = (0, import_react.useRef)(/* @__PURE__ */ new Set());
  const rowRef = (0, import_react.useRef)(row);
  const getPeripheralPlugin = (0, import_ahooks.useMemoizedFn)(
    () => {
      var _a, _b;
      return (_b = (_a = getAppInstance()) == null ? void 0 : _a.getPlugin) == null ? void 0 : _b.call(_a, "peripheral");
    }
  );
  const patchRuntimeState = (0, import_ahooks.useMemoizedFn)((state) => {
    setRuntimeState((prev) => ({
      ...prev,
      ...state
    }));
  });
  const applyBinding = (0, import_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
      });
    }
  );
  const getKnownPhysicalDevice = (0, import_ahooks.useMemoizedFn)(
    (targetRow) => (runtimeState == null ? void 0 : runtimeState.physicalDevice) || targetRow.physical
  );
  const findPhysicalDevices = (0, import_ahooks.useMemoizedFn)(
    async (targetConnection, uuid) => {
      const plugin = getPeripheralPlugin();
      if (!(plugin == null ? void 0 : plugin.findList)) {
        throw new Error("Peripheral plugin is not available.");
      }
      const statuses = ["CONNECTED", "NOT_CONNECT"];
      const requests = statuses.map((status) => (0, import_peripheralRuntime.buildFindListParams)(targetConnection, status, uuid)).filter(Boolean);
      if (!requests.length) return [];
      const results = await Promise.allSettled(
        requests.map((params) => {
          var _a;
          return (_a = plugin.findList) == null ? void 0 : _a.call(plugin, params);
        })
      );
      return (0, import_peripheralRuntime.uniquePeripheralDevices)(
        results.flatMap((result) => {
          var _a;
          if (result.status !== "fulfilled") return [];
          const devices = (_a = result.value) == null ? void 0 : _a.data;
          return Array.isArray(devices) ? devices : [];
        })
      );
    }
  );
  const markDisconnectedOnce = (0, import_ahooks.useMemoizedFn)(
    async (targetRow, physicalDevice) => {
      if (markedDisconnectedRef.current.has(targetRow.id)) return;
      markedDisconnectedRef.current.add(targetRow.id);
      const result = await (0, import_peripheralConnectionService.disconnectPeripheralConnection)({
        app: getAppInstance(),
        connection: targetRow.connection,
        physicalDevice: physicalDevice || getKnownPhysicalDevice(targetRow)
      });
      applyBinding(targetRow, result.binding);
    }
  );
  const showConnectFailed = (0, import_ahooks.useMemoizedFn)((silent) => {
    if (silent) return;
    (0, import_materials.PisellToast)({
      content: getText("pisell2.saas.app-peripheral.connect-failed"),
      duration: 2
    });
  });
  const connectPhysicalDevice = (0, import_ahooks.useMemoizedFn)(
    async (targetRow, physicalDevice, peripheralUsage, options = {}) => {
      patchRuntimeState({
        status: "connecting",
        physicalDevice: "is_connect" in physicalDevice ? physicalDevice : void 0,
        loading: true
      });
      try {
        const nextUsage = peripheralUsage ?? (isLabelPrinter(targetRow.connection) ? rowRef.current.usage : void 0);
        const result = await (0, import_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, import_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;
      }
    }
  );
  const connectOrMarkDisconnected = (0, import_ahooks.useMemoizedFn)(
    async (targetRow, target, options = {}) => {
      try {
        await connectPhysicalDevice(targetRow, target, void 0, options);
      } catch (e) {
        await markDisconnectedOnce(
          targetRow,
          "is_connect" in target ? target : void 0
        );
        showConnectFailed(options.silent);
      }
    }
  );
  const connectSelectedPhysicalDevice = (0, import_ahooks.useMemoizedFn)(
    async (targetRow, physicalDevice) => {
      await connectOrMarkDisconnected(targetRow, physicalDevice, {
        promptUsage: true
      });
    }
  );
  const handleConnectPeripheral = (0, import_ahooks.useMemoizedFn)(
    async (targetRow, auto = false) => {
      var _a;
      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 {
        const knownPhysicalDevice = getKnownPhysicalDevice(targetRow);
        const effectiveUuid = (knownPhysicalDevice == null ? void 0 : knownPhysicalDevice.uuid) || (0, import_peripheralRuntime.getPeripheralUuid)(targetRow.connection);
        const ip = (knownPhysicalDevice == null ? void 0 : knownPhysicalDevice.ip) || (0, import_peripheralRuntime.getPeripheralIp)(targetRow.connection);
        const options = {
          silent: auto,
          promptUsage: !auto
        };
        if (effectiveUuid) {
          const devices2 = await findPhysicalDevices(
            targetRow.connection,
            effectiveUuid
          );
          const physicalDevice = devices2.find((device) => device.uuid === effectiveUuid) || knownPhysicalDevice;
          const target = physicalDevice || { uuid: effectiveUuid, ip };
          await connectOrMarkDisconnected(targetRow, target, options);
          return;
        }
        if (ip && ((_a = targetRow.connection.config) == null ? void 0 : _a.connection_method) === "manual") {
          await connectOrMarkDisconnected(targetRow, { ip }, options);
          return;
        }
        const devices = await findPhysicalDevices(targetRow.connection);
        const matchedDevices = ip ? devices.filter((device) => device.ip === ip) : devices;
        const candidates = matchedDevices.length ? matchedDevices : devices;
        if (!candidates.length) {
          await markDisconnectedOnce(targetRow);
          showConnectFailed(auto);
          return;
        }
        if (candidates.length === 1) {
          await 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);
      }
    }
  );
  const handleOpenUsageSelect = (0, import_ahooks.useMemoizedFn)(
    (targetRow) => {
      const physicalDevice = getKnownPhysicalDevice(targetRow);
      if (!physicalDevice) return;
      setPrintUsageSelect({
        row: targetRow,
        physicalDevice
      });
    }
  );
  const handleSelectPeripheralUsage = (0, import_ahooks.useMemoizedFn)(
    async (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 = await (0, import_peripheralConnectionService.updatePeripheralUsage)({
          app: getAppInstance(),
          connection: nextState.row.connection,
          physicalDevice,
          peripheralUsage: usage
        });
        applyBinding(nextState.row, result.binding);
        setPrintUsageSelect(void 0);
        (0, import_materials.PisellToast)({
          content: getText("pisell2.saas.app-peripheral.connect-success"),
          duration: 2
        });
      } catch (e) {
        (0, import_materials.PisellToast)({
          content: getText("pisell2.saas.app-peripheral.connect-failed"),
          duration: 2
        });
        patchRuntimeState({
          status: "connected",
          physicalDevice,
          loading: false
        });
      }
    }
  );
  const handleDisconnectPeripheral = (0, import_ahooks.useMemoizedFn)(
    async (targetRow) => {
      try {
        const result = await (0, import_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, import_materials.PisellToast)({
          content: getText("pisell2.saas.app-peripheral.disconnect-success"),
          duration: 2
        });
      } catch (e) {
        (0, import_materials.PisellToast)({
          content: getText("pisell2.saas.app-peripheral.disconnect-failed"),
          duration: 2
        });
      }
    }
  );
  (0, import_react.useEffect)(() => {
    rowRef.current = row;
  }, [row]);
  (0, import_react.useEffect)(() => {
    setRuntimeState((prev) => {
      var _a, _b, _c;
      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 && ((_a = prev.physicalDevice) == null ? void 0 : _a.uuid) === row.physical.uuid && ((_b = prev.physicalDevice) == null ? void 0 : _b.is_connect) === row.physical.is_connect && ((_c = prev.physicalDevice) == null ? void 0 : _c.status_code) === row.physical.status_code) {
        return prev;
      }
      return {
        status: nextStatus,
        physicalDevice: row.physical,
        loading: false
      };
    });
  }, [row.physical]);
  (0, import_react.useEffect)(() => {
    handleConnectPeripheral(row, true);
  }, [row.id, handleConnectPeripheral]);
  const isRuntimeSubmitting = Boolean(runtimeState == null ? void 0 : runtimeState.loading);
  return {
    runtimeState,
    physicalSelect,
    printUsageSelect,
    isRuntimeSubmitting,
    setPhysicalSelect,
    setPrintUsageSelect,
    handleConnectPeripheral,
    handleDisconnectPeripheral,
    handleOpenUsageSelect,
    handleSelectPeripheralUsage,
    connectSelectedPhysicalDevice
  };
};
// Annotate the CommonJS export names for ESM import in node:
0 && (module.exports = {
  usePeripheralRuntime
});
