import assert from "node:assert/strict";
import { describe, it } from "vitest";
import type { Terminal } from "../../terminal.js";
import { CURSOR_MARKER, TUI } from "../../tui.js";
import { Editor, type EditorTheme } from "../editor.js";

function makeTerminal(): Terminal {
	return {
		isTTY: true,
		columns: 80,
		rows: 24,
		kittyProtocolActive: false,
		start() {},
		stop() {},
		drainInput: async () => {},
		write() {},
		moveBy() {},
		hideCursor() {},
		showCursor() {},
		clearLine() {},
		clearFromCursor() {},
		clearScreen() {},
		setTitle() {},
	};
}

const theme: EditorTheme = {
	borderColor: (text) => text,
	selectList: {
		selectedPrefix: (text) => text,
		selectedText: (text) => text,
		description: (text) => text,
		scrollInfo: (text) => text,
		noMatch: (text) => text,
	},
};

describe("Editor", () => {
	it("clears bracketed paste state when focus is lost", () => {
		const editor = new Editor(new TUI(makeTerminal()), theme);
		editor.focused = true;

		editor.handleInput("\x1b[200~partial");
		editor.focused = false;
		editor.focused = true;
		editor.handleInput("hello");

		assert.equal(editor.getText(), "hello");
	});

	it("keeps the hardware cursor marker visible while autocomplete is open", () => {
		const editor = new Editor(new TUI(makeTerminal()), theme);
		editor.focused = true;
		editor.setText("/se");

		(editor as any).autocompleteState = "regular";
		(editor as any).autocompleteList = { render: () => [] };

		const rendered = editor.render(40).join("\n");

		assert.ok(rendered.includes(CURSOR_MARKER));
	});

	it("maps kitty keypad digits to plain editor text", () => {
		const editor = new Editor(new TUI(makeTerminal()), theme);
		editor.focused = true;

		editor.handleInput("\x1b[57404;129u");

		assert.equal(editor.getText(), "5");
	});

	it("does not insert kitty keypad navigation private-use glyphs into the editor", () => {
		const editor = new Editor(new TUI(makeTerminal()), theme);
		editor.focused = true;

		editor.handleInput("\x1b[57419u");

		assert.equal(editor.getText(), "");
	});

	it("redo_restores_after_undo_via_ctrl_shift_z_CSI_u", () => {
		const editor = new Editor(new TUI(makeTerminal()), theme);
		editor.focused = true;
		editor.setText("");

		for (const ch of "hello") {
			editor.handleInput(ch);
		}
		assert.equal(editor.getText(), "hello");

		editor.handleInput("\x1f"); // ctrl+-
		assert.equal(editor.getText(), "");

		editor.handleInput("\x1b[122;6u"); // ctrl+shift+z (Kitty CSI-u)
		assert.equal(editor.getText(), "hello");
	});
});
