import { getCurrentLocale } from "../../../../utils/locale.js";
import { getText } from "../../../../locales/index.js";
import { _objectSpread2 } from "../../../../_virtual/_@oxc-project_runtime@0.122.0/helpers/objectSpread2.js";
import { useRecordBoardContext } from "../../hooks/useRecordBoardContext.js";
import { DEFAULT_RESOURCE_WALL_STATUS_SORT_FIELD_KEYS, getVenueWallStatusToneMap, matchesResourceWallStatusSortField, parseRecordBoardToolbarSortParam, venueWallOccupiedSortRank } from "./venueWallUtils.js";
import { DEFAULT_RESOURCE_WALL_LAYOUT_PERSIST } from "../../types.js";
import { VenueWallCard } from "./VenueWallCard.js";
import { ResourceWallControlPanel } from "./ResourceWallControlPanel.js";
import { ResourceWallViewportToolbar } from "./ResourceWallViewportToolbar.js";
import React, { useCallback, useEffect, useMemo, useRef, useState } from "react";
import { Spin } from "antd";
import "./ResourceWallViewport.less";
//#region src/components/pisellRecordBoard/shellFrame/ResourceWall/PisellRecordBoardResourceWallView.tsx
/** 与 {@link RecordBoardResourceWallProps.filterFieldKey} 默认一致 */
const DEFAULT_RESOURCE_WALL_FILTER_FIELD_KEY = "resource_wall_resource_ids";
/** 伪全屏偏好：刷新后若为 `1` 自动恢复 body 固定视口（与按钮状态一致） */
const RESOURCE_WALL_PSEUDO_FULLSCREEN_STORAGE_KEY = "pisell.recordBoard.resourceWall.pseudoFullscreen";
function readStoredPseudoFullscreen() {
	try {
		return typeof window !== "undefined" && window.localStorage.getItem(RESOURCE_WALL_PSEUDO_FULLSCREEN_STORAGE_KEY) === "1";
	} catch (_unused) {
		return false;
	}
}
function persistPseudoFullscreen(on) {
	try {
		if (typeof window !== "undefined") window.localStorage.setItem(RESOURCE_WALL_PSEUDO_FULLSCREEN_STORAGE_KEY, on ? "1" : "0");
	} catch (_unused2) {}
}
const FILTER_PARAMS_FIELD = "filter";
const LAYOUT_PRESETS = [
	{
		key: "1x1",
		label: "1 × 1",
		cols: 1,
		rows: 1
	},
	{
		key: "1x2",
		label: "1 × 2",
		cols: 2,
		rows: 1
	},
	{
		key: "2x3",
		label: "2 × 3",
		cols: 3,
		rows: 2
	},
	{
		key: "3x2",
		label: "3 × 2",
		cols: 2,
		rows: 3
	},
	{
		key: "3x3",
		label: "3 × 3",
		cols: 3,
		rows: 3
	},
	{
		key: "custom",
		label: "",
		cols: 3,
		rows: 2
	}
];
const DEFAULT_OCCUPIED = "#6f4ae6";
const DEFAULT_AVAILABLE = "#94a3b8";
/**
* RecordBoard 大屏资源墙主视口：`cards` 提供全量卡数据；可见列表由
* `searchParams.filter.values[filterFieldKey]` 中的资源 id 与 `cards` 交集决定。
* 若 ToolBar `searchParams.sort` 指向状态列（默认字段名 `status`），则按占用态重排展示顺序。
* 支持网格分页轮播、浅深外观、伪全屏与控制台（布局 / 配色 / 选中资源）。
*/
const PisellRecordBoardResourceWallView = (props) => {
	var _props$filterFieldKey, _ctx$searchParams3, _appearanceTheme$appe, _pagedGroups$currentP;
	const { className, style, loading, cards: cardsProp, statusToneOverrides: statusToneOverridesProp, onStatusToneOverridesChange, appearanceTheme: appearanceThemeProp, onAppearanceThemeChange, appearanceMode: appearanceModeProp, onAppearanceModeChange, resourceWallLayout: resourceWallLayoutProp, onResourceWallLayoutChange, statusSortFieldKeys: statusSortFieldKeysProp } = props;
	const ctx = useRecordBoardContext();
	const filterKey = (_props$filterFieldKey = props.filterFieldKey) !== null && _props$filterFieldKey !== void 0 ? _props$filterFieldKey : DEFAULT_RESOURCE_WALL_FILTER_FIELD_KEY;
	const statusSortFieldKeys = useMemo(() => statusSortFieldKeysProp != null && statusSortFieldKeysProp.length > 0 ? statusSortFieldKeysProp : [...DEFAULT_RESOURCE_WALL_STATUS_SORT_FIELD_KEYS], [statusSortFieldKeysProp]);
	const [localToneOverrides, setLocalToneOverrides] = useState({});
	/** 六态标注覆盖：有受控回调则只上报；否则写本地 state（演示 / 未持久化宿主） */
	const emitToneOverrides = useCallback((next) => {
		onStatusToneOverridesChange === null || onStatusToneOverridesChange === void 0 || onStatusToneOverridesChange(next);
		if (onStatusToneOverridesChange == null) setLocalToneOverrides(next);
	}, [onStatusToneOverridesChange]);
	const [internalAppearanceTheme, setInternalAppearanceTheme] = useState({});
	const appearanceTheme = appearanceThemeProp !== null && appearanceThemeProp !== void 0 ? appearanceThemeProp : internalAppearanceTheme;
	/** 占用/空闲底色与六态覆盖按浅、深槽位写入主题对象 */
	const persistAppearanceTheme = useCallback((next) => {
		onAppearanceThemeChange === null || onAppearanceThemeChange === void 0 || onAppearanceThemeChange(next);
		if (onAppearanceThemeChange == null) setInternalAppearanceTheme(next);
	}, [onAppearanceThemeChange]);
	/**
	* 资源墙可见 id：未写键、非数组、空数组一律视为「无选中」→ 不展示任何卡片。
	* 有非空 string[] 时按该顺序展示：**仅渲染能在 `cards` 里命中的**；命中不到的 id（例如磁盘残留的
	* 旧店铺 / 已删资源）直接剔除，不再回退成「数字占位卡」。磁盘侧由宿主（如 PisellReservation）
	* 水合后清洗并回写 localStorage，避免下次继续飘过来。
	*/
	const filterValues = useMemo(() => {
		var _ctx$searchParams;
		const f = (_ctx$searchParams = ctx.searchParams) === null || _ctx$searchParams === void 0 ? void 0 : _ctx$searchParams.filter;
		if (!f || typeof f !== "object" || f === null) return void 0;
		const v = f.values;
		if (v === null || v === void 0 || typeof v !== "object" || Array.isArray(v)) return;
		return v;
	}, [ctx.searchParams]);
	const hasResourceWallFilterKey = filterValues != null && Object.prototype.hasOwnProperty.call(filterValues, filterKey);
	const selectedRaw = hasResourceWallFilterKey ? filterValues[filterKey] : void 0;
	const wallSelectedIds = useMemo(() => {
		if (!hasResourceWallFilterKey) return [];
		if (!Array.isArray(selectedRaw)) return [];
		const seen = /* @__PURE__ */ new Set();
		const out = [];
		for (const x of selectedRaw) {
			const t = String(x).trim();
			if (!t || seen.has(t)) continue;
			seen.add(t);
			out.push(t);
		}
		return out;
	}, [hasResourceWallFilterKey, selectedRaw]);
	const cards = cardsProp !== null && cardsProp !== void 0 ? cardsProp : [];
	/** 按 resourceId 建表，便于按筛选 id 顺序 O(1) 取卡 */
	const cardByResourceId = useMemo(() => {
		const m = /* @__PURE__ */ new Map();
		for (const c of cards) m.set(String(c.resourceId), c);
		return m;
	}, [cards]);
	/**
	* 仅渲染「筛选 id 序列 ∩ cards」；缺数据的 id 直接跳过。
	* 若当前 `searchParams.sort` 指向状态列（见 statusSortFieldKeys），在筛选顺序上做稳定排序：
	* desc → 占用态在前；asc → 空闲态在前。
	*/
	const visibleCards = useMemo(() => {
		var _ctx$searchParams2;
		if (!wallSelectedIds.length) return [];
		const result = [];
		for (const id of wallSelectedIds) {
			const hit = cardByResourceId.get(String(id));
			if (hit) result.push(hit);
		}
		const parsed = parseRecordBoardToolbarSortParam((_ctx$searchParams2 = ctx.searchParams) === null || _ctx$searchParams2 === void 0 ? void 0 : _ctx$searchParams2.sort);
		if (parsed && matchesResourceWallStatusSortField(parsed.field, statusSortFieldKeys)) {
			const dir = parsed.dir;
			const indexed = result.map((card, idx) => ({
				card,
				idx
			}));
			indexed.sort((a, b) => {
				const ra = venueWallOccupiedSortRank(a.card);
				const rb = venueWallOccupiedSortRank(b.card);
				if (ra !== rb) return dir === "asc" ? ra - rb : rb - ra;
				return a.idx - b.idx;
			});
			return indexed.map((x) => x.card);
		}
		return result;
	}, [
		cardByResourceId,
		wallSelectedIds,
		(_ctx$searchParams3 = ctx.searchParams) === null || _ctx$searchParams3 === void 0 ? void 0 : _ctx$searchParams3.sort,
		statusSortFieldKeys
	]);
	/** 顶栏时钟 / 日期展示 */
	const [now, setNow] = useState(() => /* @__PURE__ */ new Date());
	useEffect(() => {
		const id = window.setInterval(() => setNow(/* @__PURE__ */ new Date()), 1e3);
		return () => window.clearInterval(id);
	}, []);
	/** 浅深主题：双受控（props + onChange）时完全由外部驱动，否则用内部 state */
	const [internalAppearanceMode, setInternalAppearanceMode] = useState("light");
	const appearanceModeControlled = appearanceModeProp !== void 0 && onAppearanceModeChange != null;
	const appearanceMode = appearanceModeControlled ? appearanceModeProp : internalAppearanceMode;
	const setAppearanceMode = useCallback((m) => {
		onAppearanceModeChange === null || onAppearanceModeChange === void 0 || onAppearanceModeChange(m);
		if (!appearanceModeControlled) setInternalAppearanceMode(m);
	}, [appearanceModeControlled, onAppearanceModeChange]);
	const [showControlPanel, setShowControlPanel] = useState(false);
	const closeControlPanel = useCallback(() => {
		setShowControlPanel(false);
	}, []);
	const [currentPage, setCurrentPage] = useState(0);
	const [pseudoFullscreen, setPseudoFullscreen] = useState(readStoredPseudoFullscreen);
	const togglePseudoFullscreen = useCallback(() => {
		setPseudoFullscreen((prev) => {
			const next = !prev;
			persistPseudoFullscreen(next);
			return next;
		});
	}, []);
	const shellRef = useRef(null);
	/** 伪全屏：给 body 挂类名，配合 less 撑满视口且压住部分宿主布局 */
	useEffect(() => {
		const cls = "pisell-resource-wall-fixed-viewport";
		if (typeof document === "undefined") return;
		if (pseudoFullscreen) document.body.classList.add(cls);
		else document.body.classList.remove(cls);
		return () => {
			document.body.classList.remove(cls);
		};
	}, [pseudoFullscreen]);
	/** 布局持久化：有 `onResourceWallLayoutChange` 时为受控；否则本地默认 + `setLayoutState` 补丁 */
	const layoutPersisted = onResourceWallLayoutChange != null;
	const [internalLayout, setInternalLayout] = useState(() => _objectSpread2({}, DEFAULT_RESOURCE_WALL_LAYOUT_PERSIST));
	const layoutState = layoutPersisted ? _objectSpread2(_objectSpread2({}, DEFAULT_RESOURCE_WALL_LAYOUT_PERSIST), resourceWallLayoutProp !== null && resourceWallLayoutProp !== void 0 ? resourceWallLayoutProp : {}) : internalLayout;
	const setLayoutState = useCallback((patch) => {
		if (layoutPersisted) onResourceWallLayoutChange(_objectSpread2(_objectSpread2(_objectSpread2({}, DEFAULT_RESOURCE_WALL_LAYOUT_PERSIST), resourceWallLayoutProp !== null && resourceWallLayoutProp !== void 0 ? resourceWallLayoutProp : {}), patch));
		else setInternalLayout((prev) => _objectSpread2(_objectSpread2(_objectSpread2({}, DEFAULT_RESOURCE_WALL_LAYOUT_PERSIST), prev), patch));
	}, [
		layoutPersisted,
		resourceWallLayoutProp,
		onResourceWallLayoutChange
	]);
	const { layoutKey, customCols, customRows, pageDurationSec, boardingSoonBeforeMin, heroMaxWidthRatio } = layoutState;
	const layoutPresetsWithI18n = useMemo(() => LAYOUT_PRESETS.map((p) => _objectSpread2(_objectSpread2({}, p), {}, { label: p.key === "custom" ? getText("pisell-resource-wall-layout-custom") : p.label })), [getCurrentLocale()]);
	/** 当前外观模式下的槽位：占用/空闲底色 + 六态覆盖（含未持久化时的 props 回退） */
	const modeSlot = (_appearanceTheme$appe = appearanceTheme[appearanceMode]) !== null && _appearanceTheme$appe !== void 0 ? _appearanceTheme$appe : {};
	const occupiedCardColor = modeSlot.occupiedCardColor != null && modeSlot.occupiedCardColor !== "" ? modeSlot.occupiedCardColor : DEFAULT_OCCUPIED;
	const availableCardColor = modeSlot.availableCardColor != null && modeSlot.availableCardColor !== "" ? modeSlot.availableCardColor : DEFAULT_AVAILABLE;
	const modeToneOverrides = modeSlot.statusToneOverrides;
	const statusToneOverrides = modeToneOverrides != null && Object.keys(modeToneOverrides).length > 0 ? modeToneOverrides : statusToneOverridesProp !== void 0 ? statusToneOverridesProp : localToneOverrides;
	/** 解析当前选中的预设（含 custom 行列钳位） */
	const selectedLayout = useMemo(() => {
		var _layoutPresetsWithI;
		if (layoutKey === "custom") return {
			key: "custom",
			label: getText("pisell-resource-wall-layout-custom"),
			cols: Math.max(1, Math.min(6, customCols)),
			rows: Math.max(1, Math.min(6, customRows))
		};
		return (_layoutPresetsWithI = layoutPresetsWithI18n.find((p) => p.key === layoutKey)) !== null && _layoutPresetsWithI !== void 0 ? _layoutPresetsWithI : layoutPresetsWithI18n[2];
	}, [
		layoutKey,
		customCols,
		customRows,
		layoutPresetsWithI18n
	]);
	const pageCapacity = selectedLayout.cols * selectedLayout.rows;
	/** 按单页容量切分可见卡，用于轮播与指示条 */
	const pagedGroups = useMemo(() => {
		const chunks = [];
		for (let i = 0; i < visibleCards.length; i += pageCapacity) chunks.push(visibleCards.slice(i, i + pageCapacity));
		return chunks;
	}, [visibleCards, pageCapacity]);
	const totalPages = Math.max(1, pagedGroups.length);
	/** 当前页要渲染的卡；无分页时退化为首屏 capacity 张 */
	const renderCards = (_pagedGroups$currentP = pagedGroups[currentPage]) !== null && _pagedGroups$currentP !== void 0 ? _pagedGroups$currentP : visibleCards.slice(0, pageCapacity);
	/** 控制台展示与顶栏一致的当前页 / 总页（1-based 在文案 replace 时处理） */
	const controlCarouselPager = useMemo(() => ({
		currentPage,
		totalPages
	}), [currentPage, totalPages]);
	/** 总页数变小时收回当前页索引，避免越界 */
	useEffect(() => {
		setCurrentPage((p) => totalPages > 0 ? Math.min(p, totalPages - 1) : 0);
	}, [totalPages]);
	/** 多页时按 `pageDurationSec` 自动轮播当前页 */
	useEffect(() => {
		if (totalPages <= 1) {
			setCurrentPage(0);
			return;
		}
		const ms = Math.max(3, pageDurationSec) * 1e3;
		const timer = window.setInterval(() => {
			setCurrentPage((p) => (p + 1) % totalPages);
		}, ms);
		return () => window.clearInterval(timer);
	}, [totalPages, pageDurationSec]);
	/** 网格容量或可见卡数量变化时回到第一页 */
	useEffect(() => {
		setCurrentPage(0);
	}, [pageCapacity, visibleCards.length]);
	/**
	* 写入 `filter.values[filterKey]`；`ids` 可为 `[]`（大屏不展示）。
	* 宿主合并 `onSearch` 时请保留该键；删掉键时本视图同样按「无选中」处理（不展示）。
	*/
	const mergeFilterResourceIds = useCallback((ids) => {
		var _ctx$searchParams4, _filterValue$values, _ctx$onSearch;
		const sp = (_ctx$searchParams4 = ctx.searchParams) !== null && _ctx$searchParams4 !== void 0 ? _ctx$searchParams4 : {};
		const filterValue = sp[FILTER_PARAMS_FIELD];
		const currentValues = (_filterValue$values = filterValue === null || filterValue === void 0 ? void 0 : filterValue.values) !== null && _filterValue$values !== void 0 ? _filterValue$values : {};
		const nextFilter = _objectSpread2(_objectSpread2({}, filterValue), {}, { values: _objectSpread2(_objectSpread2({}, currentValues), {}, { [filterKey]: ids }) });
		(_ctx$onSearch = ctx.onSearch) === null || _ctx$onSearch === void 0 || _ctx$onSearch.call(ctx, _objectSpread2(_objectSpread2({}, sp), {}, { [FILTER_PARAMS_FIELD]: nextFilter }));
	}, [ctx, filterKey]);
	/** 控制台「应用」：同步筛选 id、布局持久化、当前外观槽位下的占用/空闲色与六态覆盖 */
	const handleControlApply = useCallback((payload) => {
		mergeFilterResourceIds(payload.resourceIds);
		setLayoutState({
			layoutKey: payload.layoutKey,
			customCols: payload.customCols,
			customRows: payload.customRows,
			pageDurationSec: payload.pageDurationSec,
			boardingSoonBeforeMin: payload.boardingSoonBeforeMin,
			heroMaxWidthRatio: payload.heroMaxWidthRatio
		});
		const nextSlot = _objectSpread2(_objectSpread2({}, appearanceTheme[appearanceMode]), {}, {
			occupiedCardColor: payload.occupiedCardColor,
			availableCardColor: payload.availableCardColor,
			statusToneOverrides: payload.statusToneOverrides
		});
		persistAppearanceTheme(_objectSpread2(_objectSpread2({}, appearanceTheme), {}, { [appearanceMode]: nextSlot }));
		emitToneOverrides(payload.statusToneOverrides);
	}, [
		mergeFilterResourceIds,
		emitToneOverrides,
		appearanceTheme,
		appearanceMode,
		persistAppearanceTheme,
		setLayoutState
	]);
	/** 注入 i18n 后的完整六态表（含控制台覆盖），下发各 {@link VenueWallCard} */
	const statusToneMap = useMemo(() => getVenueWallStatusToneMap(statusToneOverrides), [statusToneOverrides]);
	/** 浅色态与历史实现一致（扁平顶栏 + 灰底内容区）；深色仅微调背景与顶栏，不套「卡片套卡片」大圆角壳 */
	const isDark = appearanceMode === "dark";
	const pageBg = isDark ? "#0f172a" : "#f5f7fb";
	const headerBg = isDark ? "#1e293b" : "#ffffff";
	const headerBorder = isDark ? "1px solid #334155" : "1px solid #e2e8f0";
	const clockColor = isDark ? "#f1f5f9" : "#0f172a";
	const mutedText = isDark ? "#94a3b8" : "#64748b";
	const toolbarBtnBorder = isDark ? "1px solid #475569" : "1px solid #e2e8f0";
	const toolbarBtnBg = isDark ? "#334155" : "#ffffff";
	const toolbarBtnBgActive = isDark ? "#475569" : "#f1f5f9";
	const countdownSec = Math.max(3, pageDurationSec);
	const shell = /* @__PURE__ */ React.createElement("div", {
		ref: shellRef,
		className: `pisell-resource-wall-shell${className ? ` ${className}` : ""}`,
		style: _objectSpread2({
			flex: 1,
			minHeight: 0,
			display: "flex",
			flexDirection: "column",
			overflow: "hidden",
			background: pageBg,
			color: clockColor
		}, style)
	}, /* @__PURE__ */ React.createElement(ResourceWallViewportToolbar, {
		now,
		appearanceMode,
		onAppearanceModeChange: setAppearanceMode,
		pseudoFullscreen,
		onTogglePseudoFullscreen: togglePseudoFullscreen,
		onOpenControlPanel: () => setShowControlPanel(true),
		headerBorder,
		headerBg,
		clockColor,
		mutedText,
		toolbarBtnBorder,
		toolbarBtnBg,
		toolbarBtnBgActive
	}), /* @__PURE__ */ React.createElement("div", { style: {
		flex: 1,
		minHeight: 0,
		padding: 12,
		display: "flex",
		flexDirection: "column",
		gap: 10
	} }, totalPages > 1 ? /* @__PURE__ */ React.createElement("div", { style: {
		flexShrink: 0,
		display: "flex",
		alignItems: "center",
		gap: 12
	} }, /* @__PURE__ */ React.createElement("div", { style: {
		fontSize: 13,
		fontWeight: 600,
		color: mutedText,
		whiteSpace: "nowrap"
	} }, getText("pisell-resource-wall-page-indicator").replace("{cur}", String(currentPage + 1)).replace("{total}", String(totalPages))), /* @__PURE__ */ React.createElement("div", { style: {
		flex: 1,
		height: 4,
		borderRadius: 2,
		overflow: "hidden",
		background: isDark ? "rgba(255,255,255,0.1)" : "rgba(15,23,42,0.08)"
	} }, /* @__PURE__ */ React.createElement("div", {
		key: `${currentPage}-${countdownSec}`,
		className: "pisell-resource-wall-page-countdown-bar",
		style: {
			height: "100%",
			width: "100%",
			background: occupiedCardColor,
			animationDuration: `${countdownSec}s`
		}
	}))) : null, /* @__PURE__ */ React.createElement("div", { style: {
		flex: 1,
		minHeight: 0,
		height: "100%",
		display: "grid",
		gap: 16,
		gridTemplateColumns: `repeat(${selectedLayout.cols}, minmax(0, 1fr))`,
		gridTemplateRows: `repeat(${selectedLayout.rows}, minmax(0, 1fr))`
	} }, renderCards.map((card) => /* @__PURE__ */ React.createElement(VenueWallCard, {
		key: String(card.resourceId),
		card,
		wallNowMs: now.getTime(),
		boardingSoonBeforeMin,
		occupiedCardColor,
		availableCardColor,
		heroMaxWidthRatio,
		statusToneMap,
		appearance: appearanceMode
	})))), /* @__PURE__ */ React.createElement(ResourceWallControlPanel, {
		open: showControlPanel,
		onClose: closeControlPanel,
		isDark,
		layoutPresets: layoutPresetsWithI18n,
		layoutKey,
		customCols,
		customRows,
		pageDurationSec,
		occupiedCardColor,
		availableCardColor,
		boardingSoonBeforeMin,
		statusToneOverrides,
		selectedResourceIds: wallSelectedIds,
		carouselPager: controlCarouselPager,
		heroMaxWidthRatio,
		onApply: handleControlApply
	}));
	/** 控制台打开时仍挂载 shell，避免整页 Spin 卸载弹层导致草稿丢失（全选后无法勾掉） */
	if (loading && !showControlPanel) return /* @__PURE__ */ React.createElement("div", {
		className,
		style: _objectSpread2({
			flex: 1,
			minHeight: 0,
			display: "flex",
			alignItems: "center",
			justifyContent: "center",
			background: pageBg
		}, style)
	}, /* @__PURE__ */ React.createElement(Spin, null));
	return shell;
};
//#endregion
export { DEFAULT_RESOURCE_WALL_FILTER_FIELD_KEY, PisellRecordBoardResourceWallView };
