import asyncio
import json
import logging
from datetime import datetime

from fastapi import APIRouter, Form, Request
from fastapi.responses import HTMLResponse

from dashboard.store import message_log
from dashboard.templating import templates
from timmy.session import _clean_response, chat_with_tools, continue_chat
from timmy.tool_safety import (
    format_action_description,
    get_impact_level,
)

logger = logging.getLogger(__name__)

router = APIRouter(prefix="/agents", tags=["agents"])

MAX_MESSAGE_LENGTH = 10_000  # chars — reject before hitting the model

# In-memory store for paused runs (approval_id -> run context).
# Each entry holds the RunOutput, the RunRequirement ref, and tool metadata.
_pending_runs: dict[str, dict] = {}


@router.get("")
async def list_agents():
    """Return registered agents."""
    from config import settings

    return {
        "agents": [
            {
                "id": "default",
                "name": settings.agent_name,
                "status": "idle",
                "capabilities": "chat,reasoning,research,planning",
                "type": "local",
                "model": settings.ollama_model,
                "backend": "ollama",
                "version": "1.0.0",
            }
        ]
    }


@router.get("/default/panel", response_class=HTMLResponse)
async def agent_panel(request: Request):
    """Chat panel — for HTMX main-panel swaps."""
    return templates.TemplateResponse(request, "partials/agent_panel_chat.html", {"agent": None})


@router.get("/default/history", response_class=HTMLResponse)
async def get_history(request: Request):
    return templates.TemplateResponse(
        request,
        "partials/history.html",
        {"messages": message_log.all()},
    )


@router.delete("/default/history", response_class=HTMLResponse)
async def clear_history(request: Request):
    message_log.clear()
    return templates.TemplateResponse(
        request,
        "partials/history.html",
        {"messages": []},
    )


@router.post("/default/chat", response_class=HTMLResponse)
async def chat_agent(request: Request, message: str = Form(...)):
    """Chat — synchronous response with native Agno tool confirmation."""
    message = message.strip()
    if not message:
        from fastapi import HTTPException

        raise HTTPException(status_code=400, detail="Message cannot be empty")

    if len(message) > MAX_MESSAGE_LENGTH:
        from fastapi import HTTPException

        raise HTTPException(status_code=422, detail="Message too long")

    timestamp = datetime.now().strftime("%H:%M:%S")
    response_text = None
    error_text = None

    try:
        run_output = await asyncio.to_thread(chat_with_tools, message)
    except Exception as exc:
        logger.error("Chat error: %s", exc)
        error_text = f"Chat error: {exc}"
        run_output = None

    # Check if Agno paused the run for tool confirmation
    tool_actions = []
    if run_output is not None:
        status = getattr(run_output, "status", None)
        is_paused = status == "PAUSED" or str(status) == "RunStatus.paused"

        if is_paused and getattr(run_output, "active_requirements", None):
            for req in run_output.active_requirements:
                if getattr(req, "needs_confirmation", False):
                    te = req.tool_execution
                    tool_name = getattr(te, "tool_name", "unknown")
                    tool_args = getattr(te, "tool_args", {}) or {}

                    from timmy.approvals import create_item

                    item = create_item(
                        title=f"Dashboard: {tool_name}",
                        description=format_action_description(tool_name, tool_args),
                        proposed_action=json.dumps({"tool": tool_name, "args": tool_args}),
                        impact=get_impact_level(tool_name),
                    )
                    _pending_runs[item.id] = {
                        "run_output": run_output,
                        "requirement": req,
                        "tool_name": tool_name,
                        "tool_args": tool_args,
                    }
                    tool_actions.append(
                        {
                            "approval_id": item.id,
                            "tool_name": tool_name,
                            "description": format_action_description(tool_name, tool_args),
                            "impact": get_impact_level(tool_name),
                        }
                    )

        raw_content = run_output.content if hasattr(run_output, "content") else ""
        response_text = _clean_response(raw_content or "")
        if not response_text and not tool_actions:
            response_text = None  # let error template show if needed

    message_log.append(role="user", content=message, timestamp=timestamp, source="browser")
    if response_text:
        message_log.append(
            role="agent", content=response_text, timestamp=timestamp, source="browser"
        )
    elif error_text:
        message_log.append(role="error", content=error_text, timestamp=timestamp, source="browser")

    return templates.TemplateResponse(
        request,
        "partials/chat_message.html",
        {
            "user_message": message,
            "response": response_text,
            "error": error_text,
            "timestamp": timestamp,
            "task_id": None,
            "queue_info": None,
            "tool_actions": tool_actions,
        },
    )


@router.post("/default/tool/{approval_id}/approve", response_class=HTMLResponse)
async def approve_tool(request: Request, approval_id: str):
    """Confirm a paused tool and resume execution via Agno."""
    from timmy.approvals import approve

    pending = _pending_runs.pop(approval_id, None)
    if not pending:
        return HTMLResponse(
            "<p class='text-danger'>Action not found or already processed.</p>",
            status_code=404,
        )

    approve(approval_id)

    tool_name = pending["tool_name"]

    # Confirm the requirement — Agno will execute the tool on continue_run
    req = pending["requirement"]
    req.confirm()

    try:
        result_run = await asyncio.to_thread(continue_chat, pending["run_output"])
        # Extract tool result from the resumed run
        tool_result = ""
        for te in getattr(result_run, "tools", None) or []:
            if getattr(te, "tool_name", None) == tool_name and getattr(te, "result", None):
                tool_result = te.result
                break
        if not tool_result:
            tool_result = getattr(result_run, "content", None) or "Tool executed successfully."
    except Exception as exc:
        logger.error("Tool execution failed: %s", exc)
        tool_result = f"Error: {exc}"

    return templates.TemplateResponse(
        request,
        "partials/chat_tool_result.html",
        {
            "approval_id": approval_id,
            "tool_name": tool_name,
            "status": "approved",
            "result": str(tool_result)[:2000],
        },
    )


@router.post("/default/tool/{approval_id}/reject", response_class=HTMLResponse)
async def reject_tool(request: Request, approval_id: str):
    """Reject a pending tool action."""
    from timmy.approvals import reject

    pending = _pending_runs.pop(approval_id, None)
    tool_name = "action"

    if pending:
        tool_name = pending["tool_name"]
        req = pending["requirement"]
        req.reject(note="User rejected from dashboard")
        # Resume so the agent knows the tool was rejected
        try:
            await asyncio.to_thread(continue_chat, pending["run_output"])
        except Exception:
            pass

    reject(approval_id)

    return templates.TemplateResponse(
        request,
        "partials/chat_tool_result.html",
        {
            "approval_id": approval_id,
            "tool_name": tool_name,
            "status": "rejected",
            "result": "",
        },
    )
