var __create = Object.create;
var __defProp = Object.defineProperty;
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
var __getOwnPropNames = Object.getOwnPropertyNames;
var __getProtoOf = Object.getPrototypeOf;
var __hasOwnProp = Object.prototype.hasOwnProperty;
var __export = (target, all) => {
  for (var name in all)
    __defProp(target, name, { get: all[name], enumerable: true });
};
var __copyProps = (to, from, except, desc) => {
  if (from && typeof from === "object" || typeof from === "function") {
    for (let key of __getOwnPropNames(from))
      if (!__hasOwnProp.call(to, key) && key !== except)
        __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
  }
  return to;
};
var __toESM = (mod, isNodeMode, target) => (target = mod != null ? __create(__getProtoOf(mod)) : {}, __copyProps(
  // If the importer is in node compatibility mode or this is not an ESM
  // file that has been converted to a CommonJS file using a Babel-
  // compatible transform (i.e. "__esModule" has not been set), then set
  // "default" to the CommonJS "module.exports" for node compatibility.
  isNodeMode || !mod || !mod.__esModule ? __defProp(target, "default", { value: mod, enumerable: true }) : target,
  mod
));
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);

// src/components/pisellRecordBoard/shellFrame/Calendar/BookingCalendar.tsx
var BookingCalendar_exports = {};
__export(BookingCalendar_exports, {
  default: () => BookingCalendar
});
module.exports = __toCommonJS(BookingCalendar_exports);
var import_react = __toESM(require("react"));
var import_antd = require("antd");
var import_utils = require("../../../pisellTimeNavigator/utils");
var import_calendarPersistGuard = require("./calendarPersistGuard");
var import_bookingCalendarConstants = require("./const/bookingCalendarConstants");
var import_bookingCalendarDateUtils = require("./utils/bookingCalendarDateUtils");
var import_MoveConfirmModal = require("./modal/MoveConfirmModal");
var import_BookingCalendarBlockPanel = require("./modal/BookingCalendarBlockPanel");
var import_BookingCalendarOverflowListLayer = require("./modal/BookingCalendarOverflowListLayer");
var import_bookingCalendarViewShared = require("./bookingCalendarViewShared");
var import_calendarI18n = require("./calendarI18n");
var import_BookingCalendarMonthView = require("./view/BookingCalendarMonthView");
var import_BookingCalendarWeekView = require("./view/BookingCalendarWeekView");
var import_BookingCalendarDayView = require("./view/BookingCalendarDayView");
var import_BookingCalendarResourceView = require("./view/BookingCalendarResourceView");
var import_BookingCalendarDaySelectionBar = require("./view/BookingCalendarDaySelectionBar");
var import_bookingCalendarSelectionUtils = require("./utils/bookingCalendarSelectionUtils");
var import_useBookingCalendarDayOverlayLayout = require("./hooks/useBookingCalendarDayOverlayLayout");
var import_useBookingCalendarDayHourRemaining = require("./view/day/useBookingCalendarDayHourRemaining");
var import_useBookingCalendarDaySelection = require("./view/day/useBookingCalendarDaySelection");
var import_useBookingCalendarResourceDayHeaderRemaining = require("./view/resource/useBookingCalendarResourceDayHeaderRemaining");
var import_useBookingCalendarResourceCellToggle = require("./view/resource/useBookingCalendarResourceCellToggle");
var import_useBookingCalendarGoToDayFromCell = require("./view/useBookingCalendarGoToDayFromCell");
var import_BookingCalendar = require("./BookingCalendar.less");
function BookingCalendar(props = {}) {
  const allowPersist = (0, import_calendarPersistGuard.useCalendarPersist)();
  const courts = (0, import_react.useMemo)(() => {
    const r = props.resources;
    if (Array.isArray(r) && r.length > 0) {
      const mapped = r.filter(
        (x) => x && x.id !== void 0 && x.id !== null && String(x.id).trim() !== ""
      ).map((x) => ({
        id: String(x.id),
        name: x.name != null && String(x.name).trim() !== "" ? String(x.name) : String(x.id),
        type: x.groupType && String(x.groupType).trim() !== "" ? String(x.groupType) : (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.common.resourceFallback")
      }));
      if (mapped.length > 0) return mapped;
    }
    return [];
  }, [props.resources]);
  const isLight = props.appearance === "light";
  const [internalView, setInternalView] = (0, import_react.useState)("month");
  const [internalAnchor, setInternalAnchor] = (0, import_react.useState)(() => /* @__PURE__ */ new Date());
  const view = props.calendarView != null ? props.calendarView : internalView;
  const linkedAnchorMs = props.anchorDate != null ? props.anchorDate.getTime() : null;
  const anchorDate = (0, import_react.useMemo)(() => {
    if (props.anchorDate != null) {
      return new Date(props.anchorDate);
    }
    return internalAnchor;
  }, [linkedAnchorMs, internalAnchor]);
  const resolvedSlotMinutes = (0, import_react.useMemo)(() => {
    const raw = props.slotStepMinutes ?? 60;
    const n = Math.round(Number(raw));
    if (!Number.isFinite(n) || n < 1) return 60;
    return Math.min(24 * 60, n);
  }, [props.slotStepMinutes]);
  const slotStepHours = resolvedSlotMinutes / 60;
  const slotColWidth = import_bookingCalendarConstants.dayColWidth;
  const resourceViewSlotColWidth = import_bookingCalendarConstants.resourceViewDayColWidth;
  const timelinePxPerHour = import_bookingCalendarConstants.dayColWidth / slotStepHours;
  const commitView = (v) => {
    var _a;
    (_a = props.onCalendarViewChange) == null ? void 0 : _a.call(props, v);
    if (!props.onCalendarViewChange) {
      setInternalView(v);
    }
  };
  const commitAnchor = (d) => {
    var _a;
    (_a = props.onAnchorDateChange) == null ? void 0 : _a.call(props, d);
    if (!props.onAnchorDateChange) {
      setInternalAnchor(d);
    }
  };
  const [internalBookings, setBookings] = (0, import_react.useState)([]);
  const isControlledBookings = props.bookings != null;
  const bookings = isControlledBookings ? props.bookings : internalBookings;
  (0, import_react.useEffect)(() => {
    if (!props.onViewportChange) return;
    const a = new Date(anchorDate);
    let rangeStart;
    let rangeEnd;
    if (view === "month") {
      rangeStart = new Date(a.getFullYear(), a.getMonth(), 1);
      rangeEnd = new Date(a.getFullYear(), a.getMonth() + 1, 0);
    } else if (view === "resource") {
      rangeStart = new Date(a.getFullYear(), a.getMonth(), 1);
      rangeEnd = new Date(a.getFullYear(), a.getMonth() + 1, 0);
    } else if (view === "week") {
      rangeStart = (0, import_bookingCalendarDateUtils.startOfWeek)(a);
      rangeEnd = (0, import_bookingCalendarDateUtils.addDays)(rangeStart, 6);
    } else {
      rangeStart = new Date(a);
      rangeEnd = new Date(a);
    }
    props.onViewportChange({
      view,
      anchorDate: a,
      rangeStart,
      rangeEnd
    });
  }, [view, anchorDate, props.onViewportChange]);
  const [selectedFreeSlots, setSelectedFreeSlots] = (0, import_react.useState)([]);
  const [selectedBlockSlots, setSelectedBlockSlots] = (0, import_react.useState)([]);
  const [selectedResourceCells, setSelectedResourceCells] = (0, import_react.useState)([]);
  const [focusedCourtId, setFocusedCourtId] = (0, import_react.useState)(null);
  const [showBlockPanel, setShowBlockPanel] = (0, import_react.useState)(false);
  const [blockFormName, setBlockFormName] = (0, import_react.useState)(
    () => (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.defaultTitle")
  );
  const [blockModalNote, setBlockModalNote] = (0, import_react.useState)("");
  const [blockResourceId, setBlockResourceId] = (0, import_react.useState)("");
  const [blockTimeRange, setBlockTimeRange] = (0, import_react.useState)(null);
  const [blockSaving, setBlockSaving] = (0, import_react.useState)(false);
  const [transitioningToDay, setTransitioningToDay] = (0, import_react.useState)(null);
  const [navDirection, setNavDirection] = (0, import_react.useState)(0);
  const [overflowPopover, setOverflowPopover] = (0, import_react.useState)(null);
  const [overflowListModal, setOverflowListModal] = (0, import_react.useState)(null);
  const [draggingItem, setDraggingItem] = (0, import_react.useState)(null);
  const [moveConfirm, setMoveConfirm] = (0, import_react.useState)(null);
  const [moveDraft, setMoveDraft] = (0, import_react.useState)(null);
  const [collapsedGroups, setCollapsedGroups] = (0, import_react.useState)({
    VIP: false,
    Standard: false
  });
  const [dayTimelineScrollToNowToken, setDayTimelineScrollToNowToken] = (0, import_react.useState)(0);
  const [resourceMonthScrollToTodayToken, setResourceMonthScrollToTodayToken] = (0, import_react.useState)(0);
  const prevCalendarViewRef = (0, import_react.useRef)(null);
  const prevViewForSlotIsolationRef = (0, import_react.useRef)(view);
  (0, import_react.useLayoutEffect)(() => {
    const prev = prevCalendarViewRef.current;
    if (view === "day" && (prev === null || prev !== "day")) {
      setDayTimelineScrollToNowToken((t) => t + 1);
    }
    if (view === "resource" && (prev === null || prev !== "resource")) {
      setResourceMonthScrollToTodayToken((t) => t + 1);
    }
    prevCalendarViewRef.current = view;
  }, [view]);
  const blockPanelRef = (0, import_react.useRef)(null);
  const overflowPanelRef = (0, import_react.useRef)(null);
  const moveConfirmRef = (0, import_react.useRef)(null);
  const visibleCourts = (0, import_react.useMemo)(() => courts, [courts]);
  const visibleCourtRows = (0, import_react.useMemo)(
    () => (0, import_bookingCalendarViewShared.buildGroupedCourtRows)(visibleCourts, collapsedGroups),
    [visibleCourts, collapsedGroups]
  );
  const dayKey = (0, import_bookingCalendarDateUtils.fmtDate)(anchorDate);
  const hourSlots = (0, import_react.useMemo)(
    () => (0, import_utils.buildCalendarTimelineSlotStartsFromRange)(
      props.timelineRange ?? import_bookingCalendarConstants.DEFAULT_CALENDAR_TIMELINE,
      anchorDate,
      resolvedSlotMinutes
    ),
    [props.timelineRange, anchorDate, resolvedSlotMinutes]
  );
  const {
    dayRowHeights,
    overlayBookings,
    courtDayDisplayLaneCount,
    hiddenDayOverlayIdSet,
    dayOverlayOverflowPluses
  } = (0, import_useBookingCalendarDayOverlayLayout.useBookingCalendarDayOverlayLayout)(
    visibleCourtRows,
    dayKey,
    bookings,
    hourSlots,
    slotStepHours
  );
  const weekDays = (0, import_react.useMemo)(() => (0, import_bookingCalendarDateUtils.rangeDays)(anchorDate), [anchorDate]);
  const resourceMonthDays = (0, import_react.useMemo)(
    () => (0, import_bookingCalendarDateUtils.monthCalendarDays)(anchorDate),
    [anchorDate]
  );
  const selectedWeekKeys = (0, import_react.useMemo)(
    () => new Set(weekDays.map((d) => (0, import_bookingCalendarDateUtils.fmtDate)(d))),
    [weekDays]
  );
  const firstTimelineHour = hourSlots[0] ?? 0;
  const endTimelineExclusive = hourSlots.length ? hourSlots[hourSlots.length - 1] + slotStepHours : 24;
  const isBusinessHour = (0, import_react.useCallback)(
    (h) => (0, import_bookingCalendarDateUtils.isHourInTimelineSlots)(h, hourSlots),
    [hourSlots]
  );
  const dayHourRemaining = (0, import_useBookingCalendarDayHourRemaining.useBookingCalendarDayHourRemaining)(
    visibleCourts,
    dayKey,
    bookings,
    hourSlots,
    slotStepHours,
    isBusinessHour
  );
  const resourceDayHeaderRemaining = (0, import_useBookingCalendarResourceDayHeaderRemaining.useBookingCalendarResourceDayHeaderRemaining)(
    resourceMonthDays,
    visibleCourts,
    bookings,
    hourSlots,
    slotStepHours
  );
  const resourceSelectionContiguous = (0, import_react.useMemo)(
    () => (0, import_bookingCalendarSelectionUtils.isResourceSelectionContiguousSameCourt)(selectedResourceCells),
    [selectedResourceCells]
  );
  const resourceSelectionBarMeta = (0, import_react.useMemo)(() => {
    if (selectedResourceCells.length === 0) return null;
    return {
      freePickCount: selectedResourceCells.length,
      blockPickCount: selectedResourceCells.length,
      freeAllowsBlockPanel: resourceSelectionContiguous
    };
  }, [selectedResourceCells, resourceSelectionContiguous]);
  (0, import_react.useEffect)(() => {
    const prev = prevViewForSlotIsolationRef.current;
    if (prev !== view) {
      if (view === "day") setSelectedResourceCells([]);
      if (view === "resource") {
        setSelectedFreeSlots([]);
        setSelectedBlockSlots([]);
      }
      prevViewForSlotIsolationRef.current = view;
    }
  }, [view]);
  const monthDays = (0, import_react.useMemo)(
    () => (0, import_bookingCalendarDateUtils.monthGrid)(anchorDate, bookings, courts, hourSlots, slotStepHours),
    [anchorDate, bookings, courts, hourSlots, slotStepHours]
  );
  const dayContentHeight = import_bookingCalendarConstants.dayHeaderHeight + dayRowHeights.reduce((sum, h) => sum + h, 0);
  (0, import_react.useEffect)(() => {
    function handleOutside(e) {
      const target = e.target;
      if (!(target instanceof Node)) return;
      if (showBlockPanel && blockPanelRef.current && !blockPanelRef.current.contains(target))
        setShowBlockPanel(false);
      if (overflowPopover && overflowPanelRef.current && !overflowPanelRef.current.contains(target))
        setOverflowPopover(null);
      if (overflowListModal && overflowPanelRef.current && !overflowPanelRef.current.contains(target))
        setOverflowListModal(null);
      if (moveConfirm && moveConfirmRef.current && !moveConfirmRef.current.contains(target))
        setMoveConfirm(null);
    }
    document.addEventListener("mousedown", handleOutside);
    return () => document.removeEventListener("mousedown", handleOutside);
  }, [showBlockPanel, overflowPopover, overflowListModal, moveConfirm]);
  (0, import_react.useEffect)(() => {
    if (!showBlockPanel) return;
    if (view === "resource") {
      if (!resourceSelectionContiguous) setShowBlockPanel(false);
      return;
    }
    if (!(0, import_bookingCalendarDateUtils.isFreeSelectionContiguousSameResource)(selectedFreeSlots, slotStepHours)) {
      setShowBlockPanel(false);
    }
  }, [
    showBlockPanel,
    view,
    selectedFreeSlots,
    resourceSelectionContiguous,
    slotStepHours
  ]);
  (0, import_react.useEffect)(() => {
    if (props.onBlockedTimePanelRequest) return;
    if (!showBlockPanel) return;
    if (view === "resource") {
      if (!resourceSelectionContiguous) return;
      const sortedDates = [...selectedResourceCells].map((s) => s.dateKey).sort();
      const firstDate = sortedDates[0];
      const lastDate = sortedDates[sortedDates.length - 1];
      const bizHours = hourSlots.filter(
        (h) => (0, import_bookingCalendarDateUtils.isHourInTimelineSlots)(h, hourSlots)
      );
      const h0 = bizHours[0] ?? 0;
      const hLast = bizHours[bizHours.length - 1] ?? h0;
      const slotStep = slotStepHours > 0 ? slotStepHours : 1;
      setBlockResourceId(String(selectedResourceCells[0].courtId));
      setBlockTimeRange([
        (0, import_bookingCalendarDateUtils.dayAndHourToDayjs)(firstDate, h0),
        (0, import_bookingCalendarDateUtils.dayAndHourToDayjs)(lastDate, hLast + slotStep)
      ]);
      setBlockFormName((0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.defaultTitle"));
      setBlockModalNote("");
      return;
    }
    if (selectedFreeSlots.length === 0) return;
    const groups = (0, import_bookingCalendarDateUtils.groupSelectedSlots)(selectedFreeSlots, slotStepHours);
    const g = groups[0];
    if (!g) return;
    setBlockResourceId(String(g.courtId));
    setBlockTimeRange([
      (0, import_bookingCalendarDateUtils.dayAndHourToDayjs)(g.date, g.startHour),
      (0, import_bookingCalendarDateUtils.dayAndHourToDayjs)(g.date, g.endHour)
    ]);
    setBlockFormName((0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.defaultTitle"));
    setBlockModalNote("");
  }, [
    showBlockPanel,
    view,
    selectedFreeSlots,
    selectedResourceCells,
    resourceSelectionContiguous,
    hourSlots,
    slotStepHours,
    props.onBlockedTimePanelRequest
  ]);
  (0, import_react.useEffect)(() => {
    if (!transitioningToDay) return;
    const timer = setTimeout(() => setTransitioningToDay(null), 280);
    return () => clearTimeout(timer);
  }, [transitioningToDay]);
  const goToDayFromCell = (0, import_useBookingCalendarGoToDayFromCell.useBookingCalendarGoToDayFromCell)(
    anchorDate,
    commitAnchor,
    commitView,
    setNavDirection,
    setTransitioningToDay,
    setSelectedFreeSlots,
    setSelectedBlockSlots,
    setSelectedResourceCells,
    setFocusedCourtId
  );
  const toggleResourceCell = (0, import_useBookingCalendarResourceCellToggle.useBookingCalendarResourceCellToggle)(
    setSelectedResourceCells
  );
  const { isFreeSelected, isBlockSelected, toggleSlot } = (0, import_useBookingCalendarDaySelection.useBookingCalendarDaySelection)(
    dayKey,
    bookings,
    hourSlots,
    slotStepHours,
    courts,
    selectedFreeSlots,
    selectedBlockSlots,
    setSelectedFreeSlots,
    setSelectedBlockSlots
  );
  const openBookingDetail = (0, import_react.useCallback)(
    (item) => {
      var _a;
      if (((_a = props.onBookingClick) == null ? void 0 : _a.call(props, item)) === true) {
        return;
      }
      setOverflowPopover(null);
    },
    [props.onBookingClick]
  );
  function deselectAll() {
    setSelectedFreeSlots([]);
    setSelectedBlockSlots([]);
  }
  function createBookingFromSelection() {
    if (selectedFreeSlots.length === 0) return;
    const groups = (0, import_bookingCalendarDateUtils.groupSelectedSlots)(selectedFreeSlots, slotStepHours);
    const host = props.onCreateBookingFromSelection;
    if (host) {
      void (async () => {
        try {
          const consumed = await Promise.resolve(
            host({
              mode: "day",
              groups: groups.map((g) => ({
                courtId: g.courtId,
                date: g.date,
                startHour: g.startHour,
                endHour: g.endHour
              }))
            })
          );
          if (consumed !== false) setSelectedFreeSlots([]);
        } catch {
        }
      })();
      return;
    }
    if (!allowPersist("createBooking")) return;
    const newBookings = groups.map(
      (slot, idx) => ({
        id: `new-${slot.courtId}-${slot.date}-${slot.startHour}-${idx}`,
        courtId: slot.courtId,
        date: slot.date,
        startHour: slot.startHour,
        endHour: slot.endHour,
        name: (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.common.newBookingName"),
        kind: "booking"
      })
    );
    setBookings((prev) => [...newBookings, ...prev]);
    setSelectedFreeSlots([]);
  }
  function createBookingFromResourceSelection() {
    if (!resourceSelectionContiguous) return;
    const sortedDates = [...selectedResourceCells].map((s) => s.dateKey).sort();
    const firstDate = sortedDates[0];
    const lastDate = sortedDates[sortedDates.length - 1];
    const courtId = selectedResourceCells[0].courtId;
    const bizHours = hourSlots.filter(
      (h) => (0, import_bookingCalendarDateUtils.isHourInTimelineSlots)(h, hourSlots)
    );
    const h0 = bizHours[0] ?? 0;
    const hLast = bizHours[bizHours.length - 1] ?? h0;
    const slotStep = slotStepHours > 0 ? slotStepHours : 1;
    const endHour = hLast + slotStep;
    const host = props.onCreateBookingFromSelection;
    if (host) {
      void (async () => {
        try {
          const consumed = await Promise.resolve(
            host({
              mode: "resource",
              courtId,
              dates: sortedDates,
              startHour: h0,
              endHour
            })
          );
          if (consumed !== false) setSelectedResourceCells([]);
        } catch {
        }
      })();
      return;
    }
    if (!allowPersist("createBooking")) return;
    const newBooking = {
      id: `new-${courtId}-${firstDate}-${Date.now()}`,
      courtId,
      date: firstDate,
      endDate: lastDate !== firstDate ? lastDate : void 0,
      startHour: h0,
      endHour,
      name: (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.common.newBookingName"),
      kind: "booking"
    };
    setBookings((prev) => [newBooking, ...prev]);
    setSelectedResourceCells([]);
  }
  const handleOpenBlockPanelFromSelection = (0, import_react.useCallback)(async () => {
    if (!(0, import_bookingCalendarDateUtils.isFreeSelectionContiguousSameResource)(selectedFreeSlots, slotStepHours)) {
      return;
    }
    const groups = (0, import_bookingCalendarDateUtils.groupSelectedSlots)(selectedFreeSlots, slotStepHours);
    const g = groups[0];
    if (!g) return;
    if (props.onBlockedTimePanelRequest) {
      try {
        const slotsPayload = selectedFreeSlots.map((s) => {
          const slot = {
            courtId: s.courtId,
            date: s.date,
            hour: s.hour
          };
          const extra = s;
          if (extra.court !== void 0 && extra.court !== "") {
            slot.court = extra.court;
          }
          return slot;
        });
        const payload = {
          slotStepHours,
          slotStepMinutes: resolvedSlotMinutes,
          /** 与 mergedRange 同日，资源视图多选时锚定日未必等于选区日 */
          dayKey: g.date,
          selectedFreeSlots: slotsPayload,
          mergedRange: {
            courtId: g.courtId,
            date: g.date,
            startHour: g.startHour,
            endHour: g.endHour
          }
        };
        const ok = await props.onBlockedTimePanelRequest(payload);
        if (ok !== false) {
          setSelectedFreeSlots([]);
        }
      } catch {
      }
      return;
    }
    setShowBlockPanel(true);
  }, [
    selectedFreeSlots,
    slotStepHours,
    resolvedSlotMinutes,
    props.onBlockedTimePanelRequest
  ]);
  const handleOpenBlockPanelFromResource = (0, import_react.useCallback)(async () => {
    if (!resourceSelectionContiguous) return;
    const sortedDates = [...selectedResourceCells].map((s) => s.dateKey).sort();
    const firstDate = sortedDates[0];
    const lastDate = sortedDates[sortedDates.length - 1];
    const courtId = selectedResourceCells[0].courtId;
    const court = courts.find((c) => c.id === courtId);
    const bizHours = hourSlots.filter(
      (h) => (0, import_bookingCalendarDateUtils.isHourInTimelineSlots)(h, hourSlots)
    );
    const h0 = bizHours[0] ?? 0;
    const hLast = bizHours[bizHours.length - 1] ?? h0;
    const slotStep = slotStepHours > 0 ? slotStepHours : 1;
    const startHour = h0;
    const endHour = hLast + slotStep;
    if (props.onBlockedTimePanelRequest) {
      try {
        const slotsPayload = sortedDates.map((d) => ({
          courtId,
          date: d,
          hour: startHour,
          ...(court == null ? void 0 : court.name) ? { court: court.name } : {}
        }));
        const payload = {
          slotStepHours,
          slotStepMinutes: resolvedSlotMinutes,
          dayKey: firstDate,
          selectedFreeSlots: slotsPayload,
          mergedRange: {
            courtId,
            date: firstDate,
            endDate: lastDate !== firstDate ? lastDate : void 0,
            startHour,
            endHour
          }
        };
        const ok = await props.onBlockedTimePanelRequest(payload);
        if (ok !== false) {
          setSelectedResourceCells([]);
        }
      } catch {
      }
      return;
    }
    setShowBlockPanel(true);
  }, [
    selectedResourceCells,
    resourceSelectionContiguous,
    hourSlots,
    slotStepHours,
    courts,
    resolvedSlotMinutes,
    props.onBlockedTimePanelRequest
  ]);
  async function saveBlockedTime() {
    if (!(blockTimeRange == null ? void 0 : blockTimeRange[0]) || !(blockTimeRange == null ? void 0 : blockTimeRange[1])) {
      import_antd.message.warning(
        (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.warnSelectTime")
      );
      return;
    }
    const [start, end] = blockTimeRange;
    if (!end.isAfter(start)) {
      import_antd.message.warning(
        (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.warnEndAfterStart")
      );
      return;
    }
    const rid = Number(blockResourceId);
    if (!Number.isFinite(rid) || rid <= 0) {
      import_antd.message.warning(
        (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.warnSelectResource")
      );
      return;
    }
    const channels = props.blockedTimeSalesChannels ?? ["online_store"];
    const payload = {
      name: (blockFormName || "").trim() || (0, import_calendarI18n.tCal)("pisell2.recordBoard.calendar.block.defaultTitle"),
      note: (blockModalNote || "").trim(),
      resource_ids: [rid],
      blocked_sales_channels: channels,
      start_time: start.format("YYYY-MM-DD HH:mm"),
      end_time: end.format("YYYY-MM-DD HH:mm")
    };
    if (props.onBlockedTimeSave) {
      setBlockSaving(true);
      try {
        const ok = await props.onBlockedTimeSave(payload);
        if (ok === false) return;
        setShowBlockPanel(false);
        setSelectedFreeSlots([]);
        setSelectedResourceCells([]);
        setBlockModalNote("");
      } finally {
        setBlockSaving(false);
      }
      return;
    }
    const courtId = String(blockResourceId);
    const date = start.format("YYYY-MM-DD");
    const endDate = end.format("YYYY-MM-DD");
    const startHour = start.hour() + start.minute() / 60;
    const endHour = end.hour() + end.minute() / 60;
    const nextBlock = {
      id: `block-local-${courtId}-${date}-${startHour}-${Date.now()}`,
      courtId,
      date,
      endDate: endDate !== date ? endDate : void 0,
      startHour,
      endHour,
      name: payload.name,
      note: payload.note,
      blockedAt: date,
      kind: "block"
    };
    if (!allowPersist("createBlock")) return;
    setBookings((prev) => [nextBlock, ...prev]);
    setSelectedFreeSlots([]);
    setSelectedResourceCells([]);
    setShowBlockPanel(false);
    setBlockModalNote("");
  }
  const handleDropMove = (0, import_react.useCallback)(
    (targetCourtId, targetDate, targetHour) => {
      if (!draggingItem) return;
      const duration = draggingItem.endHour - draggingItem.startHour;
      const nextStart = targetHour;
      const nextEnd = targetHour + duration;
      if (!(0, import_bookingCalendarDateUtils.isHourInTimelineSlots)(nextStart, hourSlots) || nextEnd > endTimelineExclusive)
        return;
      const targetCourt = targetCourtId ?? draggingItem.courtId;
      const itemSnapshot = draggingItem;
      const draft = {
        targetCourtId: targetCourt,
        targetDate,
        targetHour
      };
      setDraggingItem(null);
      if (props.onBookingMoveRequest) {
        void Promise.resolve(
          props.onBookingMoveRequest({ item: itemSnapshot, draft })
        ).catch(() => {
        });
        return;
      }
      setMoveConfirm({
        item: itemSnapshot,
        targetCourtId: targetCourt,
        targetDate,
        targetHour
      });
      setMoveDraft(draft);
    },
    [
      draggingItem,
      hourSlots,
      endTimelineExclusive,
      props.onBookingMoveRequest
    ]
  );
  const handleGridDropMove = (0, import_react.useCallback)(
    (targetDate, targetCourtId = null) => {
      if (!draggingItem || draggingItem.kind === "block") return;
      handleDropMove(
        targetCourtId ?? draggingItem.courtId,
        targetDate,
        draggingItem.startHour
      );
    },
    [draggingItem, handleDropMove]
  );
  function confirmMove() {
    if (!moveConfirm || !moveDraft) return;
    if (!allowPersist("moveBooking")) return;
    const { item } = moveConfirm;
    const { targetCourtId, targetDate, targetHour } = moveDraft;
    const duration = item.endHour - item.startHour;
    setBookings(
      (prev) => prev.map(
        (b) => b.id === item.id ? {
          ...b,
          courtId: targetCourtId,
          date: targetDate,
          startHour: targetHour,
          endHour: targetHour + duration
        } : b
      )
    );
    setMoveConfirm(null);
    setMoveDraft(null);
  }
  return /* @__PURE__ */ import_react.default.createElement(
    import_antd.Spin,
    {
      spinning: Boolean(props.loading),
      wrapperClassName: "pisell-rb-cal-spin-wrap flex min-h-0 flex-1 flex-col"
    },
    /* @__PURE__ */ import_react.default.createElement(
      "div",
      {
        className: `theme-root theme-app flex h-full min-h-0 flex-col ${isLight ? "theme-light" : "theme-dark"}`
      },
      /* @__PURE__ */ import_react.default.createElement(
        "div",
        {
          className: "theme-shell soft-shadow mx-0 flex h-full min-h-0 w-full max-w-none flex-1 flex-col overflow-hidden transition-[padding-right] duration-200",
          style: { paddingRight: 0 }
        },
        /* @__PURE__ */ import_react.default.createElement("div", { className: "flex min-h-0 flex-1 flex-col" }, view === "month" && /* @__PURE__ */ import_react.default.createElement(
          import_BookingCalendarMonthView.BookingCalendarMonthView,
          {
            isLight,
            anchorDate,
            monthDays,
            bookings,
            goToDayFromCell,
            handleGridDropMove,
            setDraggingItem,
            openBookingDetail,
            overflowPopover,
            setOverflowPopover,
            overflowListModal,
            setOverflowListModal,
            overflowPanelRef,
            renderMonthWeekBooking: props.renderMonthWeekBooking
          }
        ), view === "week" && /* @__PURE__ */ import_react.default.createElement(
          import_BookingCalendarWeekView.BookingCalendarWeekView,
          {
            calendarProps: props,
            isLight,
            weekDays,
            bookings,
            courts,
            hourSlots,
            slotStepHours,
            visibleCourts,
            visibleCourtRows,
            isBusinessHour,
            goToDayFromCell,
            handleGridDropMove,
            openBookingDetail,
            setDraggingItem,
            setCollapsedGroups,
            overflowPopover,
            setOverflowPopover,
            overflowListModal,
            setOverflowListModal,
            overflowPanelRef
          }
        ), view === "resource" && /* @__PURE__ */ import_react.default.createElement(
          import_BookingCalendarResourceView.BookingCalendarResourceView,
          {
            calendarProps: props,
            isLight,
            anchorDate,
            monthDays: resourceMonthDays,
            slotColWidth: resourceViewSlotColWidth,
            bookings,
            hourSlots,
            slotStepHours,
            visibleCourts,
            visibleCourtRows,
            handleGridDropMove,
            openBookingDetail,
            setDraggingItem,
            setCollapsedGroups,
            overflowPopover,
            setOverflowPopover,
            setOverflowListModal,
            overflowPanelRef,
            resourceMonthScrollToTodayToken,
            resourceDayHeaderRemaining,
            toggleResourceCell,
            selectedResourceCells
          }
        ), view === "day" && /* @__PURE__ */ import_react.default.createElement(
          import_BookingCalendarDayView.BookingCalendarDayView,
          {
            calendarProps: props,
            isLight,
            view,
            anchorDate,
            dayKey,
            hourSlots,
            resolvedSlotMinutes,
            slotColWidth,
            firstTimelineHour,
            endTimelineExclusive,
            isBusinessHour,
            dayHourRemaining,
            timelinePxPerHour,
            dayContentHeight,
            dayRowHeights,
            visibleCourtRows,
            overlayBookings,
            dayOverlayOverflowPluses,
            setCollapsedGroups,
            visibleCourts,
            bookings,
            slotStepHours,
            isFreeSelected,
            isBlockSelected,
            toggleSlot,
            handleDropMove,
            hiddenDayOverlayIdSet,
            courtDayDisplayLaneCount,
            openBookingDetail,
            setDraggingItem,
            setNavDirection,
            commitAnchor,
            setFocusedCourtId,
            setOverflowListModal,
            selectedFreeSlots,
            selectedBlockSlots,
            focusedCourtId,
            dayTimelineScrollToNowToken
          }
        ))
      ),
      view === "day" && (selectedFreeSlots.length > 0 || selectedBlockSlots.length > 0) || view === "resource" && selectedResourceCells.length > 0 ? /* @__PURE__ */ import_react.default.createElement(
        import_BookingCalendarDaySelectionBar.BookingCalendarDaySelectionBar,
        {
          slotStepHours,
          selectedFreeSlots: view === "resource" ? [] : selectedFreeSlots,
          resourceSelectionSummary: view === "resource" ? resourceSelectionBarMeta : void 0,
          deselectAll: view === "resource" ? () => setSelectedResourceCells([]) : deselectAll,
          onOpenBlockPanel: view === "resource" ? handleOpenBlockPanelFromResource : handleOpenBlockPanelFromSelection,
          createBookingFromSelection: view === "resource" ? createBookingFromResourceSelection : createBookingFromSelection
        }
      ) : null,
      showBlockPanel && !props.onBlockedTimePanelRequest && (view === "resource" ? resourceSelectionContiguous : selectedFreeSlots.length > 0 && (0, import_bookingCalendarDateUtils.isFreeSelectionContiguousSameResource)(
        selectedFreeSlots,
        slotStepHours
      )) && /* @__PURE__ */ import_react.default.createElement(
        import_BookingCalendarBlockPanel.BookingCalendarBlockPanel,
        {
          blockPanelRef,
          isLight,
          blockFormName,
          setBlockFormName,
          blockModalNote,
          setBlockModalNote,
          blockResourceId,
          setBlockResourceId,
          blockTimeRange,
          setBlockTimeRange,
          resolvedSlotMinutes,
          visibleCourts,
          blockSaving,
          onClose: () => setShowBlockPanel(false),
          onSave: saveBlockedTime
        }
      ),
      overflowListModal && /* @__PURE__ */ import_react.default.createElement(
        import_BookingCalendarOverflowListLayer.BookingCalendarOverflowListLayer,
        {
          overflowPanelRef,
          isLight,
          modal: overflowListModal,
          onClose: () => setOverflowListModal(null),
          onPickItem: openBookingDetail
        }
      ),
      moveConfirm && /* @__PURE__ */ import_react.default.createElement(
        import_MoveConfirmModal.MoveConfirmModal,
        {
          moveConfirm,
          moveDraft,
          setMoveDraft,
          panelRef: moveConfirmRef,
          isLight,
          courts,
          visibleCourts,
          hourSlots,
          isBusinessHour,
          firstTimelineHour,
          endTimelineExclusive,
          onConfirm: confirmMove,
          onClose: () => {
            setMoveConfirm(null);
            setMoveDraft(null);
          }
        }
      ),
      transitioningToDay && /* @__PURE__ */ import_react.default.createElement("div", { className: "fixed inset-6 z-[60] rounded-[28px] border border-violet-400/20 bg-[#151220] pointer-events-none" })
    )
  );
}
