/**
 * Pure helper for parsing terminal cell size query responses.
 *
 * Terminal responds to `CSI 16 t` with: `CSI 6 ; <heightPx> ; <widthPx> t`
 *
 * Extracting this as a standalone function avoids the ad-hoc inline regex in
 * the TUI input handler and makes the parsing testable in isolation.
 */

const CELL_SIZE_PATTERN = /\x1b\[6;(\d+);(\d+)t/;

/**
 * Parse a cell size response from a raw input chunk.
 * Returns pixel dimensions, or null if the chunk contains no valid response.
 * Dimensions are validated to be in the range [1, 10000].
 */
export function parseCellSizeResponse(
	chunk: string,
): { height: number; width: number } | null {
	const match = chunk.match(CELL_SIZE_PATTERN);
	if (!match) return null;

	const height = parseInt(match[1]!, 10);
	const width = parseInt(match[2]!, 10);

	if (height <= 0 || height > 10000 || width <= 0 || width > 10000) return null;

	return { height, width };
}

/**
 * Remove the cell size response sequence from a string, returning the
 * remainder so it can be forwarded as normal keyboard input.
 */
export function stripCellSizeResponse(chunk: string): string {
	return chunk.replace(CELL_SIZE_PATTERN, "");
}

/**
 * Result of splitting stdin while a CSI 16 cell-size query response may arrive.
 *
 * Purpose: encapsulate buffering policy (bare Escape, incomplete CSI tails) while
 * keeping `parseCellSizeResponse` / `stripCellSizeResponse` reusable as pure parsers.
 *
 * Consumer: `TUI.handleInput` when `cellSizeQueryPending` — applies `cellPixels` via
 * `setCellDimensions` when present, then honours `wait` / `forwardInput`.
 */
export interface DrainCellSizeQueryBufferResult {
	/** Stored buffer state for subsequent chunks */
	nextBuffer: string;
	/**
	 * When the terminal reported pixel cell dimensions — caller applies once (`setCellDimensions`)
	 * before `invalidate` / `requestRender`.
	 */
	cellPixels?: { widthPx: number; heightPx: number };
	/**
	 * When true — no keystrokes forwarded yet (partial escape still accumulating).
	 */
	wait: boolean;
	/** Keyboard input unlocked from the pending buffer once `wait` is false */
	forwardInput: string;
}

/**
 * Consume stdin buffered after CSI 16 t was sent: extract optional pixel cell size,
 * bare Escape forwarding, incomplete sequence detection (legacy `parseCellSizeResponse`).
 */
export function drainCellSizeQueryBuffer(
	buffer: string,
): DrainCellSizeQueryBufferResult {
	let cellPixels: DrainCellSizeQueryBufferResult["cellPixels"];
	let buf = buffer;

	const parsed = parseCellSizeResponse(buf);
	if (parsed) {
		const { height, width } = parsed;
		cellPixels = { widthPx: width, heightPx: height };
		buf = stripCellSizeResponse(buf);
	}

	if (buf === "\x1b") {
		return {
			nextBuffer: "",
			cellPixels,
			wait: false,
			forwardInput: "\x1b",
		};
	}

	const partialCellSizePattern = /\x1b(\[6?;?[\d;]*)?$/;
	if (partialCellSizePattern.test(buf)) {
		const lastChar = buf.length > 0 ? buf[buf.length - 1]! : "";
		if (!/[a-zA-Z~]/.test(lastChar)) {
			return {
				nextBuffer: buf,
				cellPixels,
				wait: true,
				forwardInput: "",
			};
		}
	}

	return {
		nextBuffer: "",
		cellPixels,
		wait: false,
		forwardInput: buf,
	};
}
