var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
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 __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/pro/Selector/SelectorGroup.tsx
var SelectorGroup_exports = {};
__export(SelectorGroup_exports, {
  default: () => SelectorGroup_default
});
module.exports = __toCommonJS(SelectorGroup_exports);
var import_react = __toESM(require("react"));
var import_classnames = __toESM(require("classnames"));
var import_lodash = require("lodash");
var import_utils = require("@pisell/utils");
var import_locales = __toESM(require("./locales"));
var import_useEngineContext = __toESM(require("../../hooks/useEngineContext"));
var import_useThemeTokens = __toESM(require("../../hooks/useThemeTokens"));
var import_Selector = __toESM(require("./Selector"));
var import_utils2 = require("./utils");
var import_IntersectionObserver = require("./components/IntersectionObserver");
var import_CategoryTabs = __toESM(require("../../plus/productSelect/CategoryTabs"));
var import_utils3 = require("../../plus/productSelect/utils");
var import_selectorGroup = require("./selectorGroup.less");
var DEFAULT_DATASOURCE = [];
var SelectorGroup = (0, import_react.forwardRef)(
  (props, ref) => {
    var _a, _b, _c, _d;
    const context = (0, import_useEngineContext.default)();
    import_utils.locales.init(
      import_locales.default,
      ((_c = (_b = (_a = context == null ? void 0 : context.appHelper) == null ? void 0 : _a.utils) == null ? void 0 : _b.storage) == null ? void 0 : _c.get("umi_locale")) || "en"
    );
    const {
      linkageRules,
      allowedValuesPolicy = "strict",
      preserve: preserveDefault = false,
      style
    } = props;
    const { colorPrimary, colorPrimaryBg } = (0, import_useThemeTokens.default)(props.theme);
    const [activeIndex, setActiveIndex] = (0, import_react.useState)(-1);
    const isManualChangeIndexRef = (0, import_react.useRef)(false);
    const containerRef = (0, import_react.useRef)(null);
    const uniqueIdRef = (0, import_react.useRef)((0, import_utils2.generateSimpleUUID)().substring(0, 8));
    const _uniqueId = uniqueIdRef.current;
    const groupRefs = (0, import_react.useRef)({});
    const reducer = (state2, action) => {
      switch (action.type) {
        case "commit":
          return action.payload;
        case "patch":
          return { ...state2, ...action.payload };
        default:
          return state2;
      }
    };
    const [state, dispatch] = (0, import_react.useReducer)(reducer, {
      values: {},
      visibleGroups: {},
      optionEffects: {}
    });
    (0, import_react.useEffect)(() => {
      const initial = ((props == null ? void 0 : props.value) ?? (props == null ? void 0 : props.defaultValue)) || {};
      if (initial && typeof initial === "object") {
        applyValues({ ...initial });
      }
    }, []);
    const rulesStableKey = (0, import_react.useMemo)(() => {
      try {
        return JSON.stringify(linkageRules ?? null);
      } catch {
        return String(linkageRules);
      }
    }, [linkageRules]);
    const normalizedRules = (0, import_react.useMemo)(
      () => (0, import_utils2.normalizeRules)(linkageRules),
      [rulesStableKey]
    );
    const autoHiddenGroups = (0, import_react.useMemo)(
      () => (0, import_utils2.computeAutoHiddenGroups)(normalizedRules),
      [normalizedRules]
    );
    const dataSource = (0, import_react.useMemo)(() => {
      if (Array.isArray(props.dataSource)) {
        return props.dataSource.filter(
          (item) => !!item && item.id !== void 0
        );
      }
      return DEFAULT_DATASOURCE;
    }, [props.dataSource]);
    const stateRef = (0, import_react.useRef)(state);
    const dataSourceRef = (0, import_react.useRef)(dataSource);
    (0, import_react.useEffect)(() => {
      stateRef.current = state;
    }, [state]);
    (0, import_react.useEffect)(() => {
      dataSourceRef.current = dataSource;
    }, [dataSource]);
    const hasInitializedVisibilityRef = (0, import_react.useRef)(false);
    (0, import_react.useEffect)(() => {
      if (!hasInitializedVisibilityRef.current && (!state.visibleGroups || Object.keys(state.visibleGroups).length === 0)) {
        const initVisible = {};
        (dataSource || []).forEach((group) => {
          const gid = String(group.id ?? "");
          initVisible[gid] = autoHiddenGroups.has(gid) ? false : true;
        });
        hasInitializedVisibilityRef.current = true;
        dispatch({ type: "patch", payload: { visibleGroups: initVisible } });
      }
    }, [dataSource, autoHiddenGroups]);
    const lastEmittedRef = (0, import_react.useRef)(null);
    const applyValues = (0, import_react.useCallback)(
      (nextValues, visibleOverride) => {
        const maskValues = (vals, visibleMap) => {
          const out = {
            ...vals || {}
          };
          (dataSource || []).forEach((group) => {
            const gid = String(group.id ?? "");
            const preserve = typeof group.preserve === "boolean" ? group.preserve : preserveDefault;
            if (visibleMap[gid] === false && preserve === false)
              out[gid] = void 0;
          });
          return out;
        };
        const baseVisible = visibleOverride || state.visibleGroups;
        const valuesForEffects = maskValues(nextValues, baseVisible);
        const { visibleGroups: newVisible, optionEffects: newEffects } = (0, import_utils2.computeEffects)(
          dataSource,
          normalizedRules,
          valuesForEffects
        );
        let finalValues = nextValues;
        let finalVisible = newVisible;
        let finalEffects = newEffects;
        if (allowedValuesPolicy === "strict") {
          const pruned = (0, import_utils2.pruneValuesByAllowOnly)(nextValues, newEffects);
          const didPrune = !(0, import_lodash.isEqual)(pruned, nextValues);
          if (didPrune) {
            finalValues = pruned;
            const valuesForEffects2 = maskValues(finalValues, newVisible);
            const recomputed = (0, import_utils2.computeEffects)(
              dataSource,
              normalizedRules,
              valuesForEffects2
            );
            finalVisible = recomputed.visibleGroups;
            finalEffects = recomputed.optionEffects;
          }
        }
        const noStateChange = (0, import_lodash.isEqual)(state.values, finalValues) && (0, import_lodash.isEqual)(state.visibleGroups, finalVisible) && (0, import_lodash.isEqual)(state.optionEffects, finalEffects);
        if (!noStateChange) {
          dispatch({
            type: "commit",
            payload: {
              values: { ...finalValues || {} },
              visibleGroups: finalVisible,
              optionEffects: finalEffects
            }
          });
        }
        if (typeof (props == null ? void 0 : props.onChange) === "function") {
          const out = {};
          (dataSource || []).forEach((group) => {
            const gid = String(group.id ?? "");
            const preserve = typeof group.preserve === "boolean" ? group.preserve : preserveDefault;
            if (finalVisible[gid] === false && preserve === false) return;
            const v = finalValues[gid];
            if (v !== void 0) out[gid] = v;
          });
          if (!(0, import_lodash.isEqual)(lastEmittedRef.current, out)) {
            lastEmittedRef.current = out;
            props.onChange(out);
          }
        }
      },
      [
        dataSource,
        normalizedRules,
        allowedValuesPolicy,
        preserveDefault,
        state.visibleGroups,
        state.values,
        state.optionEffects,
        props == null ? void 0 : props.onChange
      ]
    );
    const getValuesInternal = (0, import_react.useCallback)(
      (includeHidden, visibleOverride) => {
        if (includeHidden) return { ...state.values || {} };
        const visibleMap = visibleOverride || state.visibleGroups;
        const result = {};
        (dataSource || []).forEach((group) => {
          const gid = String(group.id ?? "");
          const preserve = typeof group.preserve === "boolean" ? group.preserve : preserveDefault;
          if (visibleMap[gid] === false && preserve === false) return;
          const v = state.values[gid];
          if (v !== void 0) result[gid] = v;
        });
        return result;
      },
      [dataSource, state.visibleGroups, preserveDefault, state.values]
    );
    (0, import_react.useEffect)(() => {
      applyValues({ ...state.values || {} });
    }, [dataSource, normalizedRules, allowedValuesPolicy]);
    (0, import_react.useEffect)(() => {
      const external = props == null ? void 0 : props.value;
      if (external && typeof external === "object") {
        const prev = state.values || {};
        const next = external || {};
        const isDifferent = !(0, import_lodash.isEqual)(prev, next);
        if (isDifferent) {
          applyValues({ ...next });
        }
      }
    }, [props == null ? void 0 : props.value]);
    const handleGroupChange = (0, import_react.useCallback)(
      (groupId, v) => {
        const nextValues = { ...state.values || {}, [groupId]: v };
        applyValues(nextValues);
      },
      [state.values, applyValues]
    );
    const _categories = (0, import_react.useMemo)(() => {
      return dataSource.filter((item) => state.visibleGroups[String(item.id ?? "")] !== false).map((item) => {
        return { ...item, key: String(item.id ?? ""), label: item.title };
      });
    }, [dataSource, state.visibleGroups]);
    const debounceIndicator = (0, import_react.useCallback)((delay) => {
      isManualChangeIndexRef.current = true;
      const timeoutId = setTimeout(() => {
        isManualChangeIndexRef.current = false;
      }, delay);
      return () => clearTimeout(timeoutId);
    }, []);
    const switchCategory = (0, import_react.useCallback)(
      (key) => {
        const _idx = _categories.findIndex((item) => item.key === key);
        setActiveIndex(_idx);
        debounceIndicator(300);
        const categoryIndex = dataSource.findIndex(
          (item) => String(item.id) === key
        );
        let _scrollParent = null;
        if (typeof props.customScrollParent === "string") {
          _scrollParent = document.querySelector(
            props.customScrollParent
          );
        } else {
          _scrollParent = props.customScrollParent || containerRef.current;
        }
        if (!_scrollParent || !containerRef.current) return;
        const target = document.getElementById(`pisell-pro-selector-${key}`);
        if (!target) return;
        const batchSelectorWrapper = document.querySelector(
          `.pisell-batch-selector-${_uniqueId}`
        );
        const tabsWrapper = document.getElementById(
          `pisell-batch-selector-${_uniqueId}_tabs`
        );
        const tabsHeight = (tabsWrapper == null ? void 0 : tabsWrapper.offsetHeight) || 0;
        const extraOffset = 0;
        if (categoryIndex === 0) {
          if (batchSelectorWrapper) {
            const wrapperOffsetTop = (0, import_utils3.getOffsetTopRelativeToScrollContainer)(
              batchSelectorWrapper,
              _scrollParent
            );
            _scrollParent.scrollTop = wrapperOffsetTop - extraOffset;
          }
          return;
        } else {
          const listOffsetTop = (0, import_utils3.getOffsetTopRelativeToScrollContainer)(
            target,
            _scrollParent
          );
          _scrollParent.scrollTop = listOffsetTop - tabsHeight - extraOffset;
        }
      },
      [
        _categories,
        dataSource,
        debounceIndicator,
        props.customScrollParent,
        _uniqueId
      ]
    );
    (0, import_react.useImperativeHandle)(
      ref,
      () => ({
        getValues: (includeHidden) => getValuesInternal(includeHidden),
        setValues: (values) => {
          applyValues({ ...values || {} });
        },
        validate: async () => {
          const currentDataSource = dataSourceRef.current || [];
          const currentVisibleGroups = stateRef.current.visibleGroups;
          const validateGroup = async (ds) => {
            const gid = String(ds.id ?? "");
            const successResult = { gid, ok: true, errors: [] };
            if (currentVisibleGroups[gid] === false) {
              return successResult;
            }
            const inst = groupRefs.current[gid];
            if (!(inst == null ? void 0 : inst.validate)) {
              return successResult;
            }
            try {
              await inst.validate();
              return successResult;
            } catch (errors) {
              return {
                gid,
                ok: false,
                errors: Array.isArray(errors) ? errors : errors ? [errors] : []
              };
            }
          };
          const results = await Promise.all(
            currentDataSource.map(validateGroup)
          );
          const errorsByGroup = {};
          let firstErrorGID;
          for (const result of results) {
            if (!result.ok && result.errors.length > 0) {
              errorsByGroup[result.gid] = result.errors;
              if (!firstErrorGID) {
                firstErrorGID = result.gid;
              }
            }
          }
          const hasErrors = Object.keys(errorsByGroup).length > 0;
          if (hasErrors) {
            if (props.scrollToFirstError !== false && firstErrorGID) {
              switchCategory(firstErrorGID);
            }
            return Promise.reject(errorsByGroup);
          }
          return Promise.resolve({});
        },
        reset: () => {
          const nextValues = (props == null ? void 0 : props.defaultValue) || {};
          applyValues({ ...nextValues || {} });
          Object.keys(groupRefs.current).forEach((gid) => {
            var _a2;
            const inst = groupRefs.current[gid];
            (_a2 = inst == null ? void 0 : inst.reset) == null ? void 0 : _a2.call(inst);
          });
        },
        clear: () => {
          applyValues({});
          Object.keys(groupRefs.current).forEach((gid) => {
            var _a2;
            const inst = groupRefs.current[gid];
            (_a2 = inst == null ? void 0 : inst.clear) == null ? void 0 : _a2.call(inst);
          });
        }
      }),
      [
        getValuesInternal,
        applyValues,
        props.scrollToFirstError,
        props == null ? void 0 : props.defaultValue,
        switchCategory
      ]
    );
    const patchedDataSourceMap = (0, import_react.useMemo)(() => {
      const map = {};
      (dataSource || []).forEach((group) => {
        var _a2;
        const gid = String(group.id ?? "");
        const fieldValue = ((_a2 = group == null ? void 0 : group.fieldNames) == null ? void 0 : _a2.value) || "value";
        const effects = state.optionEffects[gid];
        const ds = Array.isArray(group.dataSource) ? group.dataSource : [];
        map[gid] = ds.map((opt) => {
          const val = opt[fieldValue];
          const notAllowed = (effects == null ? void 0 : effects.allowOnly) && !effects.allowOnly.has(val);
          return notAllowed ? { ...opt, disabled: true } : opt;
        });
      });
      return map;
    }, [dataSource, state.optionEffects]);
    const validationMaps = (0, import_react.useMemo)(() => {
      const titleTipMap = {};
      const customValidatorMap = {};
      (dataSource || []).forEach((group) => {
        var _a2, _b2;
        const gid = String(group.id ?? "");
        const req = (_a2 = state.optionEffects[gid]) == null ? void 0 : _a2.requireOneOf;
        if (req) {
          const currentSel = (0, import_utils2.getSelectedSet)((_b2 = state.values) == null ? void 0 : _b2[gid]);
          const ok = [...req.values].some((v) => currentSel.has(v));
          titleTipMap[gid] = ok ? void 0 : req.tip || import_utils.locales.getText("pisell2.pro.selector.validate.requireOneOf-msg");
          customValidatorMap[gid] = async (value) => {
            const sel = (0, import_utils2.getSelectedSet)(value);
            const match = [...req.values].some((v) => sel.has(v));
            if (!match) {
              throw {
                type: "requireOneOf",
                message: req.message || import_utils.locales.getText(
                  "pisell2.pro.selector.validate.requireOneOf-msg"
                )
              };
            }
          };
        } else {
          titleTipMap[gid] = void 0;
          customValidatorMap[gid] = void 0;
        }
      });
      return { titleTipMap, customValidatorMap };
    }, [dataSource, state.optionEffects, state.values]);
    const activeKey = (0, import_react.useMemo)(() => {
      var _a2;
      return (_a2 = _categories[activeIndex]) == null ? void 0 : _a2.key;
    }, [activeIndex, _categories]);
    const renderTabs = () => {
      var _a2;
      if (((_a2 = props.tabProps) == null ? void 0 : _a2.visible) === false) return null;
      if ((props.dataSource || []).length <= 1) return null;
      return /* @__PURE__ */ import_react.default.createElement(
        import_CategoryTabs.default,
        {
          activeKey: activeKey ? String(activeKey) : "",
          items: _categories,
          onChange: switchCategory,
          loading: props.loading,
          skeleton: /* @__PURE__ */ import_react.default.createElement(import_CategoryTabs.CategorySkeleton, null),
          id: `pisell-batch-selector-${_uniqueId}_tabs`
        }
      );
    };
    const _content = (0, import_react.useMemo)(() => {
      return /* @__PURE__ */ import_react.default.createElement("div", { className: `pisell-batch-selector__content` }, dataSource.filter(
        (item) => state.visibleGroups[String(item.id ?? "")] !== false
      ).map((item, index) => {
        var _a2, _b2;
        const gid = String(item.id ?? "");
        const headerProps = item.headerProps || item.titleProps || {};
        return /* @__PURE__ */ import_react.default.createElement(import_IntersectionObserver.IntersectionItem, { key: gid, index }, /* @__PURE__ */ import_react.default.createElement(
          import_Selector.default,
          {
            ...item,
            ref: (el) => {
              if (el) {
                groupRefs.current[gid] = el;
              } else {
                delete groupRefs.current[gid];
              }
            },
            value: (_a2 = state.values) == null ? void 0 : _a2[gid],
            onChange: (v) => {
              var _a3;
              handleGroupChange(gid, v);
              (_a3 = item.onChange) == null ? void 0 : _a3.call(item, v);
            },
            ruleConfig: {
              ...item.ruleConfig,
              customValidator: validationMaps.customValidatorMap[gid]
            },
            dataSource: patchedDataSourceMap[gid],
            headerProps: {
              ...headerProps,
              ...validationMaps.titleTipMap[gid] === void 0 ? {} : {
                tip: {
                  ...(headerProps == null ? void 0 : headerProps.tip) || {},
                  text: validationMaps.titleTipMap[gid],
                  visible: ((_b2 = headerProps == null ? void 0 : headerProps.tip) == null ? void 0 : _b2.visible) ?? true
                }
              }
            }
          }
        ));
      }));
    }, [
      dataSource,
      state.visibleGroups,
      state.values,
      patchedDataSourceMap,
      validationMaps,
      groupRefs,
      handleGroupChange
    ]);
    return /* @__PURE__ */ import_react.default.createElement(
      "div",
      {
        className: (0, import_classnames.default)(
          "pisell-batch-selector",
          `pisell-batch-selector-${_uniqueId}`
        ),
        ref: containerRef,
        style: {
          ...style || {},
          ["--color-primary"]: colorPrimary,
          ["--color-primary-bg"]: colorPrimaryBg
        }
      },
      renderTabs(),
      /* @__PURE__ */ import_react.default.createElement(
        import_IntersectionObserver.IntersectionObserverProvider,
        {
          rootMargin: "-70px 0px 0px 0px",
          disabled: ((_d = props.tabProps) == null ? void 0 : _d.visible) === false,
          onFirstVisibleIndexChange: (index) => {
            if (!isManualChangeIndexRef.current) {
              if (index === -1 || index === activeIndex) return;
              setActiveIndex(index);
            }
          }
        },
        _content
      )
    );
  }
);
var SelectorGroup_default = SelectorGroup;
