"""Dashboard API endpoints for the Tools tab.

Exposes tool registry, prompt building, job queue, and execution via REST.
"""

from __future__ import annotations

from typing import Any

import structlog
from fastapi import APIRouter, HTTPException, Query
from pydantic import BaseModel, Field

from proxym.tools import ToolCategory, ToolRegistry
from proxym.tools.executor import JobStatus, ToolExecutor
from proxym.tools.prompt_builder import build_prompt, build_prompt_dict

logger = structlog.get_logger()
router = APIRouter(prefix="/tools", tags=["tools"])


# ── Request models ────────────────────────────────────────

class DispatchRequest(BaseModel):
    ticket_id: str = Field(..., description="Ticket ID to dispatch")
    tool: str = Field(..., description="Tool name (aider, claude-code, ...)")
    mode: str = Field("", description="Agent mode (code, architect, debug, ask)")
    model: str = Field("", description="Model alias or full name")
    project_dir: str = Field("", description="Project directory")


class PreviewPromptRequest(BaseModel):
    ticket_id: str = Field(..., description="Ticket ID")
    tool: str = Field(..., description="Tool name")
    mode: str = Field("", description="Agent mode")


# ── Tool registry endpoints ──────────────────────────────

@router.get("/")
async def list_tools(
    category: str | None = Query(None, description="Filter by category: ide, agent_cli, browser"),
    available_only: bool = Query(False, description="Only show tools found on PATH"),
) -> dict[str, Any]:
    """List all registered tools."""
    reg = ToolRegistry.get()
    cat = ToolCategory(category) if category else None
    tools = reg.list_tools(category=cat, available_only=available_only)
    return {"tools": [t.summary() for t in tools], "count": len(tools)}


@router.get("/summary")
async def tools_summary() -> dict[str, Any]:
    """Summary of tool availability."""
    return ToolRegistry.get().summary()


# ── Prompt preview ───────────────────────────────────────

@router.post("/prompt/preview")
async def preview_prompt(req: PreviewPromptRequest) -> dict[str, Any]:
    """Preview the prompt that would be sent to a tool for a ticket."""
    tool = ToolRegistry.get().get_tool(req.tool)
    if not tool:
        raise HTTPException(404, f"Tool '{req.tool}' not found")

    ticket = _get_ticket(req.ticket_id)
    return build_prompt_dict(ticket, tool, req.mode)


# ── Job dispatch ─────────────────────────────────────────

@router.post("/dispatch")
async def dispatch_job(req: DispatchRequest) -> dict[str, Any]:
    """Dispatch a tool to work on a ticket. Enqueues a job."""
    tool = ToolRegistry.get().get_tool(req.tool)
    if not tool:
        raise HTTPException(404, f"Tool '{req.tool}' not found")

    ticket = _get_ticket(req.ticket_id)
    project_dir = req.project_dir or _default_project_dir()

    executor = ToolExecutor.get()
    job = executor.enqueue(ticket, tool, project_dir, req.mode, req.model)
    return {"job": job.summary(), "message": f"Job {job.id} enqueued for {tool.name}"}


# ── Job queue endpoints (sub-router to avoid /{tool_name} shadow) ──

queue_router = APIRouter(prefix="/queue", tags=["tools"])


@queue_router.get("")
async def queue_status() -> dict[str, Any]:
    """Get queue summary and recent jobs."""
    executor = ToolExecutor.get()
    summary = executor.queue_summary()
    recent = executor.list_jobs(limit=20)
    summary["recent_jobs"] = [j.summary() for j in recent]
    return summary


@queue_router.get("/jobs")
async def list_jobs(
    status: str | None = Query(None, description="Filter: queued, running, done, failed, cancelled"),
    limit: int = Query(50, ge=1, le=200),
) -> dict[str, Any]:
    """List jobs with optional status filter."""
    executor = ToolExecutor.get()
    st = JobStatus(status) if status else None
    jobs = executor.list_jobs(status=st, limit=limit)
    return {"jobs": [j.summary() for j in jobs], "count": len(jobs)}


@queue_router.get("/jobs/{job_id}")
async def get_job(job_id: str) -> dict[str, Any]:
    """Get details for a specific job."""
    job = ToolExecutor.get().get_job(job_id)
    if not job:
        raise HTTPException(404, f"Job '{job_id}' not found")
    return job.summary()


@queue_router.post("/jobs/{job_id}/cancel")
async def cancel_job(job_id: str) -> dict[str, Any]:
    """Cancel a queued job."""
    if ToolExecutor.get().cancel_job(job_id):
        return {"ok": True, "job_id": job_id}
    raise HTTPException(400, "Job not found or not in queued state")


@queue_router.post("/start")
async def start_executor() -> dict[str, Any]:
    """Start the background executor loop."""
    await ToolExecutor.get().start()
    return {"ok": True, "message": "Executor started"}


@queue_router.post("/stop")
async def stop_executor() -> dict[str, Any]:
    """Stop the background executor loop."""
    await ToolExecutor.get().stop()
    return {"ok": True, "message": "Executor stopped"}


router.include_router(queue_router)


# NOTE: Dynamic route MUST be after include_router(queue_router).
@router.get("/{tool_name}")
async def get_tool(tool_name: str) -> dict[str, Any]:
    """Get details for a specific tool."""
    tool = ToolRegistry.get().get_tool(tool_name)
    if not tool:
        raise HTTPException(404, f"Tool '{tool_name}' not found")
    return tool.summary()


# ── Helpers ──────────────────────────────────────────────

def _get_ticket(ticket_id: str):
    """Fetch a ticket by ID. Raises 404 if not found."""
    from proxym.dashboard._tickets_api import _tickets
    mgr = _tickets()
    ticket = mgr.get_ticket(ticket_id)
    if not ticket:
        raise HTTPException(404, f"Ticket '{ticket_id}' not found")
    return ticket


def _default_project_dir() -> str:
    """Return default project directory from settings."""
    try:
        from proxym.config import get_settings
        s = get_settings()
        return str(getattr(s, "projects_root", "~/github"))
    except Exception:
        return "~/github"
