"""Adapter to run ForemanAgent inside a Textual TUI."""

from __future__ import annotations

import asyncio
import logging
from typing import Any, Optional

from easyclaw_tui.agent.config import AgentConfig
from easyclaw_tui.agent.core import ForemanAgent
from easyclaw_tui.agent.prompt import build_system_prompt
from easyclaw_tui.agent.tools.confirm import set_confirm_callback
from easyclaw_tui.messages import (
    AgentResponse,
    AgentToolCall,
    AgentThinking,
    AgentReady,
    UserConfirmRequest,
)

log = logging.getLogger("tui_bridge")

# Timeout for user confirmations in TUI (seconds)
CONFIRM_TIMEOUT = 120.0


class TUIConfirmBridge:
    """Replaces input()-based ask_user with a Textual inline widget.

    When the agent calls ask_user, this bridge:
    1. Posts a UserConfirmRequest message to the screen
    2. Awaits an asyncio.Event (set when user clicks Approve/Deny)
    3. Returns "approved" or "denied"
    """

    def __init__(self, post_message) -> None:
        self._post_message = post_message

    async def ask_user(self, question: str) -> str:
        """TUI-based user confirmation."""
        event = asyncio.Event()
        holder: list[str] = []

        self._post_message(UserConfirmRequest(question, event, holder))

        try:
            await asyncio.wait_for(event.wait(), timeout=CONFIRM_TIMEOUT)
            return holder[0] if holder else "denied (no response)"
        except asyncio.TimeoutError:
            return "denied (timed out after 120 seconds)"


class AgentWorker:
    """Wraps ForemanAgent for sequential message processing in Textual.

    Maintains an asyncio.Queue so that concurrent requests (user message +
    auto-diagnosis) are processed one at a time.
    """

    def __init__(
        self,
        config: AgentConfig,
        post_message,
        install_mode: bool = False,
    ) -> None:
        self._post_message = post_message
        self._queue: asyncio.Queue[tuple[str, bool]] = asyncio.Queue()
        self._processing = False
        self._agent: Optional[ForemanAgent] = None
        self._config = config
        self._install_mode = install_mode

    def initialize(self) -> bool:
        """Initialize the agent. Returns True if successful."""
        if not self._config.openrouter_key:
            log.warning("No OpenRouter key — agent unavailable")
            return False

        # Build agent with install-mode prompt if needed
        self._agent = ForemanAgent(self._config, install_mode=self._install_mode)

        # Set up TUI confirmation bridge
        bridge = TUIConfirmBridge(self._post_message)
        set_confirm_callback(bridge.ask_user)

        # Set up tool-call visibility callback
        async def tool_call_handler(name: str, args: dict, result: str) -> None:
            self._post_message(AgentToolCall(name, args))

        self._agent.on_tool_call = tool_call_handler

        return True

    @property
    def is_available(self) -> bool:
        return self._agent is not None

    async def send_message(self, text: str, is_system: bool = False) -> None:
        """Queue a message for the agent to process.

        Args:
            text: The message text.
            is_system: If True, this is an internal message (e.g., auto-diagnosis)
                       and won't show "You:" in the chat.
        """
        await self._queue.put((text, is_system))

    async def run(self) -> None:
        """Main processing loop — runs as a Textual worker."""
        while True:
            text, is_system = await self._queue.get()
            self._processing = True

            self._post_message(AgentThinking())

            try:
                if self._agent is None:
                    self._post_message(
                        AgentResponse(
                            "Agent Johnny 5 is not available — no OpenRouter API key. "
                            "The install is proceeding automatically."
                        )
                    )
                    continue

                response = await self._agent.chat(text)
                self._post_message(AgentResponse(response or "(no response)"))

            except Exception as e:
                log.exception("Agent error")
                self._post_message(
                    AgentResponse(f"Error: {type(e).__name__}: {e}")
                )
            finally:
                self._processing = False
                self._post_message(AgentReady())
                self._queue.task_done()

    @property
    def is_busy(self) -> bool:
        return self._processing
