export default class RELP {
	constructor(handlers) {
		this.handlers = handlers
		this.initCommandLine()
	}

	initCommandLine() {
		if (!process.stdin) {
			console.error(
				"Failed to initialize command line: stdin is not available",
			)
			return null
		}

		// Configure line-by-line input mode
		process.stdin.setEncoding("utf8")
		process.stdin.resume()
		process.stdin.setRawMode(true)

		// Buffer to store user input
		this.inputBuffer = ""

		// Show initial prompt
		this.showPrompt()

		// Handle user input
		process.stdin.on("data", (data) => {
			const key = data.toString()

			// Ctrl+C to exit
			if (key === "\u0003") {
				process.exit(0)
			}

			// Enter key
			if (key === "\r" || key === "\n") {
				// Move to a new line
				console.log()

				// Process the command
				const command = this.inputBuffer.trim()
				if (command) {
					this.processCommand(command)
				}

				// Clear the buffer
				this.inputBuffer = ""

				// Show the prompt again
				this.showPrompt()
				return
			}

			// Backspace/Delete
			if (key === "\b" || key === "\x7f") {
				if (this.inputBuffer.length > 0) {
					// Delete a character from the buffer
					this.inputBuffer = this.inputBuffer.slice(0, -1)

					// Update the line in the terminal
					process.stdout.write("\r\x1b[K> " + this.inputBuffer)
				}
				return
			}

			// Normal characters
			if (key.length === 1 && key >= " ") {
				this.inputBuffer += key
				process.stdout.write(key)
			}
		})

		// Intercept console.log to keep the prompt visible
		const originalConsoleLog = console.log
		console.log = (...args) => {
			// Clear the current line
			process.stdout.write("\r\x1b[K")

			// Print the message
			originalConsoleLog(...args)

			// Reprint the prompt and current buffer
			this.showPrompt(false)
		}

		// Do the same with console.error
		const originalConsoleError = console.error
		console.error = (...args) => {
			// Clear the current line
			process.stdout.write("\r\x1b[K")

			// Print the error message
			originalConsoleError(...args)

			// Reprint the prompt and current buffer
			this.showPrompt(false)
		}
	}

	showPrompt(newLine = true) {
		if (newLine) {
			process.stdout.write("\r")
		}
		process.stdout.write("> " + this.inputBuffer)
	}

	processCommand(input) {
		const inputs = input.split(" ")
		const command = inputs[0]
		const args = inputs.slice(1)

		this.inputBuffer = ""

		const commandFn = this.commands.find((relpCommand) => {
			if (relpCommand.cmd === command) {
				return true
			}

			if (Array.isArray(relpCommand.aliases)) {
				return relpCommand.aliases.includes(command)
			}

			return false
		})

		if (!commandFn) {
			console.error(`Command not found: ${command}`)
			return
		}

		// Adapter to maintain compatibility with the original API
		const callback = (result) => {
			if (result) {
				console.log(result)
			}
		}

		try {
			commandFn.fn(callback, ...args)
		} catch (error) {
			console.error(`Error executing command: ${error.message}`)
		}
	}

	commands = [
		{
			cmd: "select",
			aliases: ["s", "sel"],
			fn: (cb, service) => {
				this.handlers.detachAllServicesSTD()
				return this.handlers.attachServiceSTD(service)
			},
		},
		{
			cmd: "reload",
			aliases: ["r"],
			fn: () => {
				this.handlers.reloadService()
			},
		},
		{
			cmd: "exit",
			aliases: ["e"],
			fn: () => {
				process.exit(0)
			},
		},
	]
}
