"""Skill Management API routes"""

from __future__ import annotations

import logging
from typing import Any, Literal

from fastapi import APIRouter, HTTPException, Request
from pydantic import BaseModel

logger = logging.getLogger(__name__)

router = APIRouter(tags=["skill-management"])

# Explicit set of generic execution-engine templates (react/direct/rewoo/...).
# Everything else is a business-domain skill. Explicit (not name-suffix based)
# because trend_agent/deai_agent are business skills despite the _agent suffix.
# ponytail: ceiling — new engine templates must be added here. Upgrade path:
# add an explicit `category` field to SkillConfig (方案 C).
_ENGINE_TEMPLATE_NAMES = frozenset({
    "react_agent",
    "direct_agent",
    "rewoo_agent",
    "reflexion_agent",
    "plan_exec_agent",
    "goal_driven_agent",
})


# ---------------------------------------------------------------------------
# Request / Response models
# ---------------------------------------------------------------------------


class SkillInfo(BaseModel):
    name: str
    version: str
    description: str
    capabilities: list[str]
    dependencies: list[str]
    status: str
    category: Literal["agent_template", "business_skill"]
    agent_type: str = ""
    execution_mode: str = ""
    task_mode: str = ""


class SkillDetail(BaseModel):
    name: str
    version: str
    description: str
    capabilities: list[str]
    dependencies: list[str]
    config: dict[str, Any]
    health_status: str
    category: Literal["agent_template", "business_skill"]
    agent_type: str = ""
    execution_mode: str = ""
    task_mode: str = ""


class CapabilityInfo(BaseModel):
    name: str
    display_name: str
    skill_count: int


# ---------------------------------------------------------------------------
# Helper: extract skill info from Skill object
# ---------------------------------------------------------------------------


def _skill_to_info(skill: Any) -> dict[str, Any]:
    """Convert a Skill object to a dict suitable for API responses."""
    config = getattr(skill, "config", None)

    capabilities: list[str] = []
    caps = getattr(config, "capabilities", None)
    if isinstance(caps, list):
        capabilities = [c.tag if hasattr(c, "tag") else str(c) for c in caps]
    elif isinstance(caps, dict):
        capabilities = list(caps.keys())

    deps = getattr(config, "dependencies", None)
    if isinstance(deps, list):
        dependencies: list[str] = deps
    elif isinstance(deps, dict):
        dependencies = list(deps.keys())
    else:
        dependencies = []

    version = getattr(config, "version", "") or ""
    description = getattr(config, "description", "") or ""
    agent_type = getattr(config, "agent_type", "") or ""
    execution_mode = getattr(config, "execution_mode", "") or ""
    task_mode = getattr(config, "task_mode", "") or ""

    category = "agent_template" if skill.name in _ENGINE_TEMPLATE_NAMES else "business_skill"

    return {
        "name": skill.name,
        "version": version,
        "description": description,
        "capabilities": capabilities,
        "dependencies": dependencies,
        "status": "active",
        "category": category,
        "agent_type": agent_type,
        "execution_mode": execution_mode,
        "task_mode": task_mode,
    }


def _skill_to_detail(skill: Any) -> dict[str, Any]:
    """Convert a Skill object to a detailed dict for API responses."""
    info = _skill_to_info(skill)

    config = {}
    if hasattr(skill, "config"):
        try:
            config = skill.config.to_dict() if hasattr(skill.config, "to_dict") else {}
        except (AttributeError, ValueError, TypeError):
            config = {}

    return {
        **info,
        "config": config,
        "health_status": "healthy",
    }


# ---------------------------------------------------------------------------
# Endpoints
# ---------------------------------------------------------------------------


