function _createForOfIteratorHelper(o, allowArrayLike) { var it = typeof Symbol !== "undefined" && o[Symbol.iterator] || o["@@iterator"]; if (!it) { if (Array.isArray(o) || (it = _unsupportedIterableToArray(o)) || allowArrayLike && o && typeof o.length === "number") { if (it) o = it; var i = 0; var F = function F() {}; return { s: F, n: function n() { if (i >= o.length) return { done: true }; return { done: false, value: o[i++] }; }, e: function e(_e) { throw _e; }, f: F }; } throw new TypeError("Invalid attempt to iterate non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); } var normalCompletion = true, didErr = false, err; return { s: function s() { it = it.call(o); }, n: function n() { var step = it.next(); normalCompletion = step.done; return step; }, e: function e(_e2) { didErr = true; err = _e2; }, f: function f() { try { if (!normalCompletion && it.return != null) it.return(); } finally { if (didErr) throw err; } } }; }
function _toConsumableArray(arr) { return _arrayWithoutHoles(arr) || _iterableToArray(arr) || _unsupportedIterableToArray(arr) || _nonIterableSpread(); }
function _nonIterableSpread() { throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _iterableToArray(iter) { if (typeof Symbol !== "undefined" && iter[Symbol.iterator] != null || iter["@@iterator"] != null) return Array.from(iter); }
function _arrayWithoutHoles(arr) { if (Array.isArray(arr)) return _arrayLikeToArray(arr); }
function _slicedToArray(arr, i) { return _arrayWithHoles(arr) || _iterableToArrayLimit(arr, i) || _unsupportedIterableToArray(arr, i) || _nonIterableRest(); }
function _nonIterableRest() { throw new TypeError("Invalid attempt to destructure non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method."); }
function _unsupportedIterableToArray(o, minLen) { if (!o) return; if (typeof o === "string") return _arrayLikeToArray(o, minLen); var n = Object.prototype.toString.call(o).slice(8, -1); if (n === "Object" && o.constructor) n = o.constructor.name; if (n === "Map" || n === "Set") return Array.from(o); if (n === "Arguments" || /^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(n)) return _arrayLikeToArray(o, minLen); }
function _arrayLikeToArray(arr, len) { if (len == null || len > arr.length) len = arr.length; for (var i = 0, arr2 = new Array(len); i < len; i++) arr2[i] = arr[i]; return arr2; }
function _iterableToArrayLimit(r, l) { var t = null == r ? null : "undefined" != typeof Symbol && r[Symbol.iterator] || r["@@iterator"]; if (null != t) { var e, n, i, u, a = [], f = !0, o = !1; try { if (i = (t = t.call(r)).next, 0 === l) { if (Object(t) !== t) return; f = !1; } else for (; !(f = (e = i.call(t)).done) && (a.push(e.value), a.length !== l); f = !0); } catch (r) { o = !0, n = r; } finally { try { if (!f && null != t.return && (u = t.return(), Object(u) !== u)) return; } finally { if (o) throw n; } } return a; } }
function _arrayWithHoles(arr) { if (Array.isArray(arr)) return arr; }
import dayjs from 'dayjs';
import { buildCalendarTimelineSlotStartsFromRange } from "../../../../pisellTimeNavigator/utils";
import { tCal } from "../calendarI18n";
import { DAY_OVERLAY_VISIBLE_BOOKING_CAP, dayRowHeight, DEFAULT_CALENDAR_TIMELINE, timeSliceMinutes } from "../const/bookingCalendarConstants";

/**
 * 日历日期与时间轴纯函数：`fmtDate`、占用矩阵、月格、overlay 分段、周范围等，供 BookingCalendar 三视图共用。
 */

/** 与 {@link RecordBoardCalendarBookingLike} 一致，并支持跨日 endDate */

export function fmtDate(date) {
  var y = date.getFullYear();
  var m = "".concat(date.getMonth() + 1).padStart(2, '0');
  var d = "".concat(date.getDate()).padStart(2, '0');
  return "".concat(y, "-").concat(m, "-").concat(d);
}

/** 本地当前日期键与「日历时」小数小时，用于状态徽标与当前时刻线 */
export function getViewNowReference() {
  var d = new Date();
  return {
    dateKey: fmtDate(d),
    hourFloat: d.getHours() + d.getMinutes() / 60 + d.getSeconds() / 3600
  };
}
export function parseDate(str) {
  var _str$split$map = str.split('-').map(Number),
    _str$split$map2 = _slicedToArray(_str$split$map, 3),
    y = _str$split$map2[0],
    m = _str$split$map2[1],
    d = _str$split$map2[2];
  return new Date(y, m - 1, d);
}
export function addDays(date, n) {
  var next = new Date(date);
  next.setDate(next.getDate() + n);
  return next;
}
export function startOfWeek(date) {
  var d = new Date(date);
  var day = d.getDay();
  var diff = day === 0 ? -6 : 1 - day;
  d.setDate(d.getDate() + diff);
  d.setHours(0, 0, 0, 0);
  return d;
}
export function rangeDays(anchor) {
  var start = startOfWeek(anchor);
  return Array.from({
    length: 7
  }, function (_, i) {
    return addDays(start, i);
  });
}

/**
 * 锚定日所在自然月的每一天（1 号至月末），用于资源视图横向「日」列。
 */
export function monthCalendarDays(anchor) {
  var base = anchor instanceof Date && !Number.isNaN(anchor.getTime()) ? anchor : new Date();
  var y = base.getFullYear();
  var m = base.getMonth();
  var last = new Date(y, m + 1, 0).getDate();
  return Array.from({
    length: last
  }, function (_, i) {
    return new Date(y, m, i + 1);
  });
}
export function isHourInTimelineSlots(hour, hourSlots) {
  if (!(hourSlots !== null && hourSlots !== void 0 && hourSlots.length)) return false;
  return hourSlots.some(function (x) {
    return Math.abs(x - hour) < 1e-6;
  });
}
export function formatHourLabel(hour) {
  var totalMin = Math.round(hour * 60);
  var h = Math.floor(totalMin / 60);
  var m = totalMin % 60;
  var clockH = (h % 24 + 24) % 24;
  return "".concat(String(clockH).padStart(2, '0'), ":").concat(String(m).padStart(2, '0'));
}
export function buildTimeOptions() {
  var start = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 8;
  var end = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 20;
  var sliceMinutes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : timeSliceMinutes;
  var out = [];
  for (var m = start * 60; m <= end * 60; m += sliceMinutes) out.push(m / 60);
  return out;
}
export function monthGrid(date, bookings) {
  var courtsList = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : [];
  var hourSlotsIn = arguments.length > 3 ? arguments[3] : undefined;
  var slotStepHours = arguments.length > 4 && arguments[4] !== undefined ? arguments[4] : 1;
  var hourSlots = hourSlotsIn && hourSlotsIn.length ? hourSlotsIn : buildCalendarTimelineSlotStartsFromRange(DEFAULT_CALENDAR_TIMELINE, date, 60);
  var year = date.getFullYear();
  var month = date.getMonth();
  var first = new Date(year, month, 1);
  var start = startOfWeek(first);
  var days = Array.from({
    length: 35
  }, function (_, i) {
    return addDays(start, i);
  });
  return days.map(function (day) {
    var key = fmtDate(day);
    var dayBookings = bookings.filter(function (b) {
      return b.date === key && b.kind === 'booking';
    });
    var blocks = bookings.filter(function (b) {
      return b.date === key && b.kind === 'block';
    });
    var fullyBookedCourts = courtsList.filter(function (court) {
      var _hourSlots$length;
      var items = bookings.filter(function (b) {
        return b.courtId === court.id && b.date === key;
      });
      var occupied = new Set();
      items.forEach(function (b) {
        (hourSlots || []).forEach(function (slotStart) {
          var seg = getBookingSegmentForDate(b, key);
          if (seg && seg.startHour < slotStart + slotStepHours && seg.endHour > slotStart) {
            occupied.add(slotStart);
          }
        });
      });
      var slotCount = (_hourSlots$length = hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length) !== null && _hourSlots$length !== void 0 ? _hourSlots$length : 14;
      return occupied.size >= slotCount;
    }).length;
    return {
      date: day,
      key: key,
      inMonth: day.getMonth() === month,
      bookingCount: dayBookings.length,
      blockCount: blocks.length,
      fullyBooked: fullyBookedCourts >= courtsList.length
    };
  });
}
export function getBookingSegmentForDate(item, dateKey) {
  if (!item.endDate || item.endDate === item.date) {
    if (item.date !== dateKey) return null;
    return {
      startHour: item.startHour,
      endHour: item.endHour,
      continuesPrev: false,
      continuesNext: false
    };
  }
  if (dateKey < item.date || dateKey > item.endDate) return null;
  if (dateKey === item.date) return {
    startHour: item.startHour,
    endHour: 24,
    continuesPrev: false,
    continuesNext: true
  };
  if (dateKey === item.endDate) return {
    startHour: 0,
    endHour: item.endHour,
    continuesPrev: true,
    continuesNext: false
  };
  return {
    startHour: 0,
    endHour: 24,
    continuesPrev: true,
    continuesNext: true
  };
}
export function dayOccupancy(courtId, dateKey, bookings, hourSlots, slotStepHours) {
  var items = bookings.filter(function (b) {
    return b.courtId === courtId && getBookingSegmentForDate(b, dateKey);
  });
  var map = {};
  var stepH = slotStepHours > 0 ? slotStepHours : 1;
  (hourSlots || []).forEach(function (hour) {
    map[hour] = items.find(function (b) {
      var seg = getBookingSegmentForDate(b, dateKey);
      return seg && seg.startHour < hour + stepH && seg.endHour > hour;
    }) || null;
  });
  return map;
}
export function groupSelectedSlots(slots) {
  var slotStepHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  var stepH = slotStepHours > 0 ? slotStepHours : 1;
  var sorted = _toConsumableArray(slots).sort(function (a, b) {
    if (a.date !== b.date) return a.date.localeCompare(b.date);
    if (a.courtId !== b.courtId) return a.courtId.localeCompare(b.courtId);
    return a.hour - b.hour;
  });
  var groups = [];
  sorted.forEach(function (slot) {
    var prev = groups[groups.length - 1];
    if (prev && prev.courtId === slot.courtId && prev.date === slot.date && Math.abs(prev.endHour - slot.hour) < 1e-6) prev.endHour = slot.hour + stepH;else groups.push({
      courtId: slot.courtId,
      date: slot.date,
      startHour: slot.hour,
      endHour: slot.hour + stepH
    });
  });
  return groups;
}

/**
 * 日视图空闲格：仅当全部为同一 court、同一日，且时间上首尾相接成一段时返回 true（与 {@link groupSelectedSlots} 合并规则一致）。
 */
export function isFreeSelectionContiguousSameResource(slots) {
  var slotStepHours = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 1;
  if (!Array.isArray(slots) || slots.length === 0) return false;
  return groupSelectedSlots(slots, slotStepHours).length === 1;
}
export function hasConflict(bookings, courtId, date, startHour, endHour) {
  var ignoreId = arguments.length > 5 && arguments[5] !== undefined ? arguments[5] : null;
  return bookings.some(function (b) {
    if (b.id === ignoreId) return false;
    if (b.kind !== 'booking') return false;
    if (b.courtId !== courtId || b.date !== date) return false;
    return !(endHour <= b.startHour || startHour >= b.endHour);
  });
}
export function overlappingBookings(bookings, courtId, date, startHour, endHour) {
  return bookings.filter(function (b) {
    if (b.kind !== 'booking') return false;
    if (b.courtId !== courtId || b.date !== date) return false;
    return !(endHour <= b.startHour || startHour >= b.endHour);
  });
}
export function courtDaySummary(courtId, dateKey, bookings, hourSlots, slotStepHours) {
  var _hourSlots$length2;
  var occ = dayOccupancy(courtId, dateKey, bookings, hourSlots, slotStepHours);
  var items = bookings.filter(function (b) {
    return b.courtId === courtId && b.date === dateKey;
  }).sort(function (a, b) {
    return a.startHour - b.startHour;
  });
  var occupiedHours = (hourSlots || []).filter(function (h) {
    return occ[h] && isHourInTimelineSlots(h, hourSlots);
  });
  var hasBlock = occupiedHours.some(function (h) {
    var _occ$h;
    return ((_occ$h = occ[h]) === null || _occ$h === void 0 ? void 0 : _occ$h.kind) === 'block';
  });
  var slotCount = (_hourSlots$length2 = hourSlots === null || hourSlots === void 0 ? void 0 : hourSlots.length) !== null && _hourSlots$length2 !== void 0 ? _hourSlots$length2 : 0;
  var fullyBooked = slotCount > 0 && occupiedHours.length >= slotCount;
  return {
    occupiedHours: occupiedHours,
    hasBlock: hasBlock,
    fullyBooked: fullyBooked,
    items: items
  };
}
export function sameSlot(a, b) {
  return a.courtId === b.courtId && a.date === b.date && a.hour === b.hour;
}

/** 营业日 `dateStr` + 浮点小时（含半格）→ dayjs */
export function dayAndHourToDayjs(dateStr, hourFloat) {
  var h = Math.floor(hourFloat);
  var m = Math.round((hourFloat - h) * 60);
  var mm = Math.min(59, Math.max(0, m));
  return dayjs("".concat(dateStr, " ").concat(String(h).padStart(2, '0'), ":").concat(String(mm).padStart(2, '0')), 'YYYY-MM-DD HH:mm');
}
export function getDisplayStatusTag(item, dateKey) {
  if (item.kind !== 'booking') return item.statusTag || null;
  if (item.statusTag === 'checked_in' || item.statusTag === 'cancel') return item.statusTag;
  var _getViewNowReference = getViewNowReference(),
    todayKey = _getViewNowReference.dateKey,
    nowHour = _getViewNowReference.hourFloat;
  if (dateKey !== todayKey) return item.statusTag || null;
  var seg = getBookingSegmentForDate(item, dateKey);
  if (!seg) return item.statusTag || null;
  var lateThreshold = item.startHour + 5 / 60;
  if (nowHour > seg.endHour) return 'no_show';
  if (nowHour > lateThreshold) return 'late';
  return item.statusTag || null;
}
export function getLateMinutes(item, dateKey) {
  if (getDisplayStatusTag(item, dateKey) !== 'late') return null;
  var seg = getBookingSegmentForDate(item, dateKey);
  if (!seg) return null;
  var lateThreshold = seg.startHour + 5 / 60;
  var _getViewNowReference2 = getViewNowReference(),
    nowHour = _getViewNowReference2.hourFloat;
  return Math.max(1, Math.floor((nowHour - lateThreshold) * 60));
}
export function currentTimeLabel() {
  var d = new Date();
  return "".concat(String(d.getHours()).padStart(2, '0'), ":").concat(String(d.getMinutes()).padStart(2, '0'));
}
export function formatDateLoose(str) {
  if (!str) return '';
  var d = parseDate(str);
  return "".concat(d.getFullYear(), " ").concat(String(d.getMonth() + 1).padStart(2, '0'), " ").concat(String(d.getDate()).padStart(2, '0'));
}
export function formatTimelineStamp(value) {
  if (!value) return {
    date: '--',
    time: '--'
  };
  var normalized = String(value).replace('T', ' ');
  var _normalized$split = normalized.split(' '),
    _normalized$split2 = _slicedToArray(_normalized$split, 2),
    _normalized$split2$ = _normalized$split2[0],
    date = _normalized$split2$ === void 0 ? '--' : _normalized$split2$,
    _normalized$split2$2 = _normalized$split2[1],
    time = _normalized$split2$2 === void 0 ? '--' : _normalized$split2$2;
  return {
    date: date,
    time: time.slice(0, 5) || '--'
  };
}

/** 日视图 overlay 条（可原地写入 lane） */

/**
 * 同一 court 上时间重叠的 overlay 分配纵向 lane，避免多张卡片完全叠在同一矩形里。
 * 使用按开始时间排序 + 贪心：每条预约放入「上一条已结束时间不晚于本段开始」的最小编号线。
 */
export function assignDayOverlapLanesInPlace(overlays) {
  var byCourt = new Map();
  var _iterator = _createForOfIteratorHelper(overlays),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var _o3 = _step.value;
      var _list = byCourt.get(_o3.courtId);
      if (_list) _list.push(_o3);else byCourt.set(_o3.courtId, [_o3]);
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  for (var _i = 0, _Array$from = Array.from(byCourt.values()); _i < _Array$from.length; _i++) {
    var list = _Array$from[_i];
    list.sort(function (a, b) {
      if (a.start !== b.start) return a.start - b.start;
      return b.span - a.span;
    });
    var laneEnds = [];
    var _iterator2 = _createForOfIteratorHelper(list),
      _step2;
    try {
      for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
        var o = _step2.value;
        var oEnd = o.start + o.span;
        var _lane = 0;
        while (_lane < laneEnds.length && laneEnds[_lane] > o.start) {
          _lane++;
        }
        if (_lane === laneEnds.length) {
          laneEnds.push(oEnd);
        } else {
          laneEnds[_lane] = oEnd;
        }
        o.lane = _lane;
      }
    } catch (err) {
      _iterator2.e(err);
    } finally {
      _iterator2.f();
    }
    var maxL = 0;
    var _iterator3 = _createForOfIteratorHelper(list),
      _step3;
    try {
      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
        var _o$lane;
        var _o = _step3.value;
        maxL = Math.max(maxL, (_o$lane = _o.lane) !== null && _o$lane !== void 0 ? _o$lane : 0);
      }
    } catch (err) {
      _iterator3.e(err);
    } finally {
      _iterator3.f();
    }
    var laneCount = Math.max(1, maxL + 1);
    var _iterator4 = _createForOfIteratorHelper(list),
      _step4;
    try {
      for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
        var _o2 = _step4.value;
        _o2.laneCount = laneCount;
      }
    } catch (err) {
      _iterator4.e(err);
    } finally {
      _iterator4.f();
    }
  }
}

/** 扫描时间轴：同一 court 在任一时刻的最大并行条数（用于行高，与分 lane 一致） */
export function maxConcurrentBookingsOnCourt(overlays, courtId) {
  var ev = [];
  var _iterator5 = _createForOfIteratorHelper(overlays),
    _step5;
  try {
    for (_iterator5.s(); !(_step5 = _iterator5.n()).done;) {
      var o = _step5.value;
      if (o.courtId !== courtId) continue;
      ev.push({
        t: o.start,
        d: 1
      });
      ev.push({
        t: o.start + o.span,
        d: -1
      });
    }
    /** 同一时刻先处理结束 (-1) 再处理开始 (+1)，区间按 [start, end) 半开，避免「上一段 end == 下一段 start」被算成重叠 */
  } catch (err) {
    _iterator5.e(err);
  } finally {
    _iterator5.f();
  }
  ev.sort(function (a, b) {
    if (a.t !== b.t) return a.t - b.t;
    return a.d - b.d;
  });
  var c = 0;
  var m = 0;
  for (var _i2 = 0, _ev = ev; _i2 < _ev.length; _i2++) {
    var e = _ev[_i2];
    c += e.d;
    m = Math.max(m, c);
  }
  return Math.max(1, m);
}

/** 并行超过 cap 时：cap 条内容 + 1 行「+N」占位 */
export function effectiveDayOverlayDisplayLaneCount(rawConcurrent) {
  if (rawConcurrent <= DAY_OVERLAY_VISIBLE_BOOKING_CAP) return Math.max(1, rawConcurrent);
  return DAY_OVERLAY_VISIBLE_BOOKING_CAP + 1;
}

/** 同一 court 下时间轴区间相交的 overlay 归为一簇（用于 3+N 合并展示） */
export function clusterDayCourtOverlaysByOverlap(overlays, courtId) {
  var list = overlays.filter(function (o) {
    return o.courtId === courtId;
  });
  if (!list.length) return [];
  var sorted = _toConsumableArray(list).sort(function (a, b) {
    if (a.start !== b.start) return a.start - b.start;
    return a.start + a.span - (b.start + b.span);
  });
  var clusters = [];
  var cur = [];
  var curMaxEnd = -Infinity;
  var _iterator6 = _createForOfIteratorHelper(sorted),
    _step6;
  try {
    for (_iterator6.s(); !(_step6 = _iterator6.n()).done;) {
      var o = _step6.value;
      var oe = o.start + o.span;
      if (!cur.length) {
        cur = [o];
        curMaxEnd = oe;
        continue;
      }
      if (o.start < curMaxEnd - 1e-9) {
        cur.push(o);
        curMaxEnd = Math.max(curMaxEnd, oe);
      } else {
        clusters.push(cur);
        cur = [o];
        curMaxEnd = oe;
      }
    }
  } catch (err) {
    _iterator6.e(err);
  } finally {
    _iterator6.f();
  }
  if (cur.length) clusters.push(cur);
  return clusters;
}
export function dayOverlayHiddenKey(item, dayKey, courtId) {
  var id = (item === null || item === void 0 ? void 0 : item.id) != null ? String(item.id) : '';
  return "".concat(String(courtId), "\0").concat(id, "\0").concat(dayKey);
}

/**
 * 将 totalInner 像素整数分给 n 条竖向 lane（含缝），保证 Σheight + Σgap === totalInner，消除底部留白缝。
 */
export function dayOverlayLaneMetrics(totalInner, laneCount, gap) {
  var n = Math.max(1, laneCount);
  if (n === 1) {
    return {
      topFor: function topFor() {
        return 0;
      },
      heightFor: function heightFor() {
        return totalInner;
      }
    };
  }
  var gapsTotal = (n - 1) * gap;
  var body = Math.max(0, totalInner - gapsTotal);
  var base = Math.floor(body / n);
  var rem = body % n;
  var heights = [];
  for (var i = 0; i < n; i += 1) {
    heights.push(base + (i < rem ? 1 : 0));
  }
  var offsets = [0];
  for (var _i3 = 1; _i3 < n; _i3 += 1) {
    offsets.push(offsets[_i3 - 1] + heights[_i3 - 1] + gap);
  }
  return {
    topFor: function topFor(lane) {
      var _offsets$Math$min;
      return (_offsets$Math$min = offsets[Math.min(lane, n - 1)]) !== null && _offsets$Math$min !== void 0 ? _offsets$Math$min : 0;
    },
    heightFor: function heightFor(lane) {
      var _heights$Math$min;
      return (_heights$Math$min = heights[Math.min(lane, n - 1)]) !== null && _heights$Math$min !== void 0 ? _heights$Math$min : base;
    }
  };
}
export function buildOverlayBookings(visibleCourtRows, dayKey, bookings) {
  var rowTopMap = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : {};
  var hourSlots = arguments.length > 4 ? arguments[4] : undefined;
  var dayRowHeights = arguments.length > 5 ? arguments[5] : undefined;
  var slotStepHours = arguments.length > 6 && arguments[6] !== undefined ? arguments[6] : 1;
  var courtRowIndexMap = new Map();
  visibleCourtRows.forEach(function (row, index) {
    if (row.kind === 'court') courtRowIndexMap.set(row.id, index);
  });
  var stepH = slotStepHours > 0 ? slotStepHours : 1;
  var gridMin = hourSlots !== null && hourSlots !== void 0 && hourSlots.length ? hourSlots[0] : 0;
  var gridMaxExclusive = hourSlots !== null && hourSlots !== void 0 && hourSlots.length ? hourSlots[hourSlots.length - 1] + stepH : 24;
  var seen = new Set();
  var out = [];
  var _loop = function _loop() {
    var _dayRowHeights$i;
    var row = visibleCourtRows[i];
    if (row.kind !== 'court') return 1; // continue
    var rowHeight = (_dayRowHeights$i = dayRowHeights[i]) !== null && _dayRowHeights$i !== void 0 ? _dayRowHeights$i : dayRowHeight;
    var _iterator7 = _createForOfIteratorHelper(bookings.filter(function (b) {
        return b.courtId === row.id;
      })),
      _step7;
    try {
      for (_iterator7.s(); !(_step7 = _iterator7.n()).done;) {
        var _item$id;
        var item = _step7.value;
        var dedupeKey = "".concat(row.id, "\0").concat((_item$id = item.id) !== null && _item$id !== void 0 ? _item$id : '', "\0").concat(dayKey);
        if (seen.has(dedupeKey)) continue;
        var seg = getBookingSegmentForDate(item, dayKey);
        if (!seg) continue;
        var start = Math.max(seg.startHour, gridMin);
        var end = Math.min(seg.endHour, gridMaxExclusive);
        if (end <= start) continue;
        seen.add(dedupeKey);
        out.push({
          item: item,
          rowIndex: courtRowIndexMap.get(row.id) || 0,
          rowTop: rowTopMap[row.id] || 0,
          rowHeight: rowHeight,
          courtId: row.id,
          start: start,
          end: end,
          span: end - start,
          continuesNext: seg.continuesNext,
          continuesPrev: seg.continuesPrev
        });
      }
    } catch (err) {
      _iterator7.e(err);
    } finally {
      _iterator7.f();
    }
  };
  for (var i = 0; i < visibleCourtRows.length; i++) {
    if (_loop()) continue;
  }
  assignDayOverlapLanesInPlace(out);
  return out;
}

/** 日视图：按行高累加每行 rowTop（court / group） */
export function buildDayRowTopMap(visibleCourtRows, heights) {
  var acc = 0;
  var map = {};
  visibleCourtRows.forEach(function (row, index) {
    var _heights$index;
    map[row.id] = acc;
    acc += (_heights$index = heights[index]) !== null && _heights$index !== void 0 ? _heights$index : dayRowHeight;
  });
  return map;
}

/** 日历状态徽标：返回 i18n key + className；文案在 UI 层通过 tCal 解析，便于 utils 单测 */
export function statusTagMetaParts(tag) {
  switch (tag) {
    case 'cancel':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.cancel',
        className: 'bg-red-600/88 text-white border border-red-300/35'
      };
    case 'change':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.change',
        className: 'bg-amber-500/88 text-white border border-amber-200/35'
      };
    case 'checked_in':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.checkedIn',
        className: 'bg-zinc-500/88 text-white border border-zinc-300/30'
      };
    case 'pending':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.pending',
        className: 'bg-cyan-600/88 text-white border border-cyan-300/35'
      };
    case 'new':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.new',
        className: 'bg-emerald-600/88 text-white border border-emerald-300/35'
      };
    case 'late':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.late',
        className: 'bg-amber-500/88 text-white border border-amber-200/35'
      };
    case 'no_show':
      return {
        labelI18nKey: 'pisell2.recordBoard.calendar.status.noShow',
        className: 'bg-red-700/92 text-white border border-red-300/35'
      };
    default:
      return null;
  }
}
export function getBookingDetailData(item) {
  var _item$courtId, _item$id2, _item$id3, _item$id4;
  var courtsList = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : [];
  var court = courtsList.find(function (c) {
    return c.id === item.courtId;
  });
  var resourceLabel = (court === null || court === void 0 ? void 0 : court.name) != null && String(court.name).trim() !== '' ? String(court.name) : String((_item$courtId = item.courtId) !== null && _item$courtId !== void 0 ? _item$courtId : '—');
  var startTime = formatHourLabel(item.startHour);
  var endTime = formatHourLabel(item.endHour);
  var endDate = item.endDate || item.date;
  var isBlock = item.kind === 'block';
  var customerName = isBlock ? item.blockBy || tCal('pisell2.recordBoard.calendar.detail.staff') : item.name || '—';
  var noteText = item.note ? String(item.note) : '';
  var orderNotes = noteText ? [{
    id: "".concat(item.id, "-note-order"),
    label: tCal('pisell2.recordBoard.calendar.detail.orderNote'),
    text: noteText
  }] : [];
  return {
    rawSales: null,
    bookingId: String((_item$id2 = item.id) !== null && _item$id2 !== void 0 ? _item$id2 : '').toUpperCase(),
    orderNumber: String((_item$id3 = item.id) !== null && _item$id3 !== void 0 ? _item$id3 : ''),
    shopOrderNumber: String((_item$id4 = item.id) !== null && _item$id4 !== void 0 ? _item$id4 : ''),
    orderStatus: 'normal',
    appointmentStatus: isBlock ? 'blocked' : 'confirmed',
    paymentStatus: 'payment_processing',
    customer: {
      id: null,
      name: customerName,
      email: '',
      phone: item.phone ? String(item.phone) : ''
    },
    guestCount: 0,
    checkedInCount: 0,
    guests: [],
    schedule: {
      startDate: item.date,
      startTime: startTime,
      endDate: endDate,
      endTime: endTime,
      duration: Math.max(0, (item.endHour - item.startHour) * 60),
      arrivedAt: null,
      completedAt: null
    },
    resources: [],
    summaryItems: [],
    items: [],
    note: noteText,
    files: {
      form: [],
      uploaded: [],
      invoice: []
    },
    payments: [],
    history: [],
    summary: {},
    paymentSummary: {
      totalAmount: 0,
      paidAmount: 0,
      balanceAmount: 0,
      currencySymbol: '$',
      isFullyPaid: false
    },
    itemSummary: {
      itemCount: 0,
      itemQtyTotal: 0
    },
    headerSummary: {
      customerName: customerName,
      guestCount: 0,
      checkedInCount: 0,
      timeLabel: "".concat(item.date, " \xB7 ").concat(startTime, " - ").concat(endTime),
      resourceLabel: resourceLabel
    },
    headerTags: {
      paymentTag: 'Unpaid',
      fulfillmentTag: 'Open',
      hasNote: Boolean(noteText),
      paymentStatus: 'payment_processing',
      orderStatus: 'normal'
    },
    fileCount: 0,
    canChangeCustomer: !isBlock,
    noteCount: orderNotes.length,
    noteGroups: {
      internal: [],
      order: orderNotes,
      item: []
    },
    metaFlags: {
      itemsChanged: false,
      paymentsChanged: false,
      guestChanged: false,
      filesChanged: false,
      notesChanged: false,
      formChanged: false,
      uploadedChanged: false,
      invoiceChanged: false,
      historyChanged: false
    },
    actions: []
  };
}