"""Skill loading -- from config directories and builtin stdlib."""

from __future__ import annotations

import logging
import os
from pathlib import Path
from typing import TYPE_CHECKING, Any

from core.skills import get_skill_registry
from core.skills.loader import load_skill_from_directory, load_skills_from_directory
from core.tools import get_tool_registry
from stdlib.bootstrap import get_primitives_path

if TYPE_CHECKING:
    from core.protocols.services import PathwayVMLike
    from core.skills.models import ScriptToolDeclaration, Skill
    from core.pathways.context import Context

from infrastructure.tools.script_provider import ScriptToolProvider

logger = logging.getLogger(__name__)


async def load_skills_from_config(
    directories: list[str],
    auto_activate: list[str] | None = None,
    pathway_vm: PathwayVMLike | None = None,
) -> int:
    """Load skills from configured directories into the global registry."""
    skill_registry = get_skill_registry()
    loaded_count = 0
    script_tools_count = 0

    for dir_path in directories:
        expanded = os.path.expanduser(os.path.expandvars(dir_path))
        path = Path(expanded).resolve()

        if not path.exists() or not path.is_dir():
            continue

        try:
            skills = await load_skills_from_directory(path)
            for skill in skills:
                skill_registry.register(skill)
                loaded_count += 1
                script_tools_count += register_skill_script_tools(skill)
        except Exception as e:
            logger.exception("Failed to load skills from %s: %s", path, e)

    if loaded_count > 0:
        logger.info(
            "Loaded %d skills (%d script tools)", loaded_count, script_tools_count
        )

    return loaded_count


def register_skill_script_tools(skill: Skill) -> int:
    """Register a skill's script tools.

    Tool naming: "{skill_id}.{tool_id}" (e.g. "sora.create").
    """
    if not hasattr(skill, "script_tools") or not skill.script_tools:
        return 0

    registered = 0
    provider = ScriptToolProvider()
    registry = get_tool_registry()

    for tool_decl in skill.script_tools:
        tool_id = f"{skill.id}.{tool_decl.id}"

        try:
            if not skill.source_dir:
                continue

            script_path = skill.source_dir / tool_decl.script
            if not script_path.exists():
                continue

            _skill = skill
            _tool_decl = tool_decl
            _provider = provider

            async def script_handler(
                arguments: dict[str, Any],
                context: Context,
                _s: Skill = _skill,
                _td: ScriptToolDeclaration = _tool_decl,
                _p: ScriptToolProvider = _provider,
            ) -> dict[str, Any]:
                return await _p.execute_script_tool(_s, _td, arguments, context)

            input_schema = provider.build_input_schema(tool_decl)

            registry.register(
                name=tool_id,
                handler=script_handler,
                description=tool_decl.description or f"Run {tool_decl.script}",
                parameters=input_schema,
                requires_privileged=False,
                skill_id=skill.id,
            )

            registered += 1

        except Exception as e:
            logger.exception("Failed to register skill tool %s: %s", tool_id, e)

    return registered


async def load_builtin_skills() -> int:
    """Load builtin skills from stdlib/primitives into the global registry."""
    skill_registry = get_skill_registry()
    loaded = 0
    base_path = get_primitives_path()

    if not base_path.exists():
        return 0

    for skill_dir in sorted(base_path.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 = await load_skill_from_directory(skill_dir)
            if skill:
                skill.tags.add("builtin")
                skill_registry.register(skill)
                loaded += 1
        except Exception as e:
            logger.warning("Failed to load skill %s: %s", skill_dir.name, e)

    logger.info("Loaded %d builtin skills", loaded)
    return loaded