@router.get("/skill-management/skills")
async def list_skills(
    req: Request,
    capability: str | None = None,
    page: int = 1,
    size: int = 20,
):
    """List all registered skills with optional filtering."""
    skill_registry = req.app.state.skill_registry
    all_skills = skill_registry.list_skills()

    # Apply capability filter
    if capability:
        filtered = []
        for skill in all_skills:
            caps = _skill_to_info(skill)["capabilities"]
            if capability in caps:
                filtered.append(skill)
        all_skills = filtered

    # Pagination
    total = len(all_skills)
    start = (page - 1) * size
    end = start + size
    page_skills = all_skills[start:end]

    return {
        "skills": [_skill_to_info(s) for s in page_skills],
        "total": total,
        "page": page,
        "size": size,
    }


@router.get("/skill-management/skills/{skill_name}")
async def get_skill_detail(skill_name: str, req: Request):
    """Get detailed information about a specific skill."""
    skill_registry = req.app.state.skill_registry
    try:
        skill = skill_registry.get(skill_name)
    except (KeyError, ValueError, AttributeError):
        raise HTTPException(status_code=404, detail=f"Skill '{skill_name}' not found")

    return _skill_to_detail(skill)


@router.get("/skill-management/skills/{skill_name}/health")
async def check_skill_health(skill_name: str, req: Request):
    """Check the health of a specific skill."""
    skill_registry = req.app.state.skill_registry
    try:
        skill_registry.get(skill_name)
    except (KeyError, ValueError, AttributeError):
        raise HTTPException(status_code=404, detail=f"Skill '{skill_name}' not found")

    # Basic health check - skill exists and is registered
    return {
        "skill_name": skill_name,
        "status": "healthy",
        "message": "技能已注册且可用",
    }


@router.get("/skill-management/capabilities")
async def list_capabilities(req: Request):
    """List all capability tags with skill counts."""
    skill_registry = req.app.state.skill_registry
    all_skills = skill_registry.list_skills()

    # Build capability -> skill count mapping
    cap_counts: dict[str, int] = {}
    for skill in all_skills:
        caps = _skill_to_info(skill)["capabilities"]
        for cap in caps:
            cap_counts[cap] = cap_counts.get(cap, 0) + 1

    # Display name mapping
    display_names: dict[str, str] = {
        "chat": "智能对话",
        "workflow": "工作流编排",
        "knowledge": "知识库",
        "skills": "技能管理",
        "terminal": "智能终端",
        "computer_use": "Computer Use",
        "evolution": "自进化",
        "code": "代码生成",
        "search": "搜索",
        "analysis": "分析",
    }

    capabilities = [
        {
            "name": name,
            "display_name": display_names.get(name, name),
            "skill_count": count,
        }
        for name, count in sorted(cap_counts.items())
    ]

    return {"capabilities": capabilities}


@router.post("/skill-management/skills/{skill_name}/reload")
async def reload_skill(skill_name: str, req: Request):
    """Reload a skill configuration from its YAML file."""
    skill_registry = req.app.state.skill_registry
    # Verify the skill is currently registered (404 if not).
    try:
        skill_registry.get(skill_name)
    except (KeyError, ValueError, AttributeError):
        raise HTTPException(status_code=404, detail=f"Skill '{skill_name}' not found")

    # Resolve the skills directory (mirrors routes.skills._get_skills_dir).
    import os

    skills_dir: str
    server_config = getattr(req.app.state, "server_config", None)
    if server_config and getattr(server_config, "skill_paths", None):
        from pathlib import Path as _P

        first_path = _P(server_config.skill_paths[0])
        if first_path.is_dir():
            skills_dir = str(first_path)
        else:
            skills_dir = os.path.join(os.getcwd(), "configs", "skills")
    else:
        skills_dir = os.path.join(os.getcwd(), "configs", "skills")

    from agentkit.server.admin.skill_service import get_skill_service

    svc = get_skill_service()
    try:
        result = await svc.reload_skill(skill_name, skill_registry, skills_dir)
    except ValueError as exc:
        msg = str(exc)
        if "not found" in msg:
            raise HTTPException(status_code=404, detail=msg) from exc
        raise HTTPException(status_code=400, detail=msg) from exc

    return {
        "skill_name": result["name"],
        "status": result["status"],
        "message": f"技能 '{skill_name}' 已重新加载",
    }
