"""Bootstrap - Load tools and skills from stdlib/primitives.

Tool categories (subdirectories of primitives/):
- tools/          Atomic capabilities (web, workspace, memory, shell)
- orchestration/  Agent lifecycle (agent.turn, agent.list)
- code/           Code capabilities (code.execute, code.run_test)

Each category contains skill directories, each with:
- SKILL.md: Instructions and domain knowledge (optional)
- tools/: Python scripts that become callable tools

Tool naming: {skill_dir_name}.{tool_file_name}
Example: web.search, agent.turn, code.execute
"""

import logging
from pathlib import Path

from core.skills import get_skill_registry
from core.tools import get_tool_registry
from infrastructure.tools import load_tools_from_directory

logger = logging.getLogger(__name__)

# Categories that are loaded for ALL agents
CATEGORIES = ("tools", "orchestration", "code")


def load_stdlib() -> int:
    """Load all tools, skills, and LLM providers into global registries.

    Returns
    -------
        Number of tools loaded
    """
    # Initialize LLM providers from environment
    from core.llm import init_providers

    init_providers()

    registry = get_tool_registry()
    base_dir = get_primitives_path()
    total_tools = 0

    for category in CATEGORIES:
        category_dir = base_dir / category
        if not category_dir.exists():
            continue
        count = _load_category(registry, category_dir, category)
        total_tools += count

    # Also register skills into the global skill registry
    skill_count = _register_skills_from_categories(base_dir)
    if skill_count > 0:
        logger.info("Registered %d skills from stdlib primitives", skill_count)

    return total_tools


def _load_category(registry, category_dir: Path, category: str) -> int:
    """Load all tools from a category directory.

    Each subdirectory within the category is a skill namespace:
    - tools/web/tools/search.py → web.search
    - orchestration/agent/tools/turn.py → agent.turn

    Args:
        registry: Tool registry to register into
        category_dir: Path to the category directory
        category: Category name (tools, orchestration, code)

    Returns
    -------
        Number of tools loaded
    """
    try:
        total = 0

        for skill_dir in sorted(category_dir.iterdir()):
            if not skill_dir.is_dir() or skill_dir.name.startswith((".", "_")):
                continue

            tools_dir = skill_dir / "tools"
            if not tools_dir.exists():
                logger.debug("Skill %s has no tools/ directory", skill_dir.name)
                continue

            # Load tools from this skill's tools/ directory
            tools = load_tools_from_directory(tools_dir)

            # Namespace = skill directory name (e.g., "web", "agent", "pathway")
            namespace = skill_dir.name

            for raw_tool_id, schema, handler in tools:
                tool_id = f"{namespace}.{raw_tool_id}"

                registry.register(
                    name=tool_id,
                    handler=handler,
                    description=schema.description,
                    parameters=schema.input_schema,
                    requires_privileged=schema.requires_privileged,
                    skill_id=skill_dir.name,
                    category=category,
                )
                logger.debug("Loaded tool: %s (category=%s)", tool_id, category)
                total += 1

        if total > 0:
            logger.info("Loaded %d tools from %s/", total, category)

        return total

    except Exception as e:
        logger.exception("Failed to load category %s: %s", category, e)
        raise


def _register_skills_from_categories(base_dir: Path) -> int:
    """Register skills from all categories into the global skill registry.

    Returns
    -------
    int
        Number of skills registered.
    """
    try:
        from core.skills.loader import load_skill_from_directory
    except ImportError:
        logger.debug("Skill loader not available")
        return 0

    skill_registry = get_skill_registry()
    registered = 0
    failures = 0

    for category in CATEGORIES:
        category_dir = base_dir / category
        if not category_dir.exists():
            continue

        for skill_dir in sorted(category_dir.iterdir()):
            if not skill_dir.is_dir() or skill_dir.name.startswith((".", "_")):
                continue

            skill_md = skill_dir / "SKILL.md"
            if not skill_md.exists():
                continue

            try:
                skill = load_skill_from_directory(skill_dir)
                if skill:
                    skill.tags.add("builtin")
                    skill.tags.add(category)
                    skill_registry.register(skill)
                    registered += 1
                    logger.debug("Registered skill: %s (category=%s)", skill.id, category)
            except Exception as e:
                failures += 1
                logger.exception(
                    "Failed to register skill %s (path=%s): %s",
                    skill_dir.name,
                    skill_dir,
                    e,
                )

    if failures:
        logger.warning(
            "Skill registration completed with %d failure(s) out of %d attempted",
            failures,
            registered + failures,
        )

    return registered


def get_primitives_path() -> Path:
    """Get the path to stdlib/primitives directory."""
    return Path(__file__).parent / "primitives"


__all__ = [
    "CATEGORIES",
    "get_primitives_path",
    "load_stdlib",
]
