"""Asynchronous input reader for non-blocking user input."""

import queue
import sys
import threading
from typing import Optional


class InputReader:
    """Thread-based asynchronous input reader.

    Reads from stdin in a background daemon thread and provides
    non-blocking access to user input through a thread-safe queue.
    """

    def __init__(self):
        """Initialize the input reader."""
        self._input_queue: queue.Queue[str] = queue.Queue()
        self._reader_thread: Optional[threading.Thread] = None
        self._stop_flag = threading.Event()
        self._running = False

    def start(self) -> None:
        """Start the background input reader thread."""
        if self._running:
            return

        self._stop_flag.clear()
        self._running = True
        self._reader_thread = threading.Thread(
            target=self._read_loop,
            daemon=True,
            name="InputReader",
        )
        self._reader_thread.start()

    def stop(self) -> None:
        """Stop the background input reader thread."""
        if not self._running:
            return

        self._running = False
        self._stop_flag.set()

        # Note: Thread may be blocked on stdin.readline()
        # It will exit when next input is received or on daemon cleanup

    def _read_loop(self) -> None:
        """Background loop that reads from stdin."""
        # Note: Welcome message is printed by session.py before starting this thread
        while self._running and not self._stop_flag.is_set():
            try:
                # This blocks until a line is available
                # Don't print prompt here - it will interfere with AI output
                line = sys.stdin.readline()

                if line:  # Empty string means EOF
                    stripped = line.rstrip('\n')
                    if stripped:  # Only queue non-empty input
                        self._input_queue.put(stripped)
                else:
                    # EOF reached, stop reading
                    break

            except (EOFError, OSError):
                # Handle EOF or broken pipe
                break
            except Exception as e:
                # Unexpected error, log and continue
                print(f"InputReader error: {e}", file=sys.stderr)
                break

    def get_input(self, timeout: Optional[float] = None) -> Optional[str]:
        """Get pending input from the queue.

        Args:
            timeout: Maximum time to wait for input (None = non-blocking)

        Returns:
            User input string if available, None otherwise
        """
        try:
            if timeout is None:
                # Non-blocking
                return self._input_queue.get_nowait()
            else:
                # Blocking with timeout
                return self._input_queue.get(timeout=timeout)
        except queue.Empty:
            return None

    def has_pending_input(self) -> bool:
        """Check if there is pending input in the queue.

        Returns:
            True if input is available
        """
        return not self._input_queue.empty()

    def clear(self) -> None:
        """Clear all pending input from the queue."""
        while not self._input_queue.empty():
            try:
                self._input_queue.get_nowait()
            except queue.Empty:
                break

    @property
    def is_running(self) -> bool:
        """Check if the reader thread is running.

        Returns:
            True if the reader is active
        """
        return self._running
