///|
// Global state management
extern "js" fn init_readline() -> Unit =
  #|function() {
  #|  if (!globalThis.readlineState) {
  #|    // Detect environment: browser vs Node.js
  #|    const isBrowser = typeof window !== 'undefined' && typeof process === 'undefined';
  #|    
  #|    if (isBrowser) {
  #|      // Browser environment - use prompt()
  #|      globalThis.readlineState = {
  #|        isBrowser: true,
  #|        questionCb: null
  #|      };
  #|    } else {
  #|      // Node.js environment - use stdin/stdout with raw mode
  #|      const { stdin: input, stdout: output } = process;
  #|      input.setEncoding('utf8');
  #|      input.setRawMode(true);
  #|      
  #|      globalThis.readlineState = {
  #|        isBrowser: false,
  #|        questionCb: null,
  #|        currentLine: '',
  #|        cursorPos: 0,
  #|        history: [],
  #|        historyIndex: -1,
  #|        input,
  #|        output,
  #|        prompt: ''
  #|      };
  #|      
  #|      // Handle key input
  #|      input.on('data', chunk => {
  #|        const state = globalThis.readlineState;
  #|        if (!state.questionCb) return;
  #|        
  #|        const data = chunk.toString();
  #|        
  #|        // Handle special keys
  #|        if (data === '\u0003') { // Ctrl+C
  #|          process.exit(0);
  #|        } else if (data === '\r' || data === '\n') { // Enter
  #|          state.output.write('\n');
  #|          const line = state.currentLine;
  #|          if (line.trim()) {
  #|            state.history.push(line);
  #|          }
  #|          state.currentLine = '';
  #|          state.cursorPos = 0;
  #|          state.historyIndex = -1;
  #|          const cb = state.questionCb;
  #|          state.questionCb = null;
  #|          cb(line);
  #|        } else if (data === '\u007f' || data === '\b') { // Backspace
  #|          if (state.cursorPos > 0) {
  #|            state.currentLine = state.currentLine.slice(0, state.cursorPos - 1) + 
  #|                               state.currentLine.slice(state.cursorPos);
  #|            state.cursorPos--;
  #|            state.output.write('\b \b');
  #|            // Redraw line from cursor position
  #|            const remaining = state.currentLine.slice(state.cursorPos);
  #|            if (remaining) {
  #|              state.output.write(remaining + ' ');
  #|              state.output.write('\b'.repeat(remaining.length + 1));
  #|            }
  #|          }
  #|        } else if (data === '\u001b[A') { // Up arrow
  #|          if (state.history.length > 0) {
  #|            if (state.historyIndex === -1) {
  #|              state.historyIndex = state.history.length - 1;
  #|            } else if (state.historyIndex > 0) {
  #|              state.historyIndex--;
  #|            }
  #|            const historyLine = state.history[state.historyIndex];
  #|            // Clear current line
  #|            state.output.write('\r' + state.prompt + ' '.repeat(state.currentLine.length) + '\r' + state.prompt);
  #|            state.currentLine = historyLine;
  #|            state.cursorPos = historyLine.length;
  #|            state.output.write(historyLine);
  #|          }
  #|        } else if (data === '\u001b[B') { // Down arrow
  #|          if (state.historyIndex !== -1) {
  #|            if (state.historyIndex < state.history.length - 1) {
  #|              state.historyIndex++;
  #|              const historyLine = state.history[state.historyIndex];
  #|              // Clear current line
  #|              state.output.write('\r' + state.prompt + ' '.repeat(state.currentLine.length) + '\r' + state.prompt);
  #|              state.currentLine = historyLine;
  #|              state.cursorPos = historyLine.length;
  #|              state.output.write(historyLine);
  #|            } else {
  #|              state.historyIndex = -1;
  #|              // Clear current line
  #|              state.output.write('\r' + state.prompt + ' '.repeat(state.currentLine.length) + '\r' + state.prompt);
  #|              state.currentLine = '';
  #|              state.cursorPos = 0;
  #|            }
  #|          }
  #|        } else if (data === '\u001b[C') { // Right arrow
  #|          if (state.cursorPos < state.currentLine.length) {
  #|            state.cursorPos++;
  #|            state.output.write('\u001b[C');
  #|          }
  #|        } else if (data === '\u001b[D') { // Left arrow
  #|          if (state.cursorPos > 0) {
  #|            state.cursorPos--;
  #|            state.output.write('\u001b[D');
  #|          }
  #|        } else if (data.charCodeAt(0) >= 32) { // Printable characters
  #|          state.currentLine = state.currentLine.slice(0, state.cursorPos) + 
  #|                             data + 
  #|                             state.currentLine.slice(state.cursorPos);
  #|          state.cursorPos += data.length;
  #|          state.output.write(data);
  #|          // Redraw remaining characters
  #|          const remaining = state.currentLine.slice(state.cursorPos);
  #|          if (remaining) {
  #|            state.output.write(remaining);
  #|            state.output.write('\b'.repeat(remaining.length));
  #|          }
  #|        }
  #|      });
  #|    }
  #|  }
  #|}

///|
extern "js" fn question_ffi(
  question : String,
  callback : (String) -> Unit,
) -> Unit =
  #|function(question, callback) {
  #|  if (!globalThis.readlineState) {
  #|    throw new Error('Readline not initialized');
  #|  }
  #|  const state = globalThis.readlineState;
  #|  
  #|  if (state.isBrowser) {
  #|    // Browser environment - use prompt()
  #|    const result = prompt(question);
  #|    callback(result || '');
  #|  } else {
  #|    // Node.js environment - use stdin/stdout with line editing
  #|    state.prompt = question;
  #|    state.output.write(question);
  #|    state.questionCb = callback;
  #|    state.currentLine = '';
  #|    state.cursorPos = 0;
  #|    state.historyIndex = -1;
  #|  }
  #|}

///|
extern "js" fn close_ffi() -> Unit =
  #|function() {
  #|  if (globalThis.readlineState) {
  #|    const state = globalThis.readlineState;
  #|    
  #|    if (state.isBrowser) {
  #|      // Browser environment - simple cleanup
  #|      state.questionCb = null;
  #|    } else {
  #|      // Node.js environment - full cleanup
  #|      state.questionCb = null;
  #|      state.currentLine = '';
  #|      state.cursorPos = 0;
  #|      state.input.setRawMode(false);
  #|      state.input.removeAllListeners('data');
  #|      state.input.pause();
  #|    }
  #|    
  #|    // Clean up global state
  #|    delete globalThis.readlineState;
  #|  }
  #|}

///|
fn wait_for_completion() -> Unit {
  // No-op for JS version as it's already async
}