from __future__ import annotations

import json
from pathlib import Path

from beaver.engine import EngineLoader
from beaver.skills.authoring.format import is_canonical_skill_body
from beaver.skills.catalog.utils import parse_frontmatter


REPO_ROOT = Path(__file__).resolve().parents[4]

EXPECTED_INITIAL_SKILL_TOOLS = {
    "cron-scheduler": ["cron"],
    "filesystem-operation": ["read_file", "write_file", "patch_file", "search_files", "list_directory"],
    "memory-management": ["memory"],
    "outlook-mail": [
        "mcp_outlook_mcp_mail_list_folders",
        "mcp_outlook_mcp_mail_list_messages",
        "mcp_outlook_mcp_mail_search_messages",
        "mcp_outlook_mcp_mail_get_message",
        "mcp_outlook_mcp_mail_send_email",
        "mcp_outlook_mcp_mail_reply_to_message",
        "mcp_outlook_mcp_mail_forward_message",
        "mcp_outlook_mcp_mail_move_message",
        "mcp_outlook_mcp_mail_delta_sync",
        "mcp_outlook_mcp_calendar_list_events",
        "mcp_outlook_mcp_calendar_create_event",
        "mcp_outlook_mcp_calendar_update_event",
        "mcp_outlook_mcp_calendar_get_schedule",
        "mcp_outlook_mcp_calendar_find_meeting_times",
        "mcp_outlook_mcp_calendar_delta_sync",
    ],
    "skills-admin": ["skills_list", "skill_view"],
    "terminal-operation": ["terminal", "process", "execute_code"],
    "utility-tools": ["clarify", "delegate", "send_message", "spawn", "todo"],
    "multi-search-engine": ["web_fetch"],
}

EXPECTED_NON_INITIAL_SKILL_TOOLS = {
    "skills-authoring-admin": ["skill_manage"],
}


def test_initial_skill_tool_hints_match_runtime_tool_names() -> None:
    for skill_name, expected_tools in EXPECTED_INITIAL_SKILL_TOOLS.items():
        skill_dir = REPO_ROOT / "skills" / skill_name / "versions" / "v0001"
        frontmatter, _body = parse_frontmatter((skill_dir / "SKILL.md").read_text(encoding="utf-8"))
        version = json.loads((skill_dir / "version.json").read_text(encoding="utf-8"))

        assert frontmatter["tools"] == expected_tools
        assert version["frontmatter"]["tools"] == expected_tools
        assert version["tool_hints"] == expected_tools


def test_skill_authoring_admin_is_seeded_but_not_initial() -> None:
    published = json.loads((REPO_ROOT / "skills" / "_index" / "published.json").read_text(encoding="utf-8"))
    disabled = json.loads((REPO_ROOT / "skills" / "_index" / "disabled.json").read_text(encoding="utf-8"))

    assert "skills-authoring-admin" not in published["items"]
    assert "skills-authoring-admin" in disabled["items"]

    for skill_name, expected_tools in EXPECTED_NON_INITIAL_SKILL_TOOLS.items():
        skill_dir = REPO_ROOT / "skills" / skill_name / "versions" / "v0001"
        frontmatter, _body = parse_frontmatter((skill_dir / "SKILL.md").read_text(encoding="utf-8"))
        version = json.loads((skill_dir / "version.json").read_text(encoding="utf-8"))

        assert frontmatter["tools"] == expected_tools
        assert version["frontmatter"]["tools"] == expected_tools
        assert version["tool_hints"] == expected_tools


def test_seeded_skill_bodies_use_canonical_format() -> None:
    for index_name in ("published", "disabled"):
        index = json.loads((REPO_ROOT / "skills" / "_index" / f"{index_name}.json").read_text(encoding="utf-8"))
        for skill_name in index["items"]:
            skill_dir = REPO_ROOT / "skills" / skill_name / "versions" / "v0001"
            _frontmatter, body = parse_frontmatter((skill_dir / "SKILL.md").read_text(encoding="utf-8"))

            assert is_canonical_skill_body(body), skill_name


def test_default_runtime_registers_skill_view_tool(tmp_path: Path) -> None:
    loaded = EngineLoader(workspace=tmp_path).load()
    try:
        assert "skill_view" in loaded.tools
        assert loaded.tool_registry is not None
        assert loaded.tool_registry.get("skill_view") is not None
    finally:
        loaded.close()
