const require_runtime = require("../../../_virtual/_rolldown/runtime.js");
const require_objectSpread2 = require("../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js");
const require_asyncToGenerator = require("../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/asyncToGenerator.js");
const require_booking = require("../../pisellSalesManagement/config/booking.js");
const require_serve = require("../../pisellSalesGrid/serve.js");
const require_reservationConstants = require("../reservationConstants.js");
const require_reservationOperatingDayRange = require("../data/reservationOperatingDayRange.js");
let dayjs = require("dayjs");
dayjs = require_runtime.__toESM(dayjs);
let react = require("react");
let _pisell_utils = require("@pisell/utils");
let _pisell_materials = require("@pisell/materials");
let ahooks = require("ahooks");
//#region src/plus/pisellReservation/hooks/usePisellReservationBookingData.ts
/**
* 预约看板列表：与 Sales Management「预约 / monitor」一致，请求 GET /shop/schedule/booking
*/
/** 避免 `?? []` 每次 render 新数组引用，触发依赖 list 的 effect 死循环 */
const EMPTY_RESERVATION_LIST = [];
function bookingWindowClockOrDefault(operatingDayBoundary) {
	var _boundaryClockFromOpe;
	return (_boundaryClockFromOpe = require_reservationOperatingDayRange.boundaryClockFromOperatingDayBoundary(operatingDayBoundary)) !== null && _boundaryClockFromOpe !== void 0 ? _boundaryClockFromOpe : require_reservationConstants.RESERVATION_TIMELINE_BUSINESS_RANGE.start;
}
function anchorAtBoundaryClock(d0, clock) {
	const [hs, ms] = clock.split(":");
	const h = Number(hs);
	const m = Number(ms !== null && ms !== void 0 ? ms : "0");
	return d0.hour(h).minute(m).second(0).millisecond(0);
}
function isEndTimeOperatingBoundary(operatingDayBoundary) {
	var _b$type;
	const b = operatingDayBoundary;
	return String((_b$type = b === null || b === void 0 ? void 0 : b.type) !== null && _b$type !== void 0 ? _b$type : "") === "end_time";
}
/**
* 营业日锚定：`core.operating_day_boundary`。
* - `start_time`：选中日 D 的营业窗为 [D 界钟, 次日同钟)；
* - `end_time`：选中日 D 表示营业在 D 的界钟结束，窗为 [D−1 界钟, D 界钟)；
* 无有效界钟时与 {@link RESERVATION_TIMELINE_BUSINESS_RANGE} 一致（02:00）。
*/
function bookingTimeWindowForAnchorDay(anchorDay, operatingDayBoundary) {
	const clock = bookingWindowClockOrDefault(operatingDayBoundary);
	const d0 = anchorDay.startOf("day");
	const start = anchorAtBoundaryClock(isEndTimeOperatingBoundary(operatingDayBoundary) ? d0.subtract(1, "day") : d0, clock);
	return [start, start.add(1, "day")];
}
/**
* 平面图 / 列表 `booking_time_start_between` 与时间轴可视营业窗对齐。
*
* - 顶栏日历日 == 自然「今天」：与 TimeNavigator 一致，用 {@link pickReferenceDateContainingNow}
*   + {@link getRangeBounds}（保证凌晨仍落在上一营业日窗内的预约能进画布）；
* - 其它选中日：仍用 {@link bookingTimeWindowForAnchorDay}（按营业边界类型锚定）。
*/
function bookingTimeWindowForReservationView(scheduleDate, operatingDayBoundary, timelineRange = require_reservationConstants.RESERVATION_TIMELINE_BUSINESS_RANGE, wallClock = (0, dayjs.default)()) {
	const anchorDay = (0, dayjs.default)(scheduleDate).startOf("day");
	if (anchorDay.isSame(wallClock.startOf("day"), "day")) return (0, _pisell_materials.getRangeBounds)(timelineRange, (0, _pisell_materials.pickReferenceDateContainingNow)(timelineRange, wallClock));
	return bookingTimeWindowForAnchorDay(anchorDay, operatingDayBoundary);
}
/**
* 日历跨日视口：与单日营业窗按日首尾相接。
* - `start_time`：rangeStart 界钟 → rangeEnd 次日界钟；
* - `end_time`：rangeStart−1 日界钟 → rangeEnd 当日界钟。
*/
function bookingTimeWindowForCalendarRange(rangeStart, rangeEnd, operatingDayBoundary) {
	const clock = bookingWindowClockOrDefault(operatingDayBoundary);
	let rs = (0, dayjs.default)(rangeStart).startOf("day");
	let re = (0, dayjs.default)(rangeEnd).startOf("day");
	if (re.isBefore(rs)) {
		const t = rs;
		rs = re;
		re = t;
	}
	if (isEndTimeOperatingBoundary(operatingDayBoundary)) return [anchorAtBoundaryClock(rs.subtract(1, "day"), clock), anchorAtBoundaryClock(re, clock)];
	return [anchorAtBoundaryClock(rs, clock), anchorAtBoundaryClock(re.add(1, "day"), clock)];
}
/**
* Monitor / 平面图列表初始筛：支付态 + 锚定营业日 `booking_time_start_between`。
*/
function getDefaultMonitorSearchParams(anchorDay = (0, dayjs.default)(), operatingDayBoundary, timelineRange = require_reservationConstants.RESERVATION_TIMELINE_BUSINESS_RANGE, now = (0, dayjs.default)()) {
	return { filter: { values: {
		order_payment_status: require_booking.defaultPaymentStatusKeys,
		booking_time_start_between: bookingTimeWindowForReservationView(anchorDay.startOf("day"), operatingDayBoundary, timelineRange, now)
	} } };
}
/**
* 表格视图初始筛选项：与 Sales Monitor 一致——支付态 + **今日营业日窗口**。
* 传入店铺 `operating_day_boundary` 时与时间轴界钟一致。
*/
function getGridTableBookingSearchParams(operatingDayBoundary, timelineRange = require_reservationConstants.RESERVATION_TIMELINE_BUSINESS_RANGE) {
	return getDefaultMonitorSearchParams((0, dayjs.default)().startOf("day"), operatingDayBoundary, timelineRange);
}
function usePisellReservationBookingData(enabled, options) {
	var _options$listPageSize, _options$getInitialSe, _options$subscribeRea, _req$data, _req$data$count, _req$data2;
	const listPageSize = (_options$listPageSize = options === null || options === void 0 ? void 0 : options.listPageSize) !== null && _options$listPageSize !== void 0 ? _options$listPageSize : 50;
	const getInitialSearchParams = (_options$getInitialSe = options === null || options === void 0 ? void 0 : options.getInitialSearchParams) !== null && _options$getInitialSe !== void 0 ? _options$getInitialSe : (() => getDefaultMonitorSearchParams((0, dayjs.default)()));
	const extraRequestParams = options === null || options === void 0 ? void 0 : options.extraRequestParams;
	const subscribeRealtimePush = (_options$subscribeRea = options === null || options === void 0 ? void 0 : options.subscribeRealtimePush) !== null && _options$subscribeRea !== void 0 ? _options$subscribeRea : true;
	const [pagination, setPagination] = (0, react.useState)({
		pageNumber: 1,
		pageSize: listPageSize
	});
	const [searchParams, setSearchParams] = (0, react.useState)(() => getInitialSearchParams());
	/** 列表 WebSocket 订阅 id，卸载时取消订阅（对齐 ticketBooking useProducts） */
	const subscriberIdRef = (0, react.useRef)((0, _pisell_utils.getUniqueId)());
	const bookingMutateRef = (0, react.useRef)(null);
	/**
	* WS push 微批合并：同一帧内多次推送只跑一次 mutate，避免 N 条推送 → N 次全量 re-merge / canvas 重渲染。
	* - `pendingPayloadRef`：本帧最后一份合法 payload；
	* - `flushScheduledRef`：本帧是否已经排队 rAF flush，避免重复排队。
	* 卸载时取消未执行的 flush，防止在已卸载的 useRequest 上调用 mutate。
	*/
	const pendingPayloadRef = (0, react.useRef)(null);
	const flushScheduledRef = (0, react.useRef)(null);
	const isMountedRef = (0, react.useRef)(true);
	/**
	* 每次 WS 推送 mutate 成功后 +1。下游需要的只是「有没有新推送」这件事本身，
	* 不关心数字大小，所以从 0 开始单调递增即可，溢出不在工程考虑范围。
	*
	* 旧版用 `floorDayBookingDepKey` 的 cheap hash 当唯一信号，仅覆盖 booking_id /
	* status / start_time / end_time / order_payment_status；推送只改了 customer /
	* notes / relation_id / party_size 等非追踪字段时哈希不变 → host effect 不重跑
	* → `salesResourceBookings` 一直是旧值 → 画布看上去不更新。version 兜底解决该断点。
	*/
	const [pushDataVersion, setPushDataVersion] = (0, react.useState)(0);
	(0, react.useEffect)(() => {
		isMountedRef.current = true;
		return () => {
			isMountedRef.current = false;
			if (flushScheduledRef.current != null) {
				cancelAnimationFrame(flushScheduledRef.current);
				flushScheduledRef.current = null;
			}
			pendingPayloadRef.current = null;
		};
	}, []);
	const requestParams = (0, react.useMemo)(() => {
		const { keyword, filter, sort } = searchParams;
		const filterVals = (filter === null || filter === void 0 ? void 0 : filter.values) || {};
		return require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({
			keyword,
			sort
		}, filterVals), extraRequestParams != null ? extraRequestParams : {}), {}, {
			skip: pagination.pageNumber,
			num: pagination.pageSize
		});
	}, [
		searchParams,
		pagination.pageNumber,
		pagination.pageSize,
		extraRequestParams
	]);
	const req = (0, ahooks.useRequest)((0, ahooks.useMemoizedFn)(function() {
		var _ref = require_asyncToGenerator._asyncToGenerator(function* (params) {
			if (!subscribeRealtimePush)
 /**
			* 关闭实时推送时也必须走 osServer，确保命中 pisell_os
			* 的预约路由与周/月缓存逻辑；仅关闭 subscriber/callback。
			*/
			return require_serve.getBookingList(params, { osServer: true });
			return require_serve.getBookingList(params, {
				osServer: true,
				subscriberId: subscriberIdRef.current,
				callback: (res) => {
					var _res$data;
					console.log(res, "res123454321");
					const payload = (_res$data = res === null || res === void 0 ? void 0 : res.data) !== null && _res$data !== void 0 ? _res$data : res;
					if (payload == null || !Array.isArray(payload.list)) return;
					/**
					* 订阅推送常在 HTTP 分页返回之后到达；若 payload 为 `list: []`（无有效行），
					* mutate 会整块覆盖 useRequest 里刚写入的当前页，表现为「每次翻页都有请求但表格不展示」。
					* 有意清空列表应依赖再次请求或明确带 count 的整包推送，此处不处理空 list 覆盖。
					*/
					pendingPayloadRef.current = payload;
					if (flushScheduledRef.current != null) return;
					flushScheduledRef.current = requestAnimationFrame(() => {
						var _bookingMutateRef$cur;
						flushScheduledRef.current = null;
						const next = pendingPayloadRef.current;
						pendingPayloadRef.current = null;
						if (next == null || !isMountedRef.current) return;
						(_bookingMutateRef$cur = bookingMutateRef.current) === null || _bookingMutateRef$cur === void 0 || _bookingMutateRef$cur.call(bookingMutateRef, require_serve.formatBookingResult(next));
						setPushDataVersion((v) => v + 1);
					});
				}
			});
		});
		return function(_x) {
			return _ref.apply(this, arguments);
		};
	}()), { manual: true });
	bookingMutateRef.current = req.mutate;
	(0, react.useEffect)(() => {
		if (!enabled) return;
		req.run(requestParams);
	}, [enabled, requestParams]);
	const onPageChange = (0, react.useCallback)((pageNumber, pageSize) => {
		if (pageNumber < 1 || pageSize < 1) return;
		setPagination({
			pageNumber,
			pageSize
		});
	}, []);
	const onSearch = (0, react.useCallback)((params) => {
		setSearchParams(params || {});
		setPagination((p) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, p), {}, { pageNumber: 1 }));
	}, []);
	const onReset = (0, react.useCallback)(() => {
		setSearchParams(getInitialSearchParams());
		setPagination((p) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, p), {}, { pageNumber: 1 }));
	}, [getInitialSearchParams]);
	const patchSearchParams = (0, react.useCallback)((updater) => {
		setSearchParams((prev) => updater(require_objectSpread2._objectSpread2({}, prev)));
		setPagination((p) => require_objectSpread2._objectSpread2(require_objectSpread2._objectSpread2({}, p), {}, { pageNumber: 1 }));
	}, []);
	const refresh = (0, react.useCallback)(() => {
		req.run(requestParams);
	}, [req, requestParams]);
	const refreshAsync = (0, react.useCallback)(() => {
		return req.runAsync(requestParams);
	}, [req, requestParams]);
	/** 接口常返回新的 `[]`，勿直接作依赖否则下游 effect（如 sales 合并）死循环 */
	const rawList = (_req$data = req.data) === null || _req$data === void 0 ? void 0 : _req$data.list;
	const data = (0, react.useMemo)(() => {
		if (!Array.isArray(rawList) || rawList.length === 0) return EMPTY_RESERVATION_LIST;
		return rawList;
	}, [rawList]);
	const total = (_req$data$count = (_req$data2 = req.data) === null || _req$data2 === void 0 ? void 0 : _req$data2.count) !== null && _req$data$count !== void 0 ? _req$data$count : 0;
	return {
		data,
		loading: req.loading,
		total,
		pagination,
		onPageChange,
		searchParams,
		onSearch,
		onReset,
		refresh,
		refreshAsync,
		patchSearchParams,
		pushDataVersion
	};
}
//#endregion
exports.EMPTY_RESERVATION_LIST = EMPTY_RESERVATION_LIST;
exports.bookingTimeWindowForCalendarRange = bookingTimeWindowForCalendarRange;
exports.bookingTimeWindowForReservationView = bookingTimeWindowForReservationView;
exports.getDefaultMonitorSearchParams = getDefaultMonitorSearchParams;
exports.getGridTableBookingSearchParams = getGridTableBookingSearchParams;
exports.usePisellReservationBookingData = usePisellReservationBookingData;
