"""Interactive prompt callbacks for terminal_tool integration.

These bridge terminal_tool's interactive prompts (clarify, sudo, approval)
into prompt_toolkit's event loop. Each function takes the HermesCLI instance
as its first argument and uses its state (queues, app reference) to coordinate
with the TUI.
"""

import queue
import time as _time

from hermes_cli.banner import cprint, _DIM, _RST


def clarify_callback(cli, question, choices):
    """Prompt for clarifying question through the TUI.

    Sets up the interactive selection UI, then blocks until the user
    responds. Returns the user's choice or a timeout message.
    """
    from cli import CLI_CONFIG

    timeout = CLI_CONFIG.get("clarify", {}).get("timeout", 120)
    response_queue = queue.Queue()
    is_open_ended = not choices or len(choices) == 0

    cli._clarify_state = {
        "question": question,
        "choices": choices if not is_open_ended else [],
        "selected": 0,
        "response_queue": response_queue,
    }
    cli._clarify_deadline = _time.monotonic() + timeout
    cli._clarify_freetext = is_open_ended

    if hasattr(cli, '_app') and cli._app:
        cli._app.invalidate()

    while True:
        try:
            result = response_queue.get(timeout=1)
            cli._clarify_deadline = 0
            return result
        except queue.Empty:
            remaining = cli._clarify_deadline - _time.monotonic()
            if remaining <= 0:
                break
            if hasattr(cli, '_app') and cli._app:
                cli._app.invalidate()

    cli._clarify_state = None
    cli._clarify_freetext = False
    cli._clarify_deadline = 0
    if hasattr(cli, '_app') and cli._app:
        cli._app.invalidate()
    cprint(f"\n{_DIM}(clarify timed out after {timeout}s — agent will decide){_RST}")
    return (
        "The user did not provide a response within the time limit. "
        "Use your best judgement to make the choice and proceed."
    )


def sudo_password_callback(cli) -> str:
    """Prompt for sudo password through the TUI.

    Sets up a password input area and blocks until the user responds.
    """
    timeout = 45
    response_queue = queue.Queue()

    cli._sudo_state = {"response_queue": response_queue}
    cli._sudo_deadline = _time.monotonic() + timeout

    if hasattr(cli, '_app') and cli._app:
        cli._app.invalidate()

    while True:
        try:
            result = response_queue.get(timeout=1)
            cli._sudo_state = None
            cli._sudo_deadline = 0
            if hasattr(cli, '_app') and cli._app:
                cli._app.invalidate()
            if result:
                cprint(f"\n{_DIM}  ✓ Password received (cached for session){_RST}")
            else:
                cprint(f"\n{_DIM}  ⏭ Skipped{_RST}")
            return result
        except queue.Empty:
            remaining = cli._sudo_deadline - _time.monotonic()
            if remaining <= 0:
                break
            if hasattr(cli, '_app') and cli._app:
                cli._app.invalidate()

    cli._sudo_state = None
    cli._sudo_deadline = 0
    if hasattr(cli, '_app') and cli._app:
        cli._app.invalidate()
    cprint(f"\n{_DIM}  ⏱ Timeout — continuing without sudo{_RST}")
    return ""


def approval_callback(cli, command: str, description: str) -> str:
    """Prompt for dangerous command approval through the TUI.

    Shows a selection UI with choices: once / session / always / deny.
    """
    timeout = 60
    response_queue = queue.Queue()
    choices = ["once", "session", "always", "deny"]

    cli._approval_state = {
        "command": command,
        "description": description,
        "choices": choices,
        "selected": 0,
        "response_queue": response_queue,
    }
    cli._approval_deadline = _time.monotonic() + timeout

    if hasattr(cli, '_app') and cli._app:
        cli._app.invalidate()

    while True:
        try:
            result = response_queue.get(timeout=1)
            cli._approval_state = None
            cli._approval_deadline = 0
            if hasattr(cli, '_app') and cli._app:
                cli._app.invalidate()
            return result
        except queue.Empty:
            remaining = cli._approval_deadline - _time.monotonic()
            if remaining <= 0:
                break
            if hasattr(cli, '_app') and cli._app:
                cli._app.invalidate()

    cli._approval_state = None
    cli._approval_deadline = 0
    if hasattr(cli, '_app') and cli._app:
        cli._app.invalidate()
    cprint(f"\n{_DIM}  ⏱ Timeout — denying command{_RST}")
    return "deny"
