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 _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';
/** 将 HH:mm 或 HH:mm:ss 解析为当天该时间的 dayjs（基于 reference 的日期） */
function parseTimeOfDay(timeStr, reference) {
  var _timeStr$trim$split$m = timeStr.trim().split(':').map(Number),
    _timeStr$trim$split$m2 = _slicedToArray(_timeStr$trim$split$m, 3),
    h = _timeStr$trim$split$m2[0],
    m = _timeStr$trim$split$m2[1],
    s = _timeStr$trim$split$m2[2];
  return reference.hour(isNaN(h) ? 0 : h).minute(isNaN(m) ? 0 : m).second(isNaN(s) ? 0 : s).millisecond(0);
}

/** 匹配 HH:mm 或 HH:mm:ss 这类纯时间字符串 */
var TIME_ONLY_REGEX = /^\s*\d{1,2}:\d{2}(:\d{2})?\s*$/;

/**
 * 解析 value 为 Dayjs，无效则返回 null。
 * 支持 dayjs 可解析的日期时间；纯时间字符串（如 '12:00'、'14:30'）会基于 reference 的日期解析。
 */
export function parseValue(value, reference) {
  if (value == null) return null;
  var ref = reference !== null && reference !== void 0 ? reference : dayjs();
  if (typeof value === 'string' && TIME_ONLY_REGEX.test(value)) {
    return parseTimeOfDay(value, ref);
  }
  var d = dayjs(value);
  return d.isValid() ? d : null;
}

/** 日历时间轴默认步长（分钟），与历史「整点列」一致 */
export var DEFAULT_CALENDAR_SLOT_STEP_MINUTES = 60;

/**
 * 按营业日 {@link TimeRangeOption} 在锚定自然日零点展开，生成日视图时间轴「列左边界」：
 * 值为相对 `reference.startOf('day')` 的**浮点小时**（可 ≥24，表示次日时刻），步长为 `slotStepMinutes`。
 */
export function buildCalendarTimelineSlotStartsFromRange(range, anchorDate) {
  var slotStepMinutes = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : DEFAULT_CALENDAR_SLOT_STEP_MINUTES;
  var step = Math.max(1, Math.min(24 * 60, Math.round(Number(slotStepMinutes)) || 60));
  var ref = dayjs(anchorDate).startOf('day');
  var _getRangeBounds = getRangeBounds(range, ref),
    _getRangeBounds2 = _slicedToArray(_getRangeBounds, 2),
    rs = _getRangeBounds2[0],
    re = _getRangeBounds2[1];
  var out = [];
  var cur = rs;
  while (cur.isBefore(re)) {
    out.push(cur.diff(ref, 'minute', true) / 60);
    cur = cur.add(step, 'minute');
  }
  if (out.length === 0) {
    for (var m = 8 * 60; m < 20 * 60; m += step) out.push(m / 60);
  }
  return out;
}

/**
 * @deprecated 语义上等价于 {@link buildCalendarTimelineSlotStartsFromRange}(..., 60)；保留兼容导出。
 */
export function buildCalendarHourSlotsFromRange(range, anchorDate) {
  return buildCalendarTimelineSlotStartsFromRange(range, anchorDate, DEFAULT_CALENDAR_SLOT_STEP_MINUTES);
}

/**
 * 将 range 转为 [startDayjs, endDayjs]（reference 为营业锚定日的 0 点）
 * - 同日内：如 08:00–22:00
 * - 跨日营业：结束钟面早于或等于开始（如 02:01–次日 02:00）时，end 解析为 reference 的次日同一时刻
 */
export function getRangeBounds(range, reference) {
  if (!range) {
    return [reference.startOf('day'), reference.endOf('day')];
  }
  var start = parseTimeOfDay(range.start, reference);
  var end = parseTimeOfDay(range.end, reference);
  if (end.isBefore(start) || end.isSame(start)) {
    end = parseTimeOfDay(range.end, reference.add(1, 'day'));
  }
  return [start, end];
}

/**
 * 自动挑选「能让 `now` 落入 [refDay + range.start, refDay + range.end] 营业窗口」的锚定日。
 *
 * 调用方未显式传入 `referenceDate` 时使用：保证当前时刻始终在轴可视范围内，
 * 横向「现在」橙色高亮 / 竖向当前时间横线永远展示。
 *
 * 解析顺序：
 * 1. 先尝试 `now.startOf('day')`（典型场景：跨日营业 18:00–04:00 时，下午 20:00 直接命中今天的窗口）；
 * 2. 命中失败时尝试前一日（如营业 16:00–次日 16:00，now = 中午 12:00 时窗口需锚到昨天）；
 * 3. 再尝试次日（如营业 16:00–次日 16:00，now 处于「即将进入下一个营业日」的边界附近）；
 * 4. 三个候选都不包含 now（营业时段较短且 now 落在闭店时段，如 09:00–22:00 + now=23:00）时，
 *    回退到 `now.startOf('day')`，保持原有行为，不强行扭曲日期。
 */
export function pickReferenceDateContainingNow(range, now) {
  var today = now.startOf('day');
  var candidates = [today, today.subtract(1, 'day'), today.add(1, 'day')];
  for (var _i = 0, _candidates = candidates; _i < _candidates.length; _i++) {
    var cand = _candidates[_i];
    var _getRangeBounds3 = getRangeBounds(range, cand),
      _getRangeBounds4 = _slicedToArray(_getRangeBounds3, 2),
      s = _getRangeBounds4[0],
      e = _getRangeBounds4[1];
    if (!now.isBefore(s) && !now.isAfter(e)) {
      return cand;
    }
  }
  return today;
}

