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/pro/Selector/hooks/useSelectionController.ts
var useSelectionController_exports = {};
__export(useSelectionController_exports, {
  default: () => useSelectionController
});
module.exports = __toCommonJS(useSelectionController_exports);
var import_react = require("react");
var import_ahooks = require("ahooks");
var import_utils = require("@pisell/utils");
function useSelectionController(props) {
  const {
    dataSource = [],
    ruleConfig,
    fieldNames,
    mode = "single",
    valueType = "primitive"
  } = props || {};
  const [values, setValues] = (0, import_ahooks.useControllableValue)(props);
  const valuesRef = (0, import_react.useRef)(values);
  valuesRef.current = values;
  const [errors, setErrors] = (0, import_react.useState)([]);
  const [validated, setValidated] = (0, import_react.useState)(false);
  const normalizedOptions = (0, import_react.useMemo)(() => {
    return dataSource.map((option) => ({
      ...option,
      _key: option[(fieldNames == null ? void 0 : fieldNames.value) || "value"],
      _label: option[(fieldNames == null ? void 0 : fieldNames.label) || "label"],
      _cover: option[(fieldNames == null ? void 0 : fieldNames.cover) || "cover"]
    }));
  }, [dataSource, fieldNames]);
  const mutexGroups = (0, import_react.useMemo)(() => {
    const groups = [];
    const m = ruleConfig == null ? void 0 : ruleConfig.mutex;
    if (Array.isArray(m)) {
      m.forEach((g) => {
        if (Array.isArray(g) && g.length > 0) {
          groups.push(g);
        }
      });
    }
    return groups;
  }, [ruleConfig]);
  const mutexIndex = (0, import_react.useMemo)(() => {
    const map = /* @__PURE__ */ new Map();
    mutexGroups.forEach((group, idx) => {
      group.forEach((k) => {
        const arr = map.get(k) || [];
        arr.push(idx);
        map.set(k, arr);
      });
    });
    return map;
  }, [mutexGroups]);
  const normalizedValues = (0, import_react.useMemo)(() => {
    if (!values) return [];
    if (Array.isArray(values)) {
      return values.map((item) => {
        if (typeof item === "object" && item !== null) {
          return {
            ...item,
            // 保留原有的所有字段
            value: item.value,
            quantity: item.quantity || 1
          };
        }
        return { value: item, quantity: 1 };
      });
    }
    if (typeof values === "object" && values !== null) {
      const objValue = values;
      return [
        {
          ...objValue,
          // 保留原有的所有字段
          value: objValue.value,
          quantity: objValue.quantity || 1
        }
      ];
    }
    return [{ value: values, quantity: 1 }];
  }, [values]);
  const quantityInfo = (0, import_react.useMemo)(() => {
    const selectedCount = normalizedValues.reduce(
      (sum, item) => sum + (item.quantity || 0),
      0
    );
    const list = Array.isArray(dataSource) ? dataSource : dataSource || [];
    const showQuantity = list.some(
      (opt) => {
        var _a, _b;
        return typeof ((_a = opt == null ? void 0 : opt.ruleConfig) == null ? void 0 : _a.max) === "number" && opt.ruleConfig.max > 1 || typeof ((_b = opt == null ? void 0 : opt.ruleConfig) == null ? void 0 : _b.min) === "number" && opt.ruleConfig.min > 1;
      }
    );
    const maxReached = typeof (ruleConfig == null ? void 0 : ruleConfig.max) === "number" && ruleConfig.max > 0 && selectedCount >= ruleConfig.max;
    const remainingCount = typeof (ruleConfig == null ? void 0 : ruleConfig.max) === "number" && ruleConfig.max > 0 ? Math.max(0, ruleConfig.max - selectedCount) : Infinity;
    return {
      maxReached,
      showQuantity,
      remainingCount,
      selectedCount
    };
  }, [normalizedValues, dataSource, ruleConfig == null ? void 0 : ruleConfig.max]);
  const getOptionState = (0, import_react.useCallback)(
    (optionKey) => {
      const found = normalizedValues.find((item) => item.value === optionKey);
      return {
        selected: !!found,
        quantity: (found == null ? void 0 : found.quantity) || 0
      };
    },
    [normalizedValues]
  );
  const options = (0, import_react.useMemo)(() => {
    return normalizedOptions.map((option) => {
      const state = getOptionState(option._key);
      const disabled = quantityInfo.maxReached && !(mode === "single" && (ruleConfig == null ? void 0 : ruleConfig.max) === 1) && !state.selected;
      return {
        ...option,
        selected: state.selected,
        quantity: state.quantity,
        disabled: option.disabled || disabled
      };
    });
  }, [normalizedOptions, getOptionState, quantityInfo.maxReached, mode, ruleConfig == null ? void 0 : ruleConfig.max]);
  const validate = async () => {
    const errors2 = [];
    const { required, min, max, customValidator } = ruleConfig || {};
    const values2 = valuesRef.current;
    let currentNormalizedValues = [];
    if (values2) {
      if (Array.isArray(values2)) {
        currentNormalizedValues = values2.map((item) => {
          if (typeof item === "object" && item !== null) {
            return {
              ...item,
              value: item.value,
              quantity: item.quantity || 1
            };
          }
          return { value: item, quantity: 1 };
        });
      } else if (typeof values2 === "object" && values2 !== null) {
        const objValue = values2;
        currentNormalizedValues = [
          {
            ...objValue,
            value: objValue.value,
            quantity: objValue.quantity || 1
          }
        ];
      } else {
        currentNormalizedValues = [{ value: values2, quantity: 1 }];
      }
    }
    const totalQuantity = currentNormalizedValues.reduce(
      (sum, item) => sum + (item.quantity || 0),
      0
    );
    if (required && totalQuantity < 1) {
      errors2.push({
        type: "required",
        message: import_utils.locales.getText("pisell2.pro.selector.validate.required-msg")
      });
    }
    if (typeof min === "number" && totalQuantity < min) {
      errors2.push({
        type: "min",
        message: import_utils.locales.getText("pisell2.pro.selector.validate.min-selection")(
          min
        )
      });
    }
    if (typeof max === "number" && totalQuantity > max) {
      errors2.push({
        type: "max",
        message: import_utils.locales.getText("pisell2.pro.selector.validate.max-selection")(
          max
        )
      });
    }
    options.forEach((option) => {
      var _a, _b;
      const _optionVal = currentNormalizedValues.find(
        (item) => item.value === option._key
      );
      const quantity = (_optionVal == null ? void 0 : _optionVal.quantity) || 0;
      const { _label } = option;
      const _min = (_a = option == null ? void 0 : option.ruleConfig) == null ? void 0 : _a.min;
      const _max = (_b = option == null ? void 0 : option.ruleConfig) == null ? void 0 : _b.max;
      if (typeof _min === "number" && quantity < _min) {
        errors2.push({
          type: "optionMin",
          message: import_utils.locales.getText(
            "pisell2.pro.selector.validate.min-selection"
          )(_min, _label),
          _key: option._key
        });
      }
      if (typeof _max === "number" && quantity > _max) {
        errors2.push({
          type: "optionMax",
          message: import_utils.locales.getText(
            "pisell2.pro.selector.validate.max-selection"
          )(_max, _label),
          _key: option._key
        });
      }
    });
    if (mutexGroups.length > 0) {
      const selectedValues = Array.isArray(values2) ? values2 : values2 ? [values2] : [];
      const selectedKeys = selectedValues.map(
        (v) => typeof v === "object" && v !== null ? v.value : v
      );
      mutexGroups.forEach((group) => {
        const count = selectedKeys.filter(
          (k) => group.includes(k)
        ).length;
        if (count > 1) {
          errors2.push({
            type: "mutex",
            message: "Only one option can be selected in the same mutex group"
          });
        }
      });
    }
    if (typeof customValidator === "function") {
      try {
        await customValidator(values2);
      } catch (e) {
        const type = (e == null ? void 0 : e.type) || "custom";
        const message = (e == null ? void 0 : e.message) || "Validation failed";
        errors2.push({ type, message });
      }
    }
    setErrors(errors2);
    setValidated(true);
    return errors2.length === 0 ? Promise.resolve() : Promise.reject(errors2);
  };
  const buildOutputValue = (0, import_react.useCallback)(
    (newNormalizedValues) => {
      if (newNormalizedValues.length === 0) {
        return mode === "single" ? void 0 : [];
      }
      if (mode === "single") {
        const item = newNormalizedValues[0];
        if (valueType === "primitive") {
          return item.value;
        }
        return { ...item };
      }
      if (valueType === "primitive") {
        return newNormalizedValues.map((item) => item.value);
      }
      return newNormalizedValues.map((item) => {
        return { ...item };
      });
    },
    [mode, valueType, quantityInfo.showQuantity]
  );
  const _onChange = (0, import_react.useCallback)(
    (optionKey, data) => {
      let newNormalizedValues = [...normalizedValues];
      const existingIndex = newNormalizedValues.findIndex(
        (item) => item.value === optionKey
      );
      if ((data == null ? void 0 : data.quantity) !== void 0 && data.quantity <= 0) {
        if (existingIndex >= 0) {
          newNormalizedValues.splice(existingIndex, 1);
        }
      } else {
        if (existingIndex >= 0) {
          newNormalizedValues[existingIndex] = {
            ...newNormalizedValues[existingIndex],
            ...data
          };
        } else {
          const newItem = {
            value: optionKey,
            quantity: data.quantity || 1,
            ...data
          };
          if (mode === "single") {
            newNormalizedValues = [newItem];
          } else {
            newNormalizedValues.push(newItem);
          }
        }
        const groupIdxList = mutexIndex.get(optionKey) || [];
        if (groupIdxList.length > 0) {
          const keepKey = optionKey;
          const toRemove = /* @__PURE__ */ new Set();
          groupIdxList.forEach((gi) => {
            const group = mutexGroups[gi] || [];
            group.forEach((k) => {
              if (k !== keepKey) {
                toRemove.add(k);
              }
            });
          });
          if (toRemove.size > 0) {
            newNormalizedValues = newNormalizedValues.filter(
              (item) => !toRemove.has(item.value)
            );
          }
        }
      }
      const outputValue = buildOutputValue(newNormalizedValues);
      setValues(outputValue);
      valuesRef.current = outputValue;
      if (ruleConfig == null ? void 0 : ruleConfig.autoValidate) {
        try {
          validate();
        } catch (error) {
        }
      }
    },
    [
      normalizedValues,
      mode,
      buildOutputValue,
      setValues,
      mutexIndex,
      mutexGroups,
      ruleConfig == null ? void 0 : ruleConfig.autoValidate
    ]
  );
  const clear = (0, import_react.useCallback)(() => {
    setValues(mode === "single" ? void 0 : []);
    setErrors([]);
  }, [mode, setValues, setErrors]);
  const reset = (0, import_react.useCallback)(() => {
    const hasDefinedDefault = props && props.defaultValue !== void 0;
    if (hasDefinedDefault) {
      setValues(props.defaultValue);
    } else {
      clear();
    }
    setErrors([]);
  }, [props, clear, setValues, setErrors]);
  const actions = {
    toggle: (optionKey) => {
      const currentState = getOptionState(optionKey);
      _onChange(optionKey, { quantity: currentState.selected ? 0 : 1 });
    },
    update: (optionKey, payload) => _onChange(optionKey, payload),
    setValue: (value) => setValues(value),
    clear,
    validate,
    reset
  };
  return {
    state: {
      errors,
      validated,
      values,
      options,
      quantityInfo
    },
    actions
  };
}
