"use strict";

Object.defineProperty(exports, "__esModule", {
  value: true
});
exports.default = void 0;

function _react() {
  const data = _interopRequireWildcard(require("react"));

  _react = function () {
    return data;
  };

  return data;
}

function _tslib() {
  const data = require("tslib");

  _tslib = function () {
    return data;
  };

  return data;
}

function _jsxRuntime() {
  const data = require("react/jsx-runtime");

  _jsxRuntime = function () {
    return data;
  };

  return data;
}

function _clsx() {
  const data = _interopRequireDefault(require("clsx"));

  _clsx = function () {
    return data;
  };

  return data;
}

var _ConfigProviderContext = _interopRequireDefault(require("../config-provider/ConfigProviderContext"));

var _actionBar = require("../action-bar");

var _image = require("../image");

var _hooks = require("../hooks");

var _constant = require("../utils/constant");

var _imagePreview = _interopRequireDefault(require("../image-preview"));

var _popup = require("../popup");

var _utils = require("./utils");

var _constants = require("./constants");

var _SkuRow = _interopRequireDefault(require("./components/SkuRow"));

var _SkuRowItem = _interopRequireDefault(require("./components/SkuRowItem"));

var _SkuRowPropItem = _interopRequireDefault(require("./components/SkuRowPropItem"));

var _SkuStepper = _interopRequireDefault(require("./components/SkuStepper"));

var _toast = _interopRequireDefault(require("../toast"));

function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }

function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }

function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }

/* eslint-disable @typescript-eslint/no-misused-promises */

