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; }
// @ts-nocheck
/**
 * 资源视图（按月）：与日视图同款骨架——冻结左列 + 横向滚动 + sticky 顶部表头。
 *
 * 与日视图的唯一差异：
 *   - 日视图：横轴 = 营业小时槽，cell = 一个小时；booking 通过 overlay 跨 cell 横铺。
 *   - 资源视图：横轴 = 当月每一天，cell = 一个 (court, date)；booking 通过 overlay 在 cell 内
 *     垂直 stack 渲染（最多 3 条 + `+N` 溢出 tile）。
 *
 * 性能策略（与日视图对齐）：
 *   - cell 是「轻 placeholder」：只渲染背景色 + selected ring + 空 dashed slot/Selected 文本。
 *   - 所有 booking 卡片 / `+N` tile 由 `BookingOverlay` 单独 absolute 渲染，独立于 grid。
 *   - 这样 grid 内 DOM 极轻，浏览器每帧 paint/layout 与日视图同档（cell 内含复杂 booking
 *     卡片时实测每列 ~7ms paint 成本，整月 30 列 → ~150ms；overlay 化后接近零）。
 *
 * 选中：与日视图 `toggleSlot(courtId, hour)` 等价的「`toggleResourceCell(courtId, dateKey)`」。
 * 选中态合并到 cell 自身 className（与日视图一致），不插入额外 grid item，避免 CSS Grid 整表 reflow。
 */
