function ownKeys(e, r) { var t = Object.keys(e); if (Object.getOwnPropertySymbols) { var o = Object.getOwnPropertySymbols(e); r && (o = o.filter(function (r) { return Object.getOwnPropertyDescriptor(e, r).enumerable; })), t.push.apply(t, o); } return t; }
function _objectSpread(e) { for (var r = 1; r < arguments.length; r++) { var t = null != arguments[r] ? arguments[r] : {}; r % 2 ? ownKeys(Object(t), !0).forEach(function (r) { _defineProperty(e, r, t[r]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(e, Object.getOwnPropertyDescriptors(t)) : ownKeys(Object(t)).forEach(function (r) { Object.defineProperty(e, r, Object.getOwnPropertyDescriptor(t, r)); }); } return e; }
function _defineProperty(obj, key, value) { key = _toPropertyKey(key); if (key in obj) { Object.defineProperty(obj, key, { value: value, enumerable: true, configurable: true, writable: true }); } else { obj[key] = value; } return obj; }
function _toPropertyKey(t) { var i = _toPrimitive(t, "string"); return "symbol" == _typeof(i) ? i : String(i); }
function _toPrimitive(t, r) { if ("object" != _typeof(t) || !t) return t; var e = t[Symbol.toPrimitive]; if (void 0 !== e) { var i = e.call(t, r || "default"); if ("object" != _typeof(i)) return i; throw new TypeError("@@toPrimitive must return a primitive value."); } return ("string" === r ? String : Number)(t); }
function _typeof(o) { "@babel/helpers - typeof"; return _typeof = "function" == typeof Symbol && "symbol" == typeof Symbol.iterator ? function (o) { return typeof o; } : function (o) { return o && "function" == typeof Symbol && o.constructor === Symbol && o !== Symbol.prototype ? "symbol" : typeof o; }, _typeof(o); }
import { pickIdentity } from "./identity";
import { getLineProductOptions } from "./productSkuOptions";
/**
 * 获取对象自身字段并稳定排序，避免相同规格对象因字段顺序不同生成不同 key。
 *
 * @example
 * stableSerialize({ b: 2, a: 1 }) === stableSerialize({ a: 1, b: 2 });
 */
function stableSerialize(value) {
  return JSON.stringify(normalizeForStableSerialize(value));
}

/**
 * 将任意值规整成稳定 JSON 结构；数组保持顺序，对象按 key 排序。
 *
 * @example
 * normalizeForStableSerialize([{ b: 1, a: 2 }]);
 */
function normalizeForStableSerialize(value) {
  if (value === undefined) return null;
  if (value === null) return null;
  if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
    return value;
  }
  if (Array.isArray(value)) {
    return value.map(function (item) {
      return normalizeForStableSerialize(item);
    });
  }
  if (_typeof(value) === 'object') {
    return Object.keys(value).sort().reduce(function (acc, key) {
      acc[key] = normalizeForStableSerialize(value[key]);
      return acc;
    }, {});
  }
  return String(value);
}
var PROMOTION_IDENTITY_KEYS = new Set(['unique_identification_number', 'product_uid', 'booking_uid', 'sourceProductIds', 'source_product_ids']);

/**
 * 清理促销/赠品状态中的行身份字段；合并判断关注策略状态一致，不关注真实 uid。
 *
 * @example
 * normalizePromotionState({ sourceProductIds: ['uid-1'], strategyId: 's1' });
 */
function normalizePromotionState(value) {
  if (Array.isArray(value)) {
    return value.map(function (item) {
      return normalizePromotionState(item);
    });
  }
  if (!value || _typeof(value) !== 'object') {
    return value;
  }
  return Object.keys(value).reduce(function (acc, key) {
    if (PROMOTION_IDENTITY_KEYS.has(key)) return acc;
    acc[key] = normalizePromotionState(value[key]);
    return acc;
  }, {});
}

/**
 * 统一把可能为空的字段转成字符串，保证 merge key 中 null/undefined 口径一致。
 *
 * @example
 * normalizeKeyPart(null) === '';
 */
function normalizeKeyPart(value) {
  if (value === undefined || value === null) return '';
  return String(value);
}

/**
 * 从 booking 视图中解析用户备注；备注不同的预约不能合并。
 *
 * @example
 * resolveBookingNote({ note: 'window' } as any);
 */
function resolveBookingNote(booking) {
  var _extend$note, _extend;
  return normalizeKeyPart((_extend$note = booking === null || booking === void 0 || (_extend = booking._extend) === null || _extend === void 0 ? void 0 : _extend.note) !== null && _extend$note !== void 0 ? _extend$note : booking === null || booking === void 0 ? void 0 : booking.note).trim();
}

/**
 * 生成资源指纹；资源不同的预约即使时间相同也不能合并。
 *
 * @example
 * buildResourceFingerprint({ resources: [{ relation_id: 1 }] } as any);
 */
function buildResourceFingerprint(booking) {
  var _extend2;
  return stableSerialize({
    relation_id: booking.relation_id,
    relation_type: booking.relation_type,
    resource_id: booking.resource_id,
    resources: booking.resources,
    resource: (_extend2 = booking._extend) === null || _extend2 === void 0 ? void 0 : _extend2.resource
  });
}

/**
 * 生成商品规格指纹；覆盖 option / bundle，且不依赖对象字段顺序。
 *
 * @example
 * buildProductSpecFingerprint(product);
 */
function buildProductSpecFingerprint(product) {
  return stableSerialize({
    option: getLineProductOptions(product),
    bundle: product.product_bundle
  });
}

/**
 * 生成价格指纹；手动改价、主商品价、顶层售价任一不同都不合并。
 *
 * @example
 * buildPriceFingerprint(product);
 */
function buildPriceFingerprint(product) {
  var metadata = product.metadata || {};
  return stableSerialize({
    selling_price: product.selling_price,
    original_price: product.original_price,
    source_product_price: metadata.source_product_price,
    main_product_selling_price: metadata.main_product_selling_price,
    main_product_original_price: metadata.main_product_original_price,
    price_override: metadata.price_override,
    is_manual_discount: metadata.is_manual_discount
  });
}

/**
 * 生成促销与赠品指纹；促销/赠品 uid 归属不同的行不应被合并。
 *
 * @example
 * buildPromotionFingerprint(product);
 */
function buildPromotionFingerprint(product) {
  var _metadata$_promotionT, _metadata$_giftInfo;
  var metadata = product.metadata || {};
  return stableSerialize({
    discount_list: product.discount_list,
    promotion: normalizePromotionState(metadata._promotion),
    promotionTags: (_metadata$_promotionT = metadata._promotionTags) !== null && _metadata$_promotionT !== void 0 ? _metadata$_promotionT : product._promotionTags,
    giftInfo: normalizePromotionState((_metadata$_giftInfo = metadata._giftInfo) !== null && _metadata$_giftInfo !== void 0 ? _metadata$_giftInfo : product._giftInfo),
    giftData: normalizePromotionState(product.giftData),
    isGiftPromotion: product._isGiftPromotion
  });
}

/**
 * 生成 booking 时间指纹；开始/结束时间不同的预约不能合并。
 *
 * @example
 * buildBookingTimeFingerprint(booking);
 */
function buildBookingTimeFingerprint(booking) {
  return stableSerialize({
    start_date: booking.start_date,
    start_time: booking.start_time,
    end_date: booking.end_date,
    end_time: booking.end_time,
    duration: booking.duration
  });
}

/**
 * 生成严格合并 key；任一核心展示或写回字段不同都会拆成不同展示行。
 *
 * @example
 * buildBookingMergeKey(booking);
 */
export function buildBookingMergeKey(booking) {
  var _booking$_extend;
  var product = (_booking$_extend = booking._extend) === null || _booking$_extend === void 0 ? void 0 : _booking$_extend.product;
  if (!product) return null;
  return stableSerialize({
    bookingTime: buildBookingTimeFingerprint(booking),
    productBase: {
      product_id: product.product_id,
      product_variant_id: product.product_variant_id
    },
    productSpec: buildProductSpecFingerprint(product),
    price: buildPriceFingerprint(product),
    resource: buildResourceFingerprint(booking),
    note: resolveBookingNote(booking),
    promotion: buildPromotionFingerprint(product)
  });
}

/**
 * 计算 booking 展示数量；预约商品通常一条真实行为 1，这里保留 num 兼容。
 *
 * @example
 * resolveBookingDisplayQuantity(product);
 */
export function resolveBookingDisplayQuantity(product) {
  var num = Number(product === null || product === void 0 ? void 0 : product.num);
  return Number.isFinite(num) && num > 0 ? num : 1;
}

/**
 * 从合并 booking 或代表商品行中取出真实来源；未合并时返回空数组。
 *
 * @example
 * getMergedBookingSources(bookingView);
 */
export function getMergedBookingSources(target) {
  var _mergedFrom;
  var extend = target === null || target === void 0 ? void 0 : target._extend;
  var sources = (_mergedFrom = extend === null || extend === void 0 ? void 0 : extend.mergedFrom) !== null && _mergedFrom !== void 0 ? _mergedFrom : extend === null || extend === void 0 ? void 0 : extend.mergedBookingSources;
  return Array.isArray(sources) ? sources : [];
}

/**
 * 判断购物车目标是否为合并 booking 展示行。
 *
 * @example
 * isMergedBookingTarget(bookingView);
 */
export function isMergedBookingTarget(target) {
  return getMergedBookingSources(target).length > 1;
}

/**
 * 按严格 key 合并 booking 展示行；底层真实 booking/product 不会被修改。
 *
 * @example
 * const displayBookings = mergeBookingsForDisplay(rawBookings);
 */
export function mergeBookingsForDisplay(bookings) {
  if (!Array.isArray(bookings) || bookings.length <= 1) return bookings;
  var groups = new Map();
  var passthrough = [];
  bookings.forEach(function (booking, index) {
    var _groups$get;
    var key = buildBookingMergeKey(booking);
    if (!key) {
      passthrough.push({
        index: index,
        booking: booking
      });
      return;
    }
    var existed = (_groups$get = groups.get(key)) !== null && _groups$get !== void 0 ? _groups$get : [];
    existed.push(booking);
    groups.set(key, existed);
  });
  var representatives = new Map();
  groups.forEach(function (group) {
    if (group.length <= 1) {
      representatives.set(group[0], group[0]);
      return;
    }
    var sources = group.map(function (booking) {
      var _booking$_extend2;
      var product = (_booking$_extend2 = booking._extend) === null || _booking$_extend2 === void 0 ? void 0 : _booking$_extend2.product;
      if (!product) return null;
      return {
        booking: booking,
        product: product,
        identity: pickIdentity(product)
      };
    }).filter(function (item) {
      return item !== null;
    });
    var displayQuantity = sources.reduce(function (total, source) {
      return total + resolveBookingDisplayQuantity(source.product);
    }, 0);
    var representative = group[0];
    var representativeProduct = representative._extend.product;
    var addTimeProduct = group.flatMap(function (booking) {
      var _booking$_extend3;
      return ((_booking$_extend3 = booking._extend) === null || _booking$_extend3 === void 0 ? void 0 : _booking$_extend3.addTimeProduct) || [];
    });
    var displayProduct = representativeProduct ? _objectSpread(_objectSpread({}, representativeProduct), {}, {
      num: displayQuantity,
      _extend: _objectSpread(_objectSpread({}, representativeProduct._extend), {}, {
        isMergedBookingLine: true,
        displayQuantity: displayQuantity,
        mergedBookingSources: sources
      })
    }) : representativeProduct;
    representatives.set(representative, _objectSpread(_objectSpread({}, representative), {}, {
      holderMaxCount: displayQuantity,
      _extend: _objectSpread(_objectSpread({}, representative._extend), {}, {
        product: displayProduct,
        addTimeProduct: addTimeProduct,
        canAddTime: group.some(function (booking) {
          var _booking$_extend4;
          return (_booking$_extend4 = booking._extend) === null || _booking$_extend4 === void 0 ? void 0 : _booking$_extend4.canAddTime;
        }),
        isMergedBookingLine: true,
        displayQuantity: displayQuantity,
        mergedFrom: sources
      })
    }));
  });
  return bookings.reduce(function (acc, booking, index) {
    var passthroughItem = passthrough.find(function (item) {
      return item.index === index;
    });
    if (passthroughItem) {
      acc.push(passthroughItem.booking);
      return acc;
    }
    var representative = representatives.get(booking);
    if (representative) {
      acc.push(representative);
    }
    return acc;
  }, []);
}

/**
 * 克隆新增预约真实行时清理旧 uid，避免 OS createLinkedProductAndBooking 复用原行身份。
 *
 * @example
 * const product = cloneProductForMergedBookingAppend(source.product);
 */
export function cloneProductForMergedBookingAppend(product) {
  var cloned = _objectSpread(_objectSpread({}, product), {}, {
    num: 1,
    metadata: _objectSpread({}, product.metadata || {})
  });
  delete cloned._identity;
  delete cloned._extend;
  delete cloned.unique_identification_number;
  delete cloned.identity_key;
  delete cloned.booking_uid;
  delete cloned.metadata.unique_identification_number;
  delete cloned.metadata.booking_uid;
  delete cloned.order_detail_id;
  delete cloned.discount_list;
  return cloned;
}

/**
 * 克隆新增预约真实行时清理旧 booking uid 和 product_uid。
 *
 * @example
 * const booking = cloneBookingForMergedBookingAppend(source.booking);
 */
export function cloneBookingForMergedBookingAppend(booking) {
  var _cloned$metadata, _cloned$metadata2, _cloned$metadata3;
  var cloned = _objectSpread(_objectSpread({}, booking), {}, {
    metadata: _objectSpread({}, booking.metadata || {})
  });
  delete cloned.product_uid;
  delete cloned.booking_uid;
  delete cloned.booking_id;
  if (cloned !== null && cloned !== void 0 && cloned.holder) {
    delete cloned.holder;
  }
  if (cloned !== null && cloned !== void 0 && cloned.holder_id) {
    delete cloned.holder_id;
  }
  if (cloned !== null && cloned !== void 0 && (_cloned$metadata = cloned.metadata) !== null && _cloned$metadata !== void 0 && _cloned$metadata.holder) {
    delete cloned.metadata.holder;
  }
  if (cloned !== null && cloned !== void 0 && (_cloned$metadata2 = cloned.metadata) !== null && _cloned$metadata2 !== void 0 && _cloned$metadata2.holder_id) {
    delete cloned.metadata.holder_id;
  }
  if (cloned !== null && cloned !== void 0 && (_cloned$metadata3 = cloned.metadata) !== null && _cloned$metadata3 !== void 0 && _cloned$metadata3.unique_identification_number) {
    delete cloned.metadata.unique_identification_number;
  }
  delete cloned.schedule_event_id;
  return cloned;
}