/**
 * tui-walkthrough-input.test.ts — 입력 편집 키바인드 전체 검증
 *
 * 프롬프트 textarea의 모든 편집 단축키를 한 번씩 누름:
 * - 커서 이동: left, right, up, down, home, end
 * - ctrl+커서: ctrl+a (line home), ctrl+e (line end), ctrl+b (left), ctrl+f (right)
 * - 단어 이동: alt+f, alt+b, ctrl+left, ctrl+right
 * - 선택: shift+방향키, ctrl+shift+a/e
 * - 삭제: backspace, delete, ctrl+k, ctrl+u, ctrl+w, ctrl+d
 * - 단어 삭제: alt+d, ctrl+backspace
 * - 클리어: ctrl+c
 * - 입력: 일반 텍스트, enter, newline(shift+enter)
 * - undo/redo: ctrl+-, ctrl+z (win32), ctrl+.
 */

import { describe, expect, test, beforeAll, afterAll } from "bun:test"
import { tmpdir, disposeAllInstances } from "../fixture/fixture"
import * as Log from "@saeeol/core/util/log"
import { Flag } from "@saeeol/core/flag/flag"
import { TuiDriver, Key } from "./tui-walkthrough-driver"

void Log.init({ print: false })

describe("TUI walkthrough: input editing", () => {
	let driver: TuiDriver
	let tmp: Awaited<ReturnType<typeof tmpdir>>

	beforeAll(async () => {
		tmp = await tmpdir({ git: true, config: {} })
		Flag.SAEEOL_EXPERIMENTAL_HTTPAPI = false
		driver = new TuiDriver(tmp.path)
		await driver.wait(6000)
	})

	afterAll(async () => {
		await driver.saveReport(".tui-input-report.txt")
		await driver.kill()
		await disposeAllInstances()
		Flag.SAEEOL_EXPERIMENTAL_HTTPAPI = true
	})

	// ── 기본 입력 ──

	test("typing: regular text input", async () => {
		driver.write("hello world this is a test")
		await driver.wait(500)
		driver.snapshot("input-typed")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 커서 이동 ──

	test("cursor: left/right arrow", async () => {
		driver.write(Key.left)
		await driver.wait(100)
		driver.write(Key.left)
		await driver.wait(100)
		driver.write(Key.right)
		await driver.wait(100)
		driver.snapshot("input-cursor-lr")
		expect(driver.errors()).toHaveLength(0)
	})

	test("cursor: up/down arrow", async () => {
		driver.write(Key.up)
		await driver.wait(100)
		driver.write(Key.down)
		await driver.wait(100)
		driver.snapshot("input-cursor-ud")
		expect(driver.errors()).toHaveLength(0)
	})

	test("cursor: home/end", async () => {
		driver.write(Key.home)
		await driver.wait(100)
		driver.write(Key.end)
		await driver.wait(100)
		driver.snapshot("input-cursor-home-end")
		expect(driver.errors()).toHaveLength(0)
	})

	test("cursor: ctrl+a (line home)", async () => {
		driver.write(Key.ctrlA)
		await driver.wait(200)
		driver.snapshot("input-ctrl-a")
		expect(driver.errors()).toHaveLength(0)
	})

	test("cursor: ctrl+e (line end)", async () => {
		driver.write(Key.ctrlE)
		await driver.wait(200)
		driver.snapshot("input-ctrl-e")
		expect(driver.errors()).toHaveLength(0)
	})

	test("cursor: ctrl+b (left)", async () => {
		driver.write(Key.ctrlB)
		await driver.wait(100)
		driver.write(Key.ctrlB)
		await driver.wait(100)
		driver.snapshot("input-ctrl-b")
		expect(driver.errors()).toHaveLength(0)
	})

	test("cursor: ctrl+f (right)", async () => {
		driver.write(Key.ctrlF)
		await driver.wait(100)
		driver.write(Key.ctrlF)
		await driver.wait(100)
		driver.snapshot("input-ctrl-f")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 단어 이동 ──

	test("word: alt+f (forward)", async () => {
		driver.write(Key.altF)
		await driver.wait(200)
		driver.snapshot("input-alt-f")
		expect(driver.errors()).toHaveLength(0)
	})

	test("word: alt+b (backward)", async () => {
		driver.write(Key.altB)
		await driver.wait(200)
		driver.snapshot("input-alt-b")
		expect(driver.errors()).toHaveLength(0)
	})

	test("word: ctrl+left", async () => {
		driver.write(Key.ctrlLeft)
		await driver.wait(200)
		driver.snapshot("input-ctrl-left")
		expect(driver.errors()).toHaveLength(0)
	})

	test("word: ctrl+right", async () => {
		driver.write(Key.ctrlRight)
		await driver.wait(200)
		driver.snapshot("input-ctrl-right")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 선택 ──

	test("select: shift+left/right", async () => {
		driver.write(Key.shiftLeft)
		await driver.wait(100)
		driver.write(Key.shiftLeft)
		await driver.wait(100)
		driver.write(Key.shiftRight)
		await driver.wait(100)
		driver.snapshot("input-select-lr")
		expect(driver.errors()).toHaveLength(0)
	})

	test("select: shift+up/down", async () => {
		driver.write(Key.shiftUp)
		await driver.wait(100)
		driver.write(Key.shiftDown)
		await driver.wait(100)
		driver.snapshot("input-select-ud")
		expect(driver.errors()).toHaveLength(0)
	})

	test("select: alt+a (visual line home)", async () => {
		driver.write(Key.altA)
		await driver.wait(200)
		driver.snapshot("input-alt-a")
		expect(driver.errors()).toHaveLength(0)
	})

	test("select: alt+e (visual line end)", async () => {
		driver.write(Key.altE)
		await driver.wait(200)
		driver.snapshot("input-alt-e")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 삭제 ──

	test("delete: backspace", async () => {
		driver.write(Key.backspace)
		await driver.wait(200)
		driver.snapshot("input-backspace")
		expect(driver.errors()).toHaveLength(0)
	})

	test("delete: delete key", async () => {
		driver.write(Key.delete)
		await driver.wait(200)
		driver.snapshot("input-delete")
		expect(driver.errors()).toHaveLength(0)
	})

	test("delete: ctrl+k (to line end)", async () => {
		driver.write(Key.ctrlK)
		await driver.wait(200)
		driver.snapshot("input-ctrl-k")
		expect(driver.errors()).toHaveLength(0)
	})

	test("delete: ctrl+u (to line start)", async () => {
		driver.write(Key.ctrlU)
		await driver.wait(200)
		driver.snapshot("input-ctrl-u")
		expect(driver.errors()).toHaveLength(0)
	})

	test("delete: ctrl+w (word backward)", async () => {
		// 텍스트 다시 입력
		driver.write("another test phrase")
		await driver.wait(200)
		driver.write(Key.ctrlW)
		await driver.wait(200)
		driver.snapshot("input-ctrl-w")
		expect(driver.errors()).toHaveLength(0)
	})

	test("delete: ctrl+d (char delete)", async () => {
		driver.write(Key.ctrlD)
		await driver.wait(200)
		driver.snapshot("input-ctrl-d")
		expect(driver.errors()).toHaveLength(0)
	})

	test("delete: alt+d (word forward)", async () => {
		driver.write("word1 word2 word3")
		await driver.wait(200)
		driver.write(Key.altD)
		await driver.wait(200)
		driver.snapshot("input-alt-d")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 클리어 / 언두 ──

	test("clear: ctrl+c clears input", async () => {
		driver.write("should be cleared")
		await driver.wait(200)
		driver.write(Key.ctrlC)
		await driver.wait(300)
		driver.snapshot("input-clear-ctrl-c")
		expect(driver.errors()).toHaveLength(0)
	})

	test("undo: ctrl+-", async () => {
		driver.write("typed text")
		await driver.wait(200)
		// ctrl+- 는 터미널에서 \x1f
		driver.write("\x1f")
		await driver.wait(300)
		driver.snapshot("input-undo-ctrl-minus")
		expect(driver.errors()).toHaveLength(0)
	})

	test("redo: ctrl+.", async () => {
		driver.write(Key.ctrlV) // ctrl+. — 재할당 불가하므로 대략적
		await driver.wait(200)
		driver.snapshot("input-redo")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 새 텍스트 입력 후 엔터 ──

	test("submit: enter key (does not crash)", async () => {
		driver.write(Key.ctrlC) // 클리어
		await driver.wait(200)
		driver.write("test message")
		await driver.wait(200)
		// 엔터 — 실제 전송은 안 됨 (LLM 서버 죽음), 크래시만 안 하면 됨
		driver.write(Key.enter)
		await driver.wait(1000)
		driver.snapshot("input-submit")
		expect(driver.errors()).toHaveLength(0)
	})

	// ── 정리 ──

	test("cleanup: clear and verify", async () => {
		driver.write(Key.ctrlC)
		await driver.wait(300)
		driver.snapshot("input-cleanup")
		expect(driver.errors()).toHaveLength(0)
	})
})