import React, { useCallback, useLayoutEffect, useMemo, useRef, useState } from 'react';
import { courtDaySummary, fmtDate, formatHourLabel, getViewNowReference } from "../utils/bookingCalendarDateUtils";
import { CALENDAR_EMPTY_DASHED_SLOT_CLASSNAME, DAY_VIEW_COL_BUFFER, DAY_VIEW_ROW_BUFFER_PX, dayHeaderHeight, dayRowHeight, estimateResourceViewCourtCellHeightPx, frozenColWidth, groupRowHeight, RESOURCE_VIEW_BOOKING_CARD_EST_PX, RESOURCE_VIEW_MORE_TILE_MIN_PX } from "../const/bookingCalendarConstants";
import { getGridBookingRowStateClasses } from "../utils/BookingCalendarStyle";
import { getRemainingToneClass } from "../bookingCalendarViewShared";
import { BookingCalendarGroupRowHeader } from "./BookingCalendarGroupRowHeader";
import { tCal } from "../calendarI18n";
var PREVIEW_CAP = 3;
export var BookingCalendarResourceView = /*#__PURE__*/React.memo(BookingCalendarResourceViewInner);
function BookingCalendarResourceViewInner(_ref) {
  var calendarProps = _ref.calendarProps,
    isLight = _ref.isLight,
    anchorDate = _ref.anchorDate,
    monthDays = _ref.monthDays,
    slotColWidth = _ref.slotColWidth,
    bookings = _ref.bookings,
    visibleCourts = _ref.visibleCourts,
    visibleCourtRows = _ref.visibleCourtRows,
    hourSlots = _ref.hourSlots,
    slotStepHours = _ref.slotStepHours,
    handleGridDropMove = _ref.handleGridDropMove,
    openBookingDetail = _ref.openBookingDetail,
    setDraggingItem = _ref.setDraggingItem,
    setCollapsedGroups = _ref.setCollapsedGroups,
    overflowPopover = _ref.overflowPopover,
    setOverflowPopover = _ref.setOverflowPopover,
    setOverflowListModal = _ref.setOverflowListModal,
    overflowPanelRef = _ref.overflowPanelRef,
    resourceMonthScrollToTodayToken = _ref.resourceMonthScrollToTodayToken,
    resourceDayHeaderRemaining = _ref.resourceDayHeaderRemaining,
    toggleResourceCell = _ref.toggleResourceCell,
    selectedResourceCells = _ref.selectedResourceCells;
  var props = calendarProps;
  var todayKey = fmtDate(new Date());
  var monthKeyPrefix = "".concat(anchorDate.getFullYear(), "-").concat(anchorDate.getMonth());

  /* --------------------- bookings 内容签名稳定 --------------------- */
  var bookingsSignature = useMemo(function () {
    if (!Array.isArray(bookings) || bookings.length === 0) return '[]';
    return bookings.map(function (b) {
      var _b$id, _b$courtId, _b$date, _b$kind, _b$startHour, _b$endHour;
      return "".concat((_b$id = b === null || b === void 0 ? void 0 : b.id) !== null && _b$id !== void 0 ? _b$id : '', "|").concat((_b$courtId = b === null || b === void 0 ? void 0 : b.courtId) !== null && _b$courtId !== void 0 ? _b$courtId : '', "|").concat((_b$date = b === null || b === void 0 ? void 0 : b.date) !== null && _b$date !== void 0 ? _b$date : '', "|").concat((_b$kind = b === null || b === void 0 ? void 0 : b.kind) !== null && _b$kind !== void 0 ? _b$kind : '', "|").concat((_b$startHour = b === null || b === void 0 ? void 0 : b.startHour) !== null && _b$startHour !== void 0 ? _b$startHour : '', "|").concat((_b$endHour = b === null || b === void 0 ? void 0 : b.endHour) !== null && _b$endHour !== void 0 ? _b$endHour : '');
    }).join(';');
  }, [bookings]);
  // eslint-disable-next-line react-hooks/exhaustive-deps
  var bookingsStable = useMemo(function () {
    return bookings;
  }, [bookingsSignature]);

  /* --------------------- 横向 + 纵向虚拟（仅渲染可见列 / 行） --------------------- */
  var scrollRef = useRef(null);
  var dragRef = useRef({
    dragging: false,
    startX: 0,
    startY: 0,
    startLeft: 0,
    startTop: 0,
    moved: false
  });
  var _useState = useState(false),
    _useState2 = _slicedToArray(_useState, 2),
    dragging = _useState2[0],
    setDragging = _useState2[1];
  var _useState3 = useState({
      i0: 0,
      i1: 0,
      r0: 0,
      r1: 0,
      ready: false
    }),
    _useState4 = _slicedToArray(_useState3, 2),
    virt = _useState4[0],
    setVirt = _useState4[1];
  var rafRef = useRef(null);
  /** 行前缀和 ref（updateVirt 内通过 ref 读取最新值，避免每次行高变化都重建 callback） */
  var rowPrefixRef = useRef([0]);
  var nCols = monthDays.length;
  var updateVirt = useCallback(function () {
    var root = scrollRef.current;
    if (!root || nCols <= 0) return;
    var sl = root.scrollLeft;
    var st = root.scrollTop;
    var vw = root.clientWidth;
    var vh = root.clientHeight;

    // 列窗口
    var i0 = Math.floor((sl - frozenColWidth) / slotColWidth) - DAY_VIEW_COL_BUFFER;
    var i1 = Math.ceil((sl + vw - frozenColWidth) / slotColWidth) - 1 + DAY_VIEW_COL_BUFFER;
    i0 = Math.max(0, i0);
    i1 = Math.min(nCols - 1, i1);
    if (i0 > i1) {
      i0 = 0;
      i1 = nCols - 1;
    }

    // 行窗口（基于 rowPrefixTop 累积偏移；body 顶部对齐 sticky 表头之下）
    var pfx = rowPrefixRef.current;
    var nr = Math.max(0, pfx.length - 1);
    var r0 = 0;
    var r1 = nr > 0 ? nr - 1 : 0;
    if (nr > 0) {
      var bodyTop = dayHeaderHeight;
      var vTop = st;
      var vBot = st + vh;
      var buf = DAY_VIEW_ROW_BUFFER_PX;
      for (var r = 0; r < nr; r += 1) {
        var _pfx;
        var y1 = bodyTop + ((_pfx = pfx[r + 1]) !== null && _pfx !== void 0 ? _pfx : 0);
        if (y1 > vTop - buf) {
          r0 = r;
          break;
        }
      }
      for (var _r = nr - 1; _r >= 0; _r -= 1) {
        var _pfx$_r;
        var y0 = bodyTop + ((_pfx$_r = pfx[_r]) !== null && _pfx$_r !== void 0 ? _pfx$_r : 0);
        if (y0 < vBot + buf) {
          r1 = _r;
          break;
        }
      }
      if (r0 > r1) {
        r0 = 0;
        r1 = nr - 1;
      }
    }
    setVirt(function (prev) {
      return prev.ready && prev.i0 === i0 && prev.i1 === i1 && prev.r0 === r0 && prev.r1 === r1 ? prev : {
        i0: i0,
        i1: i1,
        r0: r0,
        r1: r1,
        ready: true
      };
    });
  }, [nCols, slotColWidth]);
  var scheduleVirt = useCallback(function () {
    if (rafRef.current != null) return;
    rafRef.current = requestAnimationFrame(function () {
      rafRef.current = null;
      updateVirt();
    });
  }, [updateVirt]);
  useLayoutEffect(function () {
    var root = scrollRef.current;
    if (!root) return undefined;
    scheduleVirt();
    var onScroll = function onScroll() {
      return scheduleVirt();
    };
    root.addEventListener('scroll', onScroll, {
      passive: true
    });
    var ro = null;
    if (typeof ResizeObserver !== 'undefined') {
      ro = new ResizeObserver(function () {
        return scheduleVirt();
      });
      try {
        ro.observe(root);
      } catch (_unused) {
        /* ignore */
      }
    }
    return function () {
      var _ro;
      root.removeEventListener('scroll', onScroll);
      (_ro = ro) === null || _ro === void 0 || _ro.disconnect();
      if (rafRef.current != null) cancelAnimationFrame(rafRef.current);
      rafRef.current = null;
    };
  }, [monthKeyPrefix, scheduleVirt, nCols]);

  /** 切入资源视图时把今天列居中（仅当月含今天） */
  useLayoutEffect(function () {
    if (!resourceMonthScrollToTodayToken) return;
    var root = scrollRef.current;
    if (!root || monthDays.length === 0) return;
    var idx = monthDays.findIndex(function (d) {
      return fmtDate(d) === getViewNowReference().dateKey;
    });
    if (idx < 0) return;
    var targetLeft = frozenColWidth + idx * slotColWidth - root.clientWidth / 2 + slotColWidth / 2;
    root.scrollLeft = Math.max(0, Math.min(targetLeft, root.scrollWidth - root.clientWidth));
  }, [resourceMonthScrollToTodayToken, monthKeyPrefix, monthDays, slotColWidth]);

  /* --------------------- 拖拽滚动 --------------------- */
  var onMouseDown = useCallback(function (e) {
    if (e.button !== 0 || !scrollRef.current) return;
    dragRef.current = {
      dragging: true,
      startX: e.clientX,
      startY: e.clientY,
      startLeft: scrollRef.current.scrollLeft,
      startTop: scrollRef.current.scrollTop,
      moved: false
    };
    setDragging(true);
  }, []);
  var onMouseMove = useCallback(function (e) {
    if (!dragRef.current.dragging || !scrollRef.current) return;
    var dx = e.clientX - dragRef.current.startX;
    var dy = e.clientY - dragRef.current.startY;
    if (Math.abs(dx) > 3 || Math.abs(dy) > 3) dragRef.current.moved = true;
    scrollRef.current.scrollLeft = dragRef.current.startLeft - dx;
    scrollRef.current.scrollTop = dragRef.current.startTop - dy;
  }, []);
  var onMouseUp = useCallback(function () {
    dragRef.current.dragging = false;
    setDragging(false);
  }, []);

  /* --------------------- 可见列下标 --------------------- */
  var visibleColIndices = useMemo(function () {
    if (!virt.ready) {
      var _out = [];
      for (var i = 0; i < nCols; i += 1) _out.push(i);
      return _out;
    }
    var out = [];
    for (var _i = virt.i0; _i <= virt.i1; _i += 1) out.push(_i);
    return out;
  }, [virt, nCols]);

  /* --------------------- 单元格摘要缓存（仅可视窗口） --------------------- */
  var summaryCache = useMemo(function () {
    var m = new Map();
    var visibleCourtIds = [];
    var _iterator = _createForOfIteratorHelper(visibleCourtRows),
      _step;
    try {
      for (_iterator.s(); !(_step = _iterator.n()).done;) {
        var r = _step.value;
        if ((r === null || r === void 0 ? void 0 : r.kind) === 'court' && r.id) visibleCourtIds.push(String(r.id));
      }
    } catch (err) {
      _iterator.e(err);
    } finally {
      _iterator.f();
    }
    var visibleDateKeys = visibleColIndices.map(function (ci) {
      return monthDays[ci];
    }).filter(Boolean).map(function (d) {
      return fmtDate(d);
    });
    for (var _i2 = 0, _visibleCourtIds = visibleCourtIds; _i2 < _visibleCourtIds.length; _i2++) {
      var cid = _visibleCourtIds[_i2];
      var _iterator2 = _createForOfIteratorHelper(visibleDateKeys),
        _step2;
      try {
        for (_iterator2.s(); !(_step2 = _iterator2.n()).done;) {
          var dk = _step2.value;
          m.set("".concat(cid, "\t").concat(dk), courtDaySummary(cid, dk, bookingsStable, hourSlots, slotStepHours));
        }
      } catch (err) {
        _iterator2.e(err);
      } finally {
        _iterator2.f();
      }
    }
    return m;
  }, [visibleCourtRows, visibleColIndices, monthDays, bookingsStable, hourSlots, slotStepHours]);
  var getSummary = useCallback(function (courtId, dateKey) {
    var _summaryCache$get;
    return (_summaryCache$get = summaryCache.get("".concat(courtId, "\t").concat(dateKey))) !== null && _summaryCache$get !== void 0 ? _summaryCache$get : courtDaySummary(courtId, dateKey, bookingsStable, hourSlots, slotStepHours);
  }, [summaryCache, bookingsStable, hourSlots, slotStepHours]);

  /* --------------------- 行高（按全月最大内容估算） --------------------- */
  var rowHeights = useMemo(function () {
    return visibleCourtRows.map(function (row) {
      if (row.kind === 'group') return groupRowHeight;
      var maxH = dayRowHeight;
      for (var di = 0; di < monthDays.length; di += 1) {
        var day = monthDays[di];
        if (!day) continue;
        var summary = getSummary(row.id, fmtDate(day));
        maxH = Math.max(maxH, estimateResourceViewCourtCellHeightPx(summary));
      }
      return maxH;
    });
  }, [visibleCourtRows, monthDays, getSummary]);
  var gridTemplateRows = useMemo(function () {
    return visibleCourtRows.map(function (row, i) {
      return row.kind === 'group' ? "".concat(groupRowHeight, "px") : "".concat(rowHeights[i], "px");
    }).join(' ');
  }, [visibleCourtRows, rowHeights]);

  /** 行前缀和：rowPrefixTop[i] = 前 i 行总高度（i 从 0 到 N） */
  var rowPrefixTop = useMemo(function () {
    var arr = new Array(rowHeights.length + 1);
    arr[0] = 0;
    for (var i = 0; i < rowHeights.length; i += 1) {
      var _rowHeights$i;
      arr[i + 1] = arr[i] + ((_rowHeights$i = rowHeights[i]) !== null && _rowHeights$i !== void 0 ? _rowHeights$i : 0);
    }
    return arr;
  }, [rowHeights]);

  /** 同步到 ref，让 updateVirt 拿到最新前缀和；行高变化后立刻触发一次行窗口重算 */
  useLayoutEffect(function () {
    rowPrefixRef.current = rowPrefixTop;
    scheduleVirt();
  }, [rowPrefixTop, scheduleVirt]);
  var contentHeight = dayHeaderHeight + rowPrefixTop[rowPrefixTop.length - 1];

  /**
   * 按 court 切分的「选中日期签名」：传给 ResourceCourtRow 触发 React.memo 浅比较。
   * - 同一 court 的选中集没变 → sig 字符串相等 → memo 命中 → 整行跳过 reconcile。
   * - 这样点击 / 取消 cell 时，只有「新选中 / 旧选中」对应的 1~2 行真正重渲染，其他全部 N 行被 memo 跳过。
   */
  var selectionSigByCourtId = useMemo(function () {
    var grp = new Map();
    var _iterator3 = _createForOfIteratorHelper(selectedResourceCells),
      _step3;
    try {
      for (_iterator3.s(); !(_step3 = _iterator3.n()).done;) {
        var s = _step3.value;
        var cid = String(s.courtId);
        var arr = grp.get(cid);
        if (!arr) {
          arr = [];
          grp.set(cid, arr);
        }
        arr.push(s.dateKey);
      }
    } catch (err) {
      _iterator3.e(err);
    } finally {
      _iterator3.f();
    }
    var m = new Map();
    grp.forEach(function (arr, cid) {
      arr.sort();
      m.set(cid, arr.join('|'));
    });
    return m;
  }, [selectedResourceCells]);

  /* --------------------- render --------------------- */
  var monthLabel = "".concat(anchorDate.getFullYear(), " / ").concat(anchorDate.getMonth() + 1);
  return /*#__PURE__*/React.createElement("div", {
    key: "resource-".concat(monthKeyPrefix),
    className: "flex min-h-0 flex-1 flex-col"
  }, /*#__PURE__*/React.createElement("div", {
    className: "relative flex min-h-0 flex-1 flex-col"
  }, /*#__PURE__*/React.createElement("div", {
    ref: scrollRef,
    onMouseDown: onMouseDown,
    onMouseMove: onMouseMove,
    onMouseUp: onMouseUp,
    onMouseLeave: onMouseUp,
    style: {
      overscrollBehavior: 'none'
    },
    className: "pisell-scroll-hidden relative border min-h-0 max-h-none flex-1 overflow-auto touch-pan-x touch-pan-y select-none ".concat(isLight ? 'theme-panel theme-border' : 'border-zinc-800 bg-[#121217]', " ").concat(dragging ? 'cursor-grabbing' : 'cursor-grab')
  }, /*#__PURE__*/React.createElement("div", {
    className: "relative",
    style: {
      minWidth: "".concat(frozenColWidth + nCols * slotColWidth, "px"),
      minHeight: "".concat(contentHeight, "px")
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "grid sticky top-0 z-50",
    style: {
      gridTemplateColumns: "".concat(frozenColWidth, "px repeat(").concat(nCols, ", ").concat(slotColWidth, "px)")
    }
  }, /*#__PURE__*/React.createElement("div", {
    className: "sticky left-0 top-0 z-[60] flex h-full min-h-0 w-[132px] min-w-[132px] max-w-[132px] flex-col justify-center px-2.5 font-semibold border-b shadow-[8px_0_16px_rgba(0,0,0,0.08)] ".concat(isLight ? 'surface-brand-side text-slate-900' : 'bg-[#241d40] border-zinc-800 text-zinc-100')
  }, /*#__PURE__*/React.createElement("span", {
    className: "text-lg font-bold leading-tight"
  }, monthLabel)), visibleColIndices.map(function (ci) {
    var day = monthDays[ci];
    if (!day) return null;
    var key = fmtDate(day);
    var isToday = key === todayKey;
    var remaining = resourceDayHeaderRemaining[key];
    return /*#__PURE__*/React.createElement("div", {
      key: "rh-".concat(key),
      className: "relative z-20 border-b border-l px-1 py-2 text-center shadow-[0_8px_16px_rgba(0,0,0,0.06)] ".concat(isLight ? 'theme-border theme-text' : 'border-zinc-800', " ").concat(isToday ? isLight ? 'bg-gradient-to-b from-violet-50 to-white' : 'bg-gradient-to-b from-violet-950 to-[#1a1a22]' : isLight ? 'theme-panel-soft' : 'bg-[#1a1a22]'),
      style: {
        gridColumn: ci + 2
      }
    }, /*#__PURE__*/React.createElement("div", {
      className: "flex justify-center"
    }, /*#__PURE__*/React.createElement("span", {
      className: "grid h-10 w-10 place-items-center text-3xl font-semibold leading-none",
      "aria-label": isToday ? 'Today' : undefined
    }, day.getDate())), remaining && remaining.total > 0 && /*#__PURE__*/React.createElement("div", {
      className: "mt-1 text-[11px] font-semibold leading-tight ".concat(getRemainingToneClass(remaining.ratio, isLight))
    }, tCal('pisell2.recordBoard.calendar.day.freeRatio', {
      remaining: remaining.remaining,
      total: remaining.total
    })));
  })), /*#__PURE__*/React.createElement("div", {
    className: "grid relative",
    style: {
      gridTemplateColumns: "".concat(frozenColWidth, "px repeat(").concat(nCols, ", ").concat(slotColWidth, "px)"),
      gridTemplateRows: gridTemplateRows
    }
  }, visibleCourtRows.map(function (row, rowIndex) {
    var _selectionSigByCourtI;
    // 纵向虚拟：窗口外行渲染单个跨整列占位 div，仅保留 grid 行高，跳过 cell + 左侧 sticky 内容
    if (virt.ready && (rowIndex < virt.r0 || rowIndex > virt.r1)) {
      return /*#__PURE__*/React.createElement("div", {
        key: "".concat(row.id, "-skip"),
        className: "pointer-events-none border-b ".concat(isLight ? 'theme-border' : 'border-zinc-800'),
        style: {
          gridColumn: '1 / -1',
          gridRow: rowIndex + 1
        },
        "aria-hidden": true
      });
    }
    return row.kind === 'group' ? /*#__PURE__*/React.createElement(React.Fragment, {
      key: row.id
    }, /*#__PURE__*/React.createElement(BookingCalendarGroupRowHeader, {
      isLight: isLight,
      view: "resource",
      row: {
        id: row.id,
        label: row.label,
        count: row.count,
        collapsed: row.collapsed
      },
      renderResourceCell: props.renderResourceCell,
      setCollapsedGroups: setCollapsedGroups,
      style: {
        gridRow: rowIndex + 1,
        gridColumn: 1
      }
    }), visibleColIndices.map(function (ci) {
      var day = monthDays[ci];
      if (!day) return null;
      var key = fmtDate(day);
      var groupCourts = visibleCourts.filter(function (c) {
        return c.type === row.label;
      });
      var total = groupCourts.length;
      var noRatioCell = total === 0;
      var remaining = 0;
      var ratio = 0;
      if (!noRatioCell) {
        var busy = groupCourts.filter(function (c) {
          return getSummary(c.id, key).items.length > 0;
        }).length;
        remaining = total - busy;
        ratio = remaining / total;
      }
      return /*#__PURE__*/React.createElement("div", {
        key: "".concat(row.id, "-").concat(key),
        style: {
          gridRow: rowIndex + 1,
          gridColumn: ci + 2
        },
        className: "flex h-full items-center justify-center border-b border-l px-1.5 py-1 text-center text-sm font-medium ".concat(isLight ? 'theme-border' : 'border-zinc-800', " ").concat(noRatioCell ? isLight ? 'bg-slate-100 theme-text-faint' : 'bg-zinc-800/80 text-zinc-500' : isLight ? 'theme-panel-soft' : 'bg-[#151a2f] text-zinc-300')
      }, noRatioCell ? /*#__PURE__*/React.createElement("div", {
        className: "text-xs opacity-60"
      }, "\u2014") : /*#__PURE__*/React.createElement("div", {
        className: "text-xs font-semibold leading-none ".concat(getRemainingToneClass(ratio, isLight))
      }, tCal('pisell2.recordBoard.calendar.day.freeRatio', {
        remaining: remaining,
        total: total
      })));
    })) : /*#__PURE__*/React.createElement(ResourceCourtRow, {
      key: row.id,
      courtId: String(row.id),
      courtName: row.name,
      courtType: row.type,
      rowIndex: rowIndex,
      visibleColIndices: visibleColIndices,
      monthDays: monthDays,
      getSummary: getSummary,
      toggleResourceCell: toggleResourceCell,
      isLight: isLight,
      renderResourceCell: props.renderResourceCell,
      handleGridDropMove: handleGridDropMove,
      selectedSig: (_selectionSigByCourtI = selectionSigByCourtId.get(String(row.id))) !== null && _selectionSigByCourtI !== void 0 ? _selectionSigByCourtI : ''
    });
  }), /*#__PURE__*/React.createElement(BookingOverlay, {
    visibleCourtRows: visibleCourtRows,
    visibleColIndices: visibleColIndices,
    monthDays: monthDays,
    rowPrefixTop: rowPrefixTop,
    rowHeights: rowHeights,
    slotColWidth: slotColWidth,
    virt: virt,
    getSummary: getSummary,
    isLight: isLight,
    renderMonthWeekBooking: props.renderMonthWeekBooking,
    openBookingDetail: openBookingDetail,
    setDraggingItem: setDraggingItem,
    handleGridDropMove: handleGridDropMove,
    overflowPopover: overflowPopover,
    setOverflowPopover: setOverflowPopover,
    setOverflowListModal: setOverflowListModal,
    overflowPanelRef: overflowPanelRef
  }))))));
}