/**
 * 将时间吸附到 step 分钟刻度（0、15、30、45 等）：四舍五入到最近刻度。
 */
export function snapToStepMinutes(t, stepMinutes) {
  var m = t.minute();
  var snapped = Math.round(m / stepMinutes) * stepMinutes;
  if (snapped >= 60) {
    return t.add(1, 'hour').minute(0).second(0).millisecond(0);
  }
  return t.minute(snapped).second(0).millisecond(0);
}

/**
 * 判断时间是否落在任一禁用区间内（按绝对时间与区间 [start,end) 比较）
 * 注：与主时间轴同 reference 的跨日 range 一致时需传入同一营业锚定日解析出的区间。
 */
export function isInDisabledRanges(t, disabledRanges) {
  if (!(disabledRanges !== null && disabledRanges !== void 0 && disabledRanges.length)) return false;
  var tMin = t.startOf('minute');
  var _iterator = _createForOfIteratorHelper(disabledRanges),
    _step;
  try {
    for (_iterator.s(); !(_step = _iterator.n()).done;) {
      var r = _step.value;
      var _getRangeBounds5 = getRangeBounds(r, t.startOf('day')),
        _getRangeBounds6 = _slicedToArray(_getRangeBounds5, 2),
        s = _getRangeBounds6[0],
        e = _getRangeBounds6[1];
      if ((tMin.isAfter(s) || tMin.isSame(s)) && tMin.isBefore(e)) return true;
    }
  } catch (err) {
    _iterator.e(err);
  } finally {
    _iterator.f();
  }
  return false;
}

/**
 * 在 [rangeStart, rangeEnd] 内按 stepMinutes 生成等步刻度时间列表（Dayjs）。
 *
 * @deprecated 仅用于不需要「头/尾 partial 格」的场景；时间轴渲染请用 {@link getAxisCells}。
 */
export function getTicks(rangeStart, rangeEnd, stepMinutes) {
  var out = [];
  var cur = rangeStart;
  while (!cur.isAfter(rangeEnd)) {
    out.push(cur);
    cur = cur.add(stepMinutes, 'minute');
  }
  return out;
}

/**
 * 时间轴上一格的描述：起始时间 + 跨度（分钟）。
 * - 中间格：跨度 = `stepMinutes`，起点对齐到 step 网格（如 15 分钟一格时落在 `:00/:15/:30/:45`）；
 * - head 格：当 `rangeStart` 不在网格上时存在，起点 = `rangeStart`，跨度 < step；
 * - tail 格：当 `rangeEnd` 不在网格上时存在，起点 = 最后一个对齐点，跨度 < step。
 */

/**
 * 把 [`rangeStart`, `rangeEnd`] 切成「对齐到 step 网格」的格子序列：
 *
 * 1. 找到第一个 ≥ `rangeStart` 且分钟为 `stepMinutes` 整数倍的对齐点；
 * 2. 若对齐点严格大于 `rangeStart`，先放一格 head（`rangeStart` → 对齐点），跨度 < step；
 * 3. 中间按 step 步进，每格起点都落在网格上；
 * 4. 若 `rangeEnd` 落在两个对齐点之间，最后多出一格 tail（最后对齐点 → `rangeEnd`），跨度 < step。
 *
 * `rangeStart` / `rangeEnd` 都恰落在网格上时退化为完全等步格。
 */
export function getAxisCells(rangeStart, rangeEnd, stepMinutes) {
  var out = [];
  if (!rangeEnd.isAfter(rangeStart) || stepMinutes <= 0) return out;
  var startMin = rangeStart.minute();
  var remainder = (startMin % stepMinutes + stepMinutes) % stepMinutes;
  var isStartAligned = remainder === 0 && rangeStart.second() === 0 && rangeStart.millisecond() === 0;
  var firstAligned = isStartAligned ? rangeStart : rangeStart.startOf('hour').minute(startMin - remainder + stepMinutes).second(0).millisecond(0);
  if (firstAligned.isAfter(rangeStart)) {
    var headMin = firstAligned.diff(rangeStart, 'minute', true);
    if (headMin > 0) {
      out.push({
        start: rangeStart,
        widthMinutes: headMin
      });
    }
  }
  var cur = firstAligned;
  /**
   * 防御：超大 / 非法 range 时（如 1 年）直接挂死。这里限制最多 2 天 + 1 步的格数，
   * 与 useTimeAxis 的 `totalLengthPx` 上限呼应。
   */
  var safetyLimit = 2 * 24 * 60 / stepMinutes + 4;
  while (cur.isBefore(rangeEnd) && out.length < safetyLimit) {
    var next = cur.add(stepMinutes, 'minute');
    if (next.isAfter(rangeEnd)) {
      var tailMin = rangeEnd.diff(cur, 'minute', true);
      if (tailMin > 0) {
        out.push({
          start: cur,
          widthMinutes: tailMin
        });
      }
      break;
    }
    out.push({
      start: cur,
      widthMinutes: stepMinutes
    });
    cur = next;
  }
  return out;
}

/**
 * 横向时间轴「格」数量，与 useTimeAxis 中 cells 算法一致。
 * 用于 cursor-moves 模式下计算压缩后的每格像素宽度。
 */
export function getHorizontalAxisSlotCount(range, referenceDate, stepMinutes) {
  var _getRangeBounds7 = getRangeBounds(range, referenceDate),
    _getRangeBounds8 = _slicedToArray(_getRangeBounds7, 2),
    rangeStart = _getRangeBounds8[0],
    rangeEnd = _getRangeBounds8[1];
  return getAxisCells(rangeStart, rangeEnd, stepMinutes).length;
}