import { _objectSpread2 } from "../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
import { resolveFloorRoomCardHolder } from "../floorRoomCard/mapRowToFloorRoomCardData.js";
import dayjs from "dayjs";
//#region src/plus/pisellReservation/data/bookingToReservationTables.ts
/**
* 将 GET /shop/schedule/booking 列表项转为平面图/卡片用的 {@link PisellReservationTableRow}。
* 按资源 form_record（event_resources.relation_id）聚合；无资源时退化为按预约 id 一行。
*/
/**
* 仅 `status: reserved | occupied | locked` 参与合并；`empty` 与未知项不写入预约行（桌位保持空闲底行）。
*/
function isSkippedBooking(record) {
	var _record$status;
	const s = String((_record$status = record.status) !== null && _record$status !== void 0 ? _record$status : "");
	return s !== "reserved" && s !== "occupied" && s !== "locked";
}
/**
* 从 event_resources / resources 节点收集 relation_id（与平面图 dataBinding.recordId 对齐）
*/
function collectRelationIdsFromNode(node, ids) {
	if (!node) return;
	const rid = node.relation_id;
	if (typeof rid === "number" && rid > 0) ids.add(String(Math.trunc(rid)));
	else if (typeof rid === "string" && rid !== "" && rid !== "0") ids.add(rid);
	const kids = node.children;
	if (Array.isArray(kids)) for (const ch of kids) collectRelationIdsFromNode(ch, ids);
}
/**
* 预约项上所有资源 form_record id（GET schedule/booking 多为 `resources`，旧结构为 `event_resources`）。
* 多资源时同一预约会写入多个 id，合并阶段每张桌只拿命中本桌 id 的分组。
*/
function extractResourceRecordIds(booking) {
	const ids = /* @__PURE__ */ new Set();
	const er = booking.event_resources;
	if (Array.isArray(er)) for (const block of er) collectRelationIdsFromNode(block, ids);
	const res = booking.resources;
	if (Array.isArray(res)) for (const block of res) collectRelationIdsFromNode(block, ids);
	return [...ids];
}
/**
* 按画布已绑定资源 id 过滤 Monitor 用的 booking 列表行（与 {@link extractResourceRecordIds} 对齐）。
* `resourceIds` 为空时返回空数组。
*/
function filterBookingsByResourceIds(bookings, resourceIds) {
	if (!Array.isArray(bookings) || resourceIds.size === 0) return [];
	return bookings.filter((b) => {
		return extractResourceRecordIds(b).some((id) => resourceIds.has(id));
	});
}
/** 多资源单的父级壳行（无 resources / 无 product_uid），不参与按桌聚合，避免错误 orphan id */
function isAggregateParentShell(booking) {
	const meta = booking.metadata;
	if ((meta === null || meta === void 0 ? void 0 : meta.multiple_resource_flag) !== 1) return false;
	const uid = booking.product_uid;
	if (uid != null && String(uid) !== "") return false;
	const res = booking.resources;
	return !Array.isArray(res) || res.length === 0;
}
function resourceDisplayCode(booking) {
	var _meta$resource_name, _booking$id;
	const name = booking.relation_form_name;
	if (name) return name;
	const er0 = Array.isArray(booking.event_resources) ? booking.event_resources[0] : void 0;
	const res0 = Array.isArray(booking.resources) ? booking.resources[0] : void 0;
	const head = er0 !== null && er0 !== void 0 ? er0 : res0;
	const meta = head === null || head === void 0 ? void 0 : head.metadata;
	const rn = (_meta$resource_name = meta === null || meta === void 0 ? void 0 : meta.resource_name) !== null && _meta$resource_name !== void 0 ? _meta$resource_name : meta === null || meta === void 0 ? void 0 : meta.form_name;
	if (typeof rn === "string" && rn) return rn;
	const bid = booking.booking_id;
	if (bid != null && bid !== "") return String(bid);
	return String((_booking$id = booking.id) !== null && _booking$id !== void 0 ? _booking$id : "");
}
/**
* 预约项联系人简称（与图元 / 详情弹窗 / {@link resolveFloorRoomCardHolder} 一致，仅取展示用姓名）。
*/
function customerBrief(record) {
	var _h$name;
	const h = resolveFloorRoomCardHolder(record);
	return (h === null || h === void 0 || (_h$name = h.name) === null || _h$name === void 0 ? void 0 : _h$name.trim()) || "";
}
/** 单条预约上的日历日，用于平面图卡片进度与合成字段 */
function bookingReferenceDay(booking) {
	const at = booking.start_at;
	if (at && dayjs(at).isValid()) return dayjs(at).format("YYYY-MM-DD");
	const sd = booking.start_date;
	if (typeof sd === "string" && /^\d{4}-\d{2}-\d{2}/.test(sd)) return sd.slice(0, 10);
}
function formatBookingTime(record) {
	const raw = record.start_at || (record.start_date && record.start_time ? `${record.start_date} ${record.start_time}` : null);
	if (!raw) return "";
	const d = dayjs(raw);
	return d.isValid() ? d.format("HH:mm") : "";
}
/** 宿主 booking.status：empty / 缺省 → 空闲；reserved / occupied / locked → 对应卡片大类 */
function hostBookingStatusToCardStatus(record) {
	var _record$status2;
	const s = String((_record$status2 = record.status) !== null && _record$status2 !== void 0 ? _record$status2 : "");
	if (s === "occupied") return "occupied";
	if (s === "reserved") return "booked";
	if (s === "locked") return "maintenance";
	return "available";
}
function hostReservedStatusFromBooking(booking) {
	var _booking$reserved_sta;
	if (String(booking.status) !== "reserved") return void 0;
	const rs = String((_booking$reserved_sta = booking.reserved_status) !== null && _booking$reserved_sta !== void 0 ? _booking$reserved_sta : "");
	if (rs === "late") return "late";
	if (rs === "not_arrived") return "not_arrived";
}
function hostIsTimeoutFromBooking(booking) {
	if (String(booking.status) !== "occupied") return void 0;
	return booking.isTimeout === true ? true : void 0;
}
/** 从单条宿主 booking 摘 `reserved_status` / `isTimeout` 信号，供行合并与图元映射 */
function hostBookingUiPatchFromRecord(booking) {
	const hostReservedStatus = hostReservedStatusFromBooking(booking);
	const hostIsTimeout = hostIsTimeoutFromBooking(booking);
	const out = {};
	if (hostReservedStatus != null) out.hostReservedStatus = hostReservedStatus;
	if (hostIsTimeout === true) out.hostIsTimeout = true;
	return out;
}
/**
* 无 `bookings[]` 命中时，用资源壳上的 `status` / `reserved_status` / `isTimeout` 覆盖底行（嵌套 OS 列表等）。
*/
function applyHostResourceShellToBaseRow(base, shell) {
	var _shell$status;
	const st = String((_shell$status = shell.status) !== null && _shell$status !== void 0 ? _shell$status : "");
	if (st === "locked") return _objectSpread2(_objectSpread2({}, base), {}, { cardStatus: "maintenance" });
	if (st === "empty") return _objectSpread2(_objectSpread2({}, base), {}, {
		cardStatus: "available",
		hostReservedStatus: void 0,
		hostIsTimeout: void 0
	});
	if (st === "occupied") return _objectSpread2(_objectSpread2({}, base), {}, {
		cardStatus: "occupied",
		hostIsTimeout: shell.isTimeout === true ? true : void 0,
		hostReservedStatus: void 0
	});
	if (st === "reserved") return _objectSpread2(_objectSpread2({}, base), {}, {
		cardStatus: "booked",
		hostIsTimeout: void 0
	}, hostBookingUiPatchFromRecord(shell));
	return base;
}
function singleBookingToRow(rowId, booking, codeOverride) {
	return _objectSpread2(_objectSpread2({
		id: rowId,
		code: codeOverride !== null && codeOverride !== void 0 ? codeOverride : resourceDisplayCode(booking),
		cardStatus: hostBookingStatusToCardStatus(booking)
	}, hostBookingUiPatchFromRecord(booking)), {}, {
		guestName: customerBrief(booking) || void 0,
		time: formatBookingTime(booking) || void 0,
		floorMapSourceBookings: [booking],
		floorMapReferenceDay: bookingReferenceDay(booking),
		partySize: (() => {
			const n = booking.number;
			if (typeof n === "number" && Number.isFinite(n)) return n;
			if (n != null && n !== "") {
				const v = Number(n);
				return Number.isFinite(v) ? v : void 0;
			}
		})()
	});
}
function mergeResourceGroup(recordId, group) {
	const named = group.find((g) => g.relation_form_name);
	const code = (named === null || named === void 0 ? void 0 : named.relation_form_name) ? String(named.relation_form_name) : resourceDisplayCode(group[0]);
	const sorted = [...group].sort((a, b) => dayjs(a.start_at || `${a.start_date || ""} ${a.start_time || ""}`.trim()).valueOf() - dayjs(b.start_at || `${b.start_date || ""} ${b.start_time || ""}`.trim()).valueOf());
	if (sorted.length === 1) return singleBookingToRow(recordId, sorted[0], code);
	const hasLocked = sorted.some((b) => String(b.status) === "locked");
	const hasOccupied = sorted.some((b) => String(b.status) === "occupied");
	const cardStatus = hasLocked ? "maintenance" : hasOccupied ? "occupied" : "booked";
	const uiPatch = {};
	if (cardStatus === "occupied") {
		const ob = sorted.find((b) => String(b.status) === "occupied");
		if (ob && hostIsTimeoutFromBooking(ob)) uiPatch.hostIsTimeout = true;
	}
	if (cardStatus === "booked") {
		const rb = sorted.find((b) => String(b.status) === "reserved");
		const rs = rb ? hostReservedStatusFromBooking(rb) : void 0;
		if (rs != null) uiPatch.hostReservedStatus = rs;
	}
	return _objectSpread2(_objectSpread2({
		id: recordId,
		code: code || recordId,
		cardStatus
	}, cardStatus === "maintenance" ? {
		hostReservedStatus: void 0,
		hostIsTimeout: void 0
	} : uiPatch), {}, {
		floorMapSourceBookings: sorted,
		floorMapReferenceDay: bookingReferenceDay(sorted[0]),
		slots: sorted.map((b) => ({
			name: customerBrief(b) || "",
			time: formatBookingTime(b) || "-"
		}))
	});
}
/**
* 宿主已按桌聚合的 `bookings`（如同一张 resource 下的多条预约）→ 单行 {@link PisellReservationTableRow}，
* 与 {@link mergeResourceRowsWithBookingRows} 的资源底行合并即可得到平面图 tables 项。
*/
function mergeBookingsForResourceRecord(recordId, bookings) {
	if (!Array.isArray(bookings)) return null;
	const active = bookings.filter((b) => {
		if (!b || typeof b !== "object") return false;
		const rec = b;
		if (isSkippedBooking(rec)) return false;
		if (isAggregateParentShell(rec)) return false;
		return true;
	});
	if (active.length === 0) return null;
	return mergeResourceGroup(recordId, active);
}
/**
* 由预约列表构造桌位数据源（整列表，与当前表格页数据一致）。
*/
function bookingListToReservationTableRows(bookings) {
	if (!Array.isArray(bookings) || bookings.length === 0) return [];
	const active = bookings.filter((b) => {
		if (!b || typeof b !== "object") return false;
		const rec = b;
		if (isSkippedBooking(rec)) return false;
		if (isAggregateParentShell(rec)) return false;
		return true;
	});
	const byResource = /* @__PURE__ */ new Map();
	const orphans = [];
	for (const b of active) {
		const rids = extractResourceRecordIds(b);
		if (rids.length > 0) for (const rid of rids) {
			var _byResource$get;
			const g = (_byResource$get = byResource.get(rid)) !== null && _byResource$get !== void 0 ? _byResource$get : [];
			g.push(b);
			byResource.set(rid, g);
		}
		else orphans.push(b);
	}
	const rows = [];
	for (const [rid, group] of byResource) rows.push(mergeResourceGroup(rid, group));
	for (const b of orphans) {
		const id = b.id != null ? String(b.id) : `booking_${rows.length}`;
		rows.push(singleBookingToRow(id, b));
	}
	return rows;
}
//#endregion
export { applyHostResourceShellToBaseRow, bookingListToReservationTableRows, extractResourceRecordIds, filterBookingsByResourceIds, hostBookingUiPatchFromRecord, mergeBookingsForResourceRecord };