/* --------------------- 单条资源行（court 行）---------------------
 * `React.memo` 浅比较：除 `selectedSig` 外，其他 props 在「点击 cell 不滚动」场景下父组件保持引用稳定
 *   - courtId/courtName/courtType/rowIndex：标量
 *   - visibleColIndices/monthDays：父组件 useMemo 缓存，依赖未变则引用稳定
 *   - getSummary/toggleResourceCell/handleGridDropMove/openBookingDetail：useCallback / setState 引用稳定
 *   - overflowPopover/setOverflowPopover/setOverflowListModal/setDraggingItem/overflowPanelRef：state 或 useRef，点击 cell 时不变
 *   - renderResourceCell/renderMonthWeekBooking：宿主透传，期望稳定
 *   - selectedSig：仅相关 court 的字符串签名变化 → 仅 1~2 行真正重渲染
 */
var ResourceCourtRow = /*#__PURE__*/React.memo(function ResourceCourtRow(_ref2) {
  var courtId = _ref2.courtId,
    courtName = _ref2.courtName,
    courtType = _ref2.courtType,
    rowIndex = _ref2.rowIndex,
    visibleColIndices = _ref2.visibleColIndices,
    monthDays = _ref2.monthDays,
    getSummary = _ref2.getSummary,
    toggleResourceCell = _ref2.toggleResourceCell,
    isLight = _ref2.isLight,
    renderResourceCell = _ref2.renderResourceCell,
    handleGridDropMove = _ref2.handleGridDropMove,
    selectedSig = _ref2.selectedSig;
  /** 由签名字符串还原 Set，仅 selectedSig 变化时才重建 */
  var selectedDateKeys = useMemo(function () {
    return selectedSig ? new Set(selectedSig.split('|')) : null;
  }, [selectedSig]);
  return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", {
    className: "sticky left-0 z-30 flex h-full min-h-0 w-[132px] min-w-[132px] max-w-[132px] flex-col justify-center border-b px-2.5 py-1.5 shadow-[8px_0_16px_rgba(0,0,0,0.06)] ".concat(isLight ? 'surface-brand-side-muted' : 'border-zinc-800 bg-[#1a1a22]'),
    style: {
      gridRow: rowIndex + 1,
      gridColumn: 1
    }
  }, renderResourceCell ? renderResourceCell({
    view: 'resource',
    row: {
      kind: 'court',
      id: courtId,
      name: courtName,
      type: courtType
    },
    isLight: isLight
  }) : /*#__PURE__*/React.createElement("div", {
    className: "pisell-rb-cal-week-resource-name min-w-0 w-full font-semibold text-[16px] leading-tight"
  }, courtName)), visibleColIndices.map(function (ci) {
    var _selectedDateKeys$has;
    var day = monthDays[ci];
    if (!day) return null;
    var key = fmtDate(day);
    var summary = getSummary(courtId, key);
    return /*#__PURE__*/React.createElement(ResourceCourtCell, {
      key: "".concat(courtId, "-").concat(key),
      courtId: courtId,
      dateKey: key,
      rowIndex: rowIndex,
      colIndex: ci,
      summary: summary,
      selected: (_selectedDateKeys$has = selectedDateKeys === null || selectedDateKeys === void 0 ? void 0 : selectedDateKeys.has(key)) !== null && _selectedDateKeys$has !== void 0 ? _selectedDateKeys$has : false,
      isLight: isLight,
      toggleResourceCell: toggleResourceCell,
      handleGridDropMove: handleGridDropMove
    });
  }));
});

