"""HTTP route handlers for agent skill endpoints.

These handlers expose the :class:`AgentService` via HTTP, allowing the
frontend to list available skills and execute them on selected models.
Progress is reported via WebSocket broadcast.
"""

from __future__ import annotations

import asyncio
import logging
from typing import Any, Dict

from aiohttp import web

from ...services.agent import AgentService, AgentProgressReporter
from ...services.llm_service import LLMNotConfiguredError

logger = logging.getLogger(__name__)


class AgentHandler:
    """HTTP handler for agent skill operations."""

    def __init__(self, agent_service: AgentService | None = None) -> None:
        self._agent_service = agent_service

    async def _ensure_service(self) -> AgentService:
        if self._agent_service is None:
            self._agent_service = await AgentService.get_instance()
        return self._agent_service

    # ------------------------------------------------------------------
    # GET /api/lm/agent/skills
    # ------------------------------------------------------------------

    async def get_agent_skills(self, request: web.Request) -> web.Response:
        """Return a list of available agent skills."""

        service = await self._ensure_service()
        skills = await service.list_skills()
        return web.json_response({"skills": skills})

    # ------------------------------------------------------------------
    # POST /api/lm/agent/execute/{skill_name}
    # ------------------------------------------------------------------

    async def execute_agent_skill(self, request: web.Request) -> web.Response:
        """Execute an agent skill on the provided model paths.

        Request body::

            {"model_paths": ["/path/to/model1.safetensors", ...], "options": {}}

        Returns immediately with a task ID.  Execution runs in the
        background; progress and completion are pushed via WebSocket
        events of type ``agent_progress``.
        """

        skill_name = request.match_info.get("skill_name", "")
        if not skill_name:
            return web.json_response(
                {"error": "Skill name is required"}, status=400
            )

        try:
            body = await request.json()
        except Exception:
            return web.json_response(
                {"error": "Invalid JSON body"}, status=400
            )

        model_paths = body.get("model_paths", [])
        if not model_paths or not isinstance(model_paths, list):
            return web.json_response(
                {"error": "model_paths must be a non-empty array"},
                status=400,
            )

        service = await self._ensure_service()

        # Validate LLM configuration early for skills that need it
        # (fail fast rather than after starting background work)
        try:
            from ...services.llm_service import LLMService

            llm = await LLMService.get_instance()
            if not llm.is_configured():
                return web.json_response(
                    {
                        "error": "LLM provider is not configured. "
                        "Enable it in Settings → AI Provider.",
                    },
                    status=400,
                )
        except Exception as exc:
            logger.error("Failed to check LLM configuration: %s", exc)

        # Launch execution in the background
        progress_reporter = AgentProgressReporter()
        logger.info(
            "LLM enrichment '%s' starting for %d model(s)",
            skill_name, len(model_paths),
        )

        async def _run() -> None:
            try:
                result = await service.execute_skill(
                    skill_name=skill_name,
                    input_data={"model_paths": model_paths},
                    progress_callback=progress_reporter,
                )
                logger.info(
                    "LLM enrichment '%s' finished: success=%s, summary='%s', errors=%s",
                    skill_name, result.success, result.summary, result.errors,
                )
            except LLMNotConfiguredError as exc:
                logger.warning("LLM enrichment '%s' not configured: %s", skill_name, exc)
                await progress_reporter.on_progress(
                    {
                        "type": "agent_progress",
                        "skill": skill_name,
                        "status": "error",
                        "error": str(exc),
                    }
                )
            except Exception as exc:
                logger.error("LLM enrichment '%s' failed: %s", skill_name, exc, exc_info=True)
                await progress_reporter.on_progress(
                    {
                        "type": "agent_progress",
                        "skill": skill_name,
                        "status": "error",
                        "error": str(exc),
                    }
                )

        # Fire and forget — progress comes via WebSocket
        asyncio.create_task(_run())

        return web.json_response(
            {
                "status": "started",
                "skill": skill_name,
                "model_count": len(model_paths),
            }
        )

    # ------------------------------------------------------------------
    # POST /api/lm/agent/cancel
    # ------------------------------------------------------------------

    async def cancel_agent_skill(self, request: web.Request) -> web.Response:
        """Cancel a running agent skill.

        NOTE: Cancellation is a stub for now — the AgentService processes
        models sequentially and does not yet support mid-execution
        cancellation.  This endpoint exists for API completeness.
        """

        # TODO: implement cooperative cancellation in AgentService
        return web.json_response(
            {"status": "acknowledged", "note": "Cancellation not yet implemented"},
            status=200,
        )