/* eslint-disable react/no-array-index-key */
const {
  QUOTA_LIMIT
} = _constants.LIMIT_TYPE;
const Sku = (0, _react().forwardRef)((props, ref) => {
  var _a, _b;

  const {
    prefixCls,
    createNamespace
  } = (0, _react().useContext)(_ConfigProviderContext.default);
  const [bem] = createNamespace('sku', prefixCls);
  const stepperError = (0, _react().useRef)(false);
  const [visible, setVisible] = (0, _react().useState)(false);
  const [state, updateState] = (0, _hooks.useSetState)({
    selectedSku: {},
    selectedProp: {},
    selectedNum: props.startSaleNum
  });
  const {
    sku,
    properties = []
  } = props;
  const {
    tree = []
  } = sku;
  const bodyStyle = (0, _react().useMemo)(() => {
    const maxHeight = window.innerHeight - props.bodyOffsetTop;
    return {
      maxHeight: `${maxHeight}px`
    };
  }, [props.bodyOffsetTop]);
  const imageList = (0, _react().useMemo)(() => {
    const {
      goods
    } = props;
    const rs = [goods === null || goods === void 0 ? void 0 : goods.picture];

    if (sku.tree.length > 0) {
      sku.tree.forEach(treeItem => {
        if (!treeItem.v) return;
        treeItem.v.forEach(vItem => {
          const img = vItem.previewImgUrl || vItem.imgUrl || vItem.img_url;

          if (img && rs.indexOf(img) === -1) {
            rs.push(img);
          }
        });
      });
    }

    return rs;
  }, [(_a = props.goods) === null || _a === void 0 ? void 0 : _a.picture, sku.tree]);
  const hasSku = (0, _react().useMemo)(() => !sku.none_sku, [sku.none_sku]);
  const hasSkuOrAttr = (0, _react().useMemo)(() => hasSku || properties.length > 0, [hasSku, properties]);
  const isSkuCombSelected = (0, _react().useMemo)(() => {
    // SKU 未选完
    if (hasSku && !(0, _utils.isAllSelected)(tree, state.selectedSku)) {
      return false;
    } // 属性未全选


    return !properties.filter(i => i.is_necessary !== false).some(i => (state.selectedProp[i.k_id] || []).length === 0);
  }, [hasSku, state]);
  const selectedSkuValues = (0, _react().useMemo)(() => {
    return (0, _utils.getSelectedSkuValues)(tree, state.selectedSku);
  }, [tree, state.selectedSku]);
  const selectedPropValues = (0, _react().useMemo)(() => {
    return (0, _utils.getSelectedPropValues)(properties, state.selectedProp);
  }, [properties, state.selectedProp]);
  const selectedSkuComb = (0, _react().useMemo)(() => {
    let skuComb = null;

    if (isSkuCombSelected) {
      if (hasSku) {
        skuComb = (0, _utils.getSkuComb)(sku.list, state.selectedSku);
      } else {
        skuComb = {
          id: sku.collection_id,
          price: Math.round(+sku.price * 100),
          stock_num: sku.stock_num
        };
      }

      if (skuComb) {
        skuComb.properties = (0, _utils.getSelectedProperties)(properties, state.selectedProp);
        skuComb.property_price = selectedPropValues.reduce((acc, cur) => acc + (cur.price || 0), 0);
      }
    }

    return skuComb;
  }, [isSkuCombSelected, hasSku, JSON.stringify(sku), JSON.stringify(state), properties, selectedPropValues]);
  const unselectedSku = (0, _react().useMemo)(() => {
    return tree.filter(item => !state.selectedSku[item.k_s]).map(item => item.k);
  }, [tree, state.selectedSku]);
  const getUnselectedProp = (0, _react().useCallback)(isNecessary => {
    return properties.filter(item => isNecessary ? item.is_necessary !== false : true).filter(item => (state.selectedProp[item.k_id] || []).length < 1).map(item => item.k);
  }, [properties, state.selectedProp]);
  const selectedText = (0, _react().useMemo)(() => {
    if (selectedSkuComb) {
      const values = selectedSkuValues.concat(selectedPropValues);
      return `已选 ${values.map(item => item.name).join(' ')}`;
    }

    return `请选择 ${unselectedSku.concat(getUnselectedProp()).join(' ')}`;
  }, [unselectedSku, getUnselectedProp, selectedSkuComb, selectedSkuValues, selectedPropValues]);
  const price = (0, _react().useMemo)(() => {
    if (selectedSkuComb) {
      return ((selectedSkuComb.price + selectedSkuComb.property_price) / 100).toFixed(2);
    } // sku.price是一个格式化好的价格区间


    return sku.price;
  }, [JSON.stringify(selectedSkuComb), sku.price]);
  const stock = (0, _react().useMemo)(() => {
    const {
      stockNum
    } = props.customStepperConfig;

    if (stockNum !== undefined) {
      return stockNum;
    }

    if (selectedSkuComb) {
      return selectedSkuComb.stock_num;
    }

    return sku.stock_num;
  }, [sku.stock_num, JSON.stringify(selectedSkuComb)]);
  const stockContent = (0, _react().useMemo)(() => {
    if (props.stockRender) {
      return props.stockRender(stock);
    }

    return (0, _jsxRuntime().jsxs)(_jsxRuntime().Fragment, {
      children: ["\u5269\u4F59", (0, _jsxRuntime().jsx)("span", Object.assign({
        className: (0, _clsx().default)(bem('stock-num', {
          highlight: stock < props.stockThreshold
        }))
      }, {
        children: stock
      })), "\u4EF6"]
    });
  }, [stock]);

  const onSelect = skuValue => {
    // 点击已选中的sku时则取消选中
    const selectedSku = state.selectedSku[skuValue.skuKeyStr] === skuValue.id ? Object.assign(Object.assign({}, state.selectedSku), {
      [skuValue.skuKeyStr]: _constants.UNSELECTED_SKU_VALUE_ID
    }) : Object.assign(Object.assign({}, state.selectedSku), {
      [skuValue.skuKeyStr]: skuValue.id
    });
    updateState({
      selectedSku
    });

    if (props.onSkuSelected) {
      props.onSkuSelected({
        skuValue,
        selectedSku: state.selectedSku,
        selectedSkuComb
      });
    }
  };

  const onPropSelect = propValue => {
    const arr = state.selectedProp[propValue.skuKeyStr] || [];
    const pos = arr.indexOf(propValue.id);

    if (pos > -1) {
      arr.splice(pos, 1);
    } else if (propValue.multiple) {
      arr.push(propValue.id);
    } else {
      arr.splice(0, 1, propValue.id);
    }

    const selectedProp = Object.assign(Object.assign({}, state.selectedProp), {
      [propValue.skuKeyStr]: arr
    });
    updateState({
      selectedProp
    });

    if (props.onSkuPropSelected) {
      props.onSkuPropSelected({
        propValue,
        selectedProp: state.selectedProp,
        selectedSkuComb
      });
    }
  };

  const onOverLimit = data => {
    const {
      action,
      limitType,
      quota,
      quotaUsed
    } = data;
    const {
      handleOverLimit
    } = props.customStepperConfig;

    if (handleOverLimit) {
      handleOverLimit(data);
      return;
    }

    if (action === 'minus') {
      if (props.startSaleNum > 1) {
        (0, _toast.default)(`${props.startSaleNum}件起售`);
      } else {
        (0, _toast.default)('至少选择一件');
      }
    } else if (action === 'plus') {
      if (limitType === QUOTA_LIMIT) {
        if (quotaUsed > 0) {
          (0, _toast.default)(`每人限购${quota}件，你已购买${quotaUsed}件`);
        } else {
          (0, _toast.default)(`每人限购${quota}件`);
        }
      } else {
        (0, _toast.default)('库存不足');
      }
    }
  };

  const onStepperState = data => {
    stepperError.current = data.valid ? null : Object.assign(Object.assign({}, data), {
      action: 'plus'
    });
  };

  const validateSku = () => {
    if (state.selectedNum === 0) {
      return '商品已经无法购买啦';
    }

    if (isSkuCombSelected) {
      return '';
    }

    return `请选择 ${unselectedSku.concat(getUnselectedProp(true)).join(' ')}`;
  };

  const getSkuData = () => {
    return {
      goodsId: props.goodsId,
      selectedNum: state.selectedNum,
      selectedSkuComb
    };
  };

  const onAddCart = data => {
    var _a;

    (_a = props.onAddCart) === null || _a === void 0 ? void 0 : _a.call(props, data);
  };

  const onBuyClicked = data => {
    var _a;

    (_a = props.onBuyClicked) === null || _a === void 0 ? void 0 : _a.call(props, data);
  };

  const onBuyOrAddCart = type => (0, _tslib().__awaiter)(void 0, void 0, void 0, function* () {
    // sku 不符合购买条件
    if (stepperError.current) {
      onOverLimit(stepperError.current);
      return;
    }

    if (props.customSkuValidator) {
      if (!(yield props.customSkuValidator(type, Object.assign(Object.assign({}, state.selectedSku), state.selectedProp)))) {
        return;
      }
    } else {
      const error = validateSku();

      if (error) {
        (0, _toast.default)(error);
        return;
      }
    }

    const data = getSkuData();

    if (type === 'add-cart') {
      onAddCart(data);
    } else {
      onBuyClicked(data);
    }
  });

  const show = initialValue => {
    setVisible(true);

    if (initialValue) {
      updateState(initialValue);
    }
  };

  const reset = () => {
    updateState({
      selectedSku: {},
      selectedProp: {},
      selectedNum: props.startSaleNum
    });
  };

  const onPopupClose = () => {
    setVisible(false);
    if (props.popupProps && props.popupProps.onClose) props.popupProps.onClose();
  };

  const onPopupClosed = () => {
    if (props.resetOnHide) {
      reset();
    }

    if (props.popupProps && props.popupProps.onClosed) props.popupProps.onClosed();
  };

  const onPreviewImage = selectedValue => {
    let index = 0;
    let indexImage = imageList[0];

    if (selectedValue && selectedValue.imgUrl) {
      imageList.some((image, pos) => {
        if (image === selectedValue.imgUrl) {
          index = pos;
          return true;
        }

        return false;
      });
      indexImage = selectedValue.imgUrl;
    }

    const params = Object.assign(Object.assign({}, selectedValue), {
      index,
      imageList,
      indexImage
    });
    if (!props.previewOnClickImage) return;

    _imagePreview.default.open({
      images: imageList,
      startPosition: index,
      onClose: () => {
        if (props.onClosePreview) props.onClosePreview(params);
      }
    });

    if (props.onOpenPreview) {
      props.onOpenPreview(params);
    }
  };

  const renderHeaderInfo = () => {
    var _a;

    return (0, _jsxRuntime().jsxs)(_jsxRuntime().Fragment, {
      children: [((_a = props.skuHeaderPriceRender) === null || _a === void 0 ? void 0 : _a.call(props, price)) || (0, _jsxRuntime().jsxs)("div", Object.assign({
        className: (0, _clsx().default)(bem('goods-price'))
      }, {
        children: [(0, _jsxRuntime().jsx)("span", Object.assign({
          className: (0, _clsx().default)(bem('price-symbol'))
        }, {
          children: "\uFFE5"
        })), (0, _jsxRuntime().jsx)("span", Object.assign({
          className: (0, _clsx().default)(bem('price-num'))
        }, {
          children: price
        })), props.priceTag && (0, _jsxRuntime().jsx)("span", Object.assign({
          className: (0, _clsx().default)(bem('price-tag'))
        }, {
          children: props.priceTag
        }))]
      })), props.skuHeaderOriginPrice && (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('header-item'))
      }, {
        children: props.skuHeaderOriginPrice
      })), !props.hideStock && (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('header-item'))
      }, {
        children: (0, _jsxRuntime().jsx)("span", Object.assign({
          className: (0, _clsx().default)(bem('stock'))
        }, {
          children: stockContent
        }))
      })), !props.hideSelectedText && (0, _jsxRuntime().jsx)("div", Object.assign({
        className: (0, _clsx().default)(bem('header-item'))
      }, {
        children: selectedText
      }))]
    });
  };

  const renderHeader = () => {
    if (props.skuHeader) return props.skuHeader;
    const selectedValue = (0, _utils.getSkuImgValue)(sku, state.selectedSku);
    const imgUrl = selectedValue ? selectedValue.imgUrl : props.goods.picture;
    return (0, _jsxRuntime().jsxs)("div", Object.assign({
      className: (0, _clsx().default)(bem('header'), _constant.BORDER_BOTTOM)
    }, {
      children: [props.showHeaderImage && (0, _jsxRuntime().jsx)(_image.Image, Object.assign({
        fit: "cover",
        src: imgUrl,
        className: (0, _clsx().default)(bem('header__img-wrap')),
        onClick: () => onPreviewImage(selectedValue)
      }, {
        children: props.skuHeaderImageExtra
      })), (0, _jsxRuntime().jsxs)("div", Object.assign({
        className: (0, _clsx().default)(bem('header__goods-info'))
      }, {
        children: [renderHeaderInfo(), props.skuHeaderExtra]
      }))]
    }));
  };

  const renderGroup = () => {
    return props.skuGroup || hasSkuOrAttr && (0, _jsxRuntime().jsxs)("div", Object.assign({
      className: (0, _clsx().default)(bem('group-container', {
        'hide-soldout': !props.showSoldoutSku
      }))
    }, {
      children: [tree.map((skuTreeItem, i) => (0, _jsxRuntime().jsx)(_SkuRow.default, Object.assign({
        skuRow: skuTreeItem
      }, {
        children: skuTreeItem.v.map((skuValue, idx) => (0, _jsxRuntime().jsx)(_SkuRowItem.default, {
          skuList: sku.list,
          skuValue: skuValue,
          skuKeyStr: `${skuTreeItem.k_s}`,
          selectedSku: state.selectedSku,
          disableSoldoutSku: props.disableSoldoutSku,
          largeImageMode: skuTreeItem.largeImageMode,
          previewIcon: props.previewIcon,
          onSkuSelected: onSelect,
          onSkuPreviewImage: selectedValue => onPreviewImage(selectedValue)
        }, idx))
      }), i)), properties.map((skuTreeItem, i) => (0, _jsxRuntime().jsx)(_SkuRow.default, Object.assign({
        skuRow: skuTreeItem
      }, {
        children: skuTreeItem.v.map((skuValue, idx) => (0, _jsxRuntime().jsx)(_SkuRowPropItem.default, {
          skuValue: skuValue,
          skuKeyStr: `${skuTreeItem.k_id}`,
          selectedProp: state.selectedProp,
          multiple: skuTreeItem.is_multiple,
          onSkuPropSelected: onPropSelect
        }, idx))
      }), i))]
    }));
  };

  const renderStepper = () => props.skuStepper || (0, _jsxRuntime().jsx)(_SkuStepper.default, {
    currentNum: state.selectedNum,
    onChange: currentValue => {
      updateState({
        selectedNum: parseInt(`${currentValue}`, 10)
      });
      if (props.onStepperChange) props.onStepperChange(currentValue);
    },
    stock: stock,
    quota: props.quota,
    quotaUsed: props.quotaUsed,
    startSaleNum: props.startSaleNum,
    disableStepperInput: props.disableStepperInput,
    customStepperConfig: props.customStepperConfig,
    stepperTitle: props.stepperTitle,
    hideQuotaText: props.hideQuotaText,
    onSkuStepperState: onStepperState,
    onSkuOverLimit: onOverLimit
  });

  const renderBody = () => {
    return (0, _jsxRuntime().jsxs)("div", Object.assign({
      className: (0, _clsx().default)(bem('body')),
      style: bodyStyle
    }, {
      children: [props.skuBodyTop, renderGroup(), props.skuGroupExtra, renderStepper()]
    }));
  };

  const renderActions = () => {
    return props.skuActions || (0, _jsxRuntime().jsx)("div", Object.assign({
      className: (0, _clsx().default)(bem('actions'))
    }, {
      children: (0, _jsxRuntime().jsxs)(_actionBar.ActionBar, {
        children: [props.showAddCartBtn && (0, _jsxRuntime().jsx)(_actionBar.ActionBar.Button, {
          type: "warning",
          text: props.addCartText || '加入购物车',
          onClick: () => onBuyOrAddCart('add-cart')
        }), (0, _jsxRuntime().jsx)(_actionBar.ActionBar.Button, {
          type: "danger",
          text: props.buyText || '立即购买',
          onClick: () => onBuyOrAddCart('buy-clicked')
        })]
      })
    }));
  };

  (0, _react().useEffect)(() => {
    if (props.initialSku) {
      updateState(props.initialSku);
    }
  }, [JSON.stringify(props.initialSku)]);
  (0, _react().useImperativeHandle)(ref, () => ({
    reset,
    getSkuData,
    show,
    update: updateState
  }));
  return (0, _jsxRuntime().jsxs)(_popup.Popup, Object.assign({
    round: true,
    closeable: true,
    position: "bottom"
  }, props.popupProps, {
    visible: visible,
    onClose: onPopupClose,
    onClosed: onPopupClosed,
    className: (0, _clsx().default)((_b = props.popupProps) === null || _b === void 0 ? void 0 : _b.className, bem('container'))
  }, {
    children: [renderHeader(), renderBody(), props.skuActionsTop, renderActions(), props.skuActionsBottom]
  }));
}); // defaultProps defined if need

Sku.defaultProps = {
  stepperTitle: '购买数量',
  properties: [],
  showAddCartBtn: true,
  disableSoldoutSku: true,
  showHeaderImage: true,
  previewOnClickImage: true,
  showSoldoutSku: true,
  resetOnHide: true,
  safeAreaInsetBottom: true,
  quota: 0,
  quotaUsed: 0,
  startSaleNum: 1,
  stockThreshold: 50,
  bodyOffsetTop: 200,
  customStepperConfig: {}
};
var _default = Sku;
exports.default = _default;