/* --------------------- 单个资源 cell（极简版）---------------------
 * 与日视图对齐：cell 只是「轻 placeholder」——背景色、selected ring、空时的 dashed slot。
 * 所有 booking 卡片 / `+N` 溢出 tile 都不在 cell 内渲染，由 `BookingOverlay` 统一 absolute 渲染。
 *
 * 这样：
 *   - grid 内 DOM 只有 cell 占位（极轻），浏览器每帧 paint/layout 接近日视图。
 *   - selected 切换只改 cell 自身 className，overlay 完全不重渲染。
 *   - +N popover / 拖拽 / 详情打开等富交互全部委托给 overlay 卡片。
 */
var ResourceCourtCell = /*#__PURE__*/React.memo(function ResourceCourtCell(_ref3) {
  var courtId = _ref3.courtId,
    dateKey = _ref3.dateKey,
    rowIndex = _ref3.rowIndex,
    colIndex = _ref3.colIndex,
    summary = _ref3.summary,
    selected = _ref3.selected,
    isLight = _ref3.isLight,
    toggleResourceCell = _ref3.toggleResourceCell,
    handleGridDropMove = _ref3.handleGridDropMove;
  return /*#__PURE__*/React.createElement("button", {
    type: "button",
    onClick: function onClick() {
      return toggleResourceCell(courtId, dateKey);
    },
    onDragOver: function onDragOver(e) {
      return e.preventDefault();
    },
    onDrop: function onDrop(e) {
      e.preventDefault();
      handleGridDropMove(dateKey, courtId);
    },
    style: {
      gridRow: rowIndex + 1,
      gridColumn: colIndex + 2,
      contain: 'layout paint style'
    },
    className: "relative flex w-full min-h-0 flex-col justify-start border-b border-l p-1 text-left align-top outline-none ".concat(isLight ? 'theme-border' : 'border-zinc-700', " ").concat(summary.fullyBooked ? isLight ? 'bg-slate-100 theme-text-faint' : 'bg-zinc-800 text-zinc-500' : summary.hasBlock ? isLight ? 'bg-red-50 border-red-200' : 'bg-red-950/30 border-red-800/40' : summary.occupiedHours.length > 0 ? isLight ? 'bg-violet-50' : 'bg-[#1c1630]' : isLight ? 'theme-grid-cell' : 'bg-zinc-900', " ").concat(selected ? isLight ? 'ring-1 ring-inset ring-violet-400/75 bg-violet-400/10' : 'ring-1 ring-inset ring-violet-400/70 bg-white/10' : '')
  }, summary.items.length === 0 ? /*#__PURE__*/React.createElement("div", {
    className: "".concat(CALENDAR_EMPTY_DASHED_SLOT_CLASSNAME, " text-center ").concat(isLight ? 'border-[#d8d0eb] text-[#8f86a9]' : 'border-zinc-700 text-zinc-500')
  }, selected ? tCal('pisell2.recordBoard.calendar.day.selected') : null) : null);
});

