import { getAxisCells, getRangeBounds } from "../utils/index.js";
import { useMemo } from "react";
//#region src/components/pisellTimeNavigator/hooks/useTimeAxis.ts
/**
* 时间轴刻度与时间↔像素换算。
*
* 格子拆分策略见 {@link getAxisCells}：当 `range.start` / `range.end` 不在 `stepMinutes` 网格上时，
* 首尾出现宽度按时间比例缩小的 head/tail 格，中间格保持 step 整步并落在网格整点上。
*
* 时间→像素仍是线性映射 `dotOffsetPx + (t - rangeStart) / step × cellSize`，与 head/tail 是否存在无关：
* `dotOffsetPx`（横向 = `cellSize/2`，竖向 = 0）为 rangeStart 在轴内的像素位置；轴两端各保留 `dotOffsetPx`
* 留白以居中 rangeStart / rangeEnd。
*/
function useTimeAxis(options) {
	const { range, stepMinutes, referenceDate, orientation, cellSizePx } = options;
	return useMemo(() => {
		const [rangeStart, rangeEnd] = getRangeBounds(range, referenceDate);
		const safeStep = Math.max(1, stepMinutes);
		const cells = getAxisCells(rangeStart, rangeEnd, safeStep);
		const ticks = cells.map((c) => c.start);
		const cellWidthsPx = cells.map((c) => c.widthMinutes / safeStep * cellSizePx);
		const cellsTotalPx = cellWidthsPx.reduce((s, w) => s + w, 0);
		/**
		* 横向：每格中心为「时间下面的点」，dotOffsetPx = cellSizePx/2，rangeStart / rangeEnd
		* 在轴上分别留 cellSize/2 留白以便居中。
		* 竖向：对齐整点上面的粗线（格顶），dotOffsetPx = 0，无两端留白。
		*/
		const dotOffsetPx = orientation === "vertical" ? 0 : cellSizePx / 2;
		const rawTotalPx = orientation === "horizontal" ? cellsTotalPx + cellSizePx : cellsTotalPx;
		/** 防止异常 range/step 导致轴长爆炸（如竖向出现 33M 高度），上限约 2 天 15 分钟步进 */
		const totalLengthPx = Math.min(rawTotalPx, 5e5);
		/** rangeEnd 在轴上的像素位置；横向 = dotOffsetPx + cellsTotalPx，竖向 = cellsTotalPx */
		const maxOffsetPx = orientation === "vertical" ? cellsTotalPx : dotOffsetPx + cellsTotalPx;
		const timeToOffset = (t) => {
			const px = dotOffsetPx + t.diff(rangeStart) / (60 * 1e3) / safeStep * cellSizePx;
			return Math.max(dotOffsetPx, Math.min(px, maxOffsetPx));
		};
		/**
		* 吸附到最近的「格起点」：
		* head/tail 长度可能小于 step 整步，传统的「按 cellSize 等分四舍五入」无法直接定位 tick；
		* 这里按 ticks 实际像素位置线性扫描求最近邻，ticks 数组通常 ≤ ~200，开销可忽略。
		*/
		const offsetToTime = (offset) => {
			if (ticks.length === 0) return null;
			let bestIdx = 0;
			let bestDist = Infinity;
			for (let i = 0; i < ticks.length; i += 1) {
				const px = timeToOffset(ticks[i]);
				const d = Math.abs(px - offset);
				if (d < bestDist) {
					bestDist = d;
					bestIdx = i;
				}
			}
			return ticks[bestIdx];
		};
		/** 偏移对应连续时间；横向以格点为中心，竖向以格顶为基准 */
		const offsetToTimeContinuous = (offset) => {
			const minutesFromStart = (offset - dotOffsetPx) / cellSizePx * safeStep;
			const t = rangeStart.add(minutesFromStart, "minute");
			if (t.isBefore(rangeStart)) return rangeStart;
			if (t.isAfter(rangeEnd)) return rangeEnd;
			return t;
		};
		return {
			rangeStart,
			rangeEnd,
			ticks,
			cellWidthsPx,
			timeToOffset,
			offsetToTime,
			offsetToTimeContinuous,
			totalLengthPx
		};
	}, [
		range === null || range === void 0 ? void 0 : range.start,
		range === null || range === void 0 ? void 0 : range.end,
		stepMinutes,
		referenceDate.valueOf(),
		orientation,
		cellSizePx
	]);
}
//#endregion
export { useTimeAxis };
