import type { Terminal } from "./terminal.js";

/** Logical cursor row/col extracted from overlay-stripped rendered lines */
export type HardwareCursorLogicalPos = { row: number; col: number };

/**
 * Move the terminal cursor so IME anchors to the rendered logical cursor (`CURSOR_MARKER`).
 *
 * Purpose: IME placement stays testable without the differential render pipeline.
 *
 * Consumer: `TUI.doRender` after marker strip (`extractCursorPosition`).
 *
 * Returns the next logical hardware cursor row used for incremental cursor-move math.
 */
export function syncHardwareCursorForIME(
	terminal: Pick<Terminal, "hideCursor" | "showCursor" | "write">,
	options: {
		cursorPos: HardwareCursorLogicalPos | null;
		totalLines: number;
		hardwareCursorRow: number;
		showHardwareCursor: boolean;
	},
): number {
	const { cursorPos, totalLines, hardwareCursorRow, showHardwareCursor } =
		options;

	if (!cursorPos || totalLines <= 0) {
		terminal.hideCursor();
		return hardwareCursorRow;
	}

	const targetRow = Math.max(0, Math.min(cursorPos.row, totalLines - 1));
	const targetCol = Math.max(0, cursorPos.col);

	const rowDelta = targetRow - hardwareCursorRow;
	let buffer = "";
	if (rowDelta > 0) {
		buffer += `\x1b[${rowDelta}B`;
	} else if (rowDelta < 0) {
		buffer += `\x1b[${-rowDelta}A`;
	}
	buffer += `\x1b[${targetCol + 1}G`;

	if (buffer) {
		terminal.write(buffer);
	}

	if (showHardwareCursor) {
		terminal.showCursor();
	} else {
		terminal.hideCursor();
	}

	return targetRow;
}