/* --------------------- Booking Overlay 层（与日视图同款） ---------------------
 * 所有 booking 卡片 / `+N` tile 都在这一层 absolute 渲染，独立于 grid。
 * cell 切换 selected 时此层完全不重渲染（依赖项不变 → React.memo HIT）。
 *
 * 位置计算（grid body 内的 px 坐标）：
 *   cell.top    = rowPrefixTop[rowIndex]
 *   cell.left   = frozenColWidth + colIndex * slotColWidth
 *   cell.height = rowHeights[rowIndex]
 *   cell.width  = slotColWidth
 *
 * cell 内布局（与原方案视觉对齐）：cell padding p-1 = 4px, 卡片间 gap-1 = 4px。
 *   item[idx].top = cell.top + 4 + idx * (CARD_H + 4)
 *   item.left     = cell.left + 4
 *   item.width    = cell.width - 8
 *   item.height   = CARD_H
 */
var OVERLAY_CELL_PAD = 4;
var OVERLAY_ITEM_GAP = 4;
var BookingOverlay = /*#__PURE__*/React.memo(function BookingOverlay(_ref4) {
  var _rowPrefixTop;
  var visibleCourtRows = _ref4.visibleCourtRows,
    visibleColIndices = _ref4.visibleColIndices,
    monthDays = _ref4.monthDays,
    rowPrefixTop = _ref4.rowPrefixTop,
    rowHeights = _ref4.rowHeights,
    slotColWidth = _ref4.slotColWidth,
    virt = _ref4.virt,
    getSummary = _ref4.getSummary,
    isLight = _ref4.isLight,
    renderMonthWeekBooking = _ref4.renderMonthWeekBooking,
    openBookingDetail = _ref4.openBookingDetail,
    setDraggingItem = _ref4.setDraggingItem,
    handleGridDropMove = _ref4.handleGridDropMove,
    overflowPopover = _ref4.overflowPopover,
    setOverflowPopover = _ref4.setOverflowPopover,
    setOverflowListModal = _ref4.setOverflowListModal,
    overflowPanelRef = _ref4.overflowPanelRef;
  /** 一次遍历可见区域，计算出所有 overlay item 的 px 位置 */
  var items = useMemo(function () {
    var out = [];
    for (var rowIdx = 0; rowIdx < visibleCourtRows.length; rowIdx += 1) {
      var _rowPrefixTop$rowIdx;
      if (virt.ready && (rowIdx < virt.r0 || rowIdx > virt.r1)) continue;
      var row = visibleCourtRows[rowIdx];
      if ((row === null || row === void 0 ? void 0 : row.kind) !== 'court' || !row.id) continue;
      var _courtId = String(row.id);
      var cellTop = (_rowPrefixTop$rowIdx = rowPrefixTop[rowIdx]) !== null && _rowPrefixTop$rowIdx !== void 0 ? _rowPrefixTop$rowIdx : 0;
      var _iterator4 = _createForOfIteratorHelper(visibleColIndices),
        _step4;
      try {
        for (_iterator4.s(); !(_step4 = _iterator4.n()).done;) {
          var colIdx = _step4.value;
          var day = monthDays[colIdx];
          if (!day) continue;
          var _dateKey = fmtDate(day);
          var summary = getSummary(_courtId, _dateKey);
          if (summary.items.length === 0) continue;
          var cellLeft = colIdx * slotColWidth + frozenColWidth;
          var previewItems = summary.items.slice(0, PREVIEW_CAP);
          var moreItems = summary.items.slice(PREVIEW_CAP);
          var moreCount = moreItems.length;
          var showMore = moreCount > 0 && previewItems.length > 0;
          var itemLeft = cellLeft + OVERLAY_CELL_PAD;
          var itemWidth = slotColWidth - OVERLAY_CELL_PAD * 2;
          for (var i = 0; i < previewItems.length; i += 1) {
            var _previewItems$i$id;
            var top = cellTop + OVERLAY_CELL_PAD + i * (RESOURCE_VIEW_BOOKING_CARD_EST_PX + OVERLAY_ITEM_GAP);
            out.push({
              kind: 'booking',
              key: "".concat(_courtId, "\t").concat(_dateKey, "\t").concat((_previewItems$i$id = previewItems[i].id) !== null && _previewItems$i$id !== void 0 ? _previewItems$i$id : i),
              item: previewItems[i],
              courtId: _courtId,
              dateKey: _dateKey,
              top: top,
              left: itemLeft,
              width: itemWidth,
              height: RESOURCE_VIEW_BOOKING_CARD_EST_PX
            });
          }
          if (showMore) {
            var _top = cellTop + OVERLAY_CELL_PAD + previewItems.length * (RESOURCE_VIEW_BOOKING_CARD_EST_PX + OVERLAY_ITEM_GAP);
            out.push({
              kind: 'more',
              key: "".concat(_courtId, "\t").concat(_dateKey, "\tmore"),
              courtId: _courtId,
              dateKey: _dateKey,
              top: _top,
              left: itemLeft,
              width: itemWidth,
              moreItems: moreItems,
              moreCount: moreCount,
              allItems: summary.items
            });
          }
        }
      } catch (err) {
        _iterator4.e(err);
      } finally {
        _iterator4.f();
      }
    }
    return out;
  }, [visibleCourtRows, visibleColIndices, monthDays, rowPrefixTop, slotColWidth, virt, getSummary]);
  var overlayHeight = (_rowPrefixTop = rowPrefixTop[rowPrefixTop.length - 1]) !== null && _rowPrefixTop !== void 0 ? _rowPrefixTop : rowHeights.reduce(function (a, b) {
    return a + b;
  }, 0);
  return /*#__PURE__*/React.createElement("div", {
    "aria-hidden": true,
    style: {
      position: 'absolute',
      top: 0,
      left: 0,
      width: '100%',
      height: overlayHeight,
      pointerEvents: 'none',
      zIndex: 5
    }
  }, items.map(function (it) {
    if (it.kind === 'booking') {
      var layoutClassName = "flex flex-col justify-center rounded-lg px-2.5 py-1.5 text-xs text-left w-full h-full ".concat(getGridBookingRowStateClasses(it.item));
      return /*#__PURE__*/React.createElement("div", {
        key: it.key,
        style: {
          position: 'absolute',
          top: it.top,
          left: it.left,
          width: it.width,
          height: it.height,
          pointerEvents: 'auto'
        },
        onDragOver: function onDragOver(e) {
          return e.preventDefault();
        },
        onDrop: function onDrop(e) {
          e.preventDefault();
          handleGridDropMove(it.dateKey, it.courtId);
        }
      }, renderMonthWeekBooking ? renderMonthWeekBooking({
        item: it.item,
        dateKey: it.dateKey,
        view: 'resource',
        isLight: isLight,
        layoutClassName: layoutClassName,
        onOpenDetail: openBookingDetail,
        onDragStart: function onDragStart(i) {
          return setDraggingItem(i);
        },
        draggable: false
      }) : /*#__PURE__*/React.createElement("button", {
        type: "button",
        onClick: function onClick(e) {
          e.stopPropagation();
          openBookingDetail(it.item);
        },
        className: layoutClassName
      }, /*#__PURE__*/React.createElement("div", {
        className: "truncate"
      }, it.item.name), /*#__PURE__*/React.createElement("div", {
        className: "mt-1 opacity-80 truncate"
      }, formatHourLabel(it.item.startHour), " -", ' ', formatHourLabel(it.item.endHour))));
    }
    var isThisPopover = (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.courtId) === it.courtId && (overflowPopover === null || overflowPopover === void 0 ? void 0 : overflowPopover.date) === it.dateKey;
    return /*#__PURE__*/React.createElement("div", {
      key: it.key,
      ref: isThisPopover ? overflowPanelRef : null,
      style: {
        position: 'absolute',
        top: it.top,
        left: it.left,
        width: it.width,
        minHeight: RESOURCE_VIEW_MORE_TILE_MIN_PX,
        pointerEvents: 'auto'
      }
    }, /*#__PURE__*/React.createElement("button", {
      type: "button",
      onMouseEnter: function onMouseEnter(e) {
        e.stopPropagation();
        setOverflowPopover({
          courtId: it.courtId,
          date: it.dateKey,
          items: it.moreItems,
          pinned: false
        });
      },
      onClick: function onClick(e) {
        e.stopPropagation();
        setOverflowPopover(null);
        setOverflowListModal(function (prev) {
          return prev && prev.scope === it.courtId && prev.date === it.dateKey ? null : {
            scope: it.courtId,
            date: it.dateKey,
            title: tCal('pisell2.recordBoard.calendar.overflow.listTitleAllBookings', {
              date: it.dateKey
            }),
            items: it.allItems.filter(function (x) {
              return x.kind === 'booking';
            })
          };
        });
      },
      style: {
        minHeight: RESOURCE_VIEW_MORE_TILE_MIN_PX
      },
      className: "flex w-full items-center justify-center rounded-xl bg-violet-700/90 px-2.5 py-1 text-xs font-semibold text-white"
    }, "+", it.moreCount));
  }));
});