"""Tests for skill registry, intent detection, and skill loading."""

import pytest

from autodebug.agent.skills import (
    SKILL_BUDGETS,
    SKILL_REGISTRY,
    detect_skill,
    load_skill_content,
    build_skill_menu,
    get_skill_names,
)


class TestSkillRegistry:
    def test_registry_has_eight_skills(self):
        assert len(SKILL_REGISTRY) == 8

    def test_all_skills_have_required_fields(self):
        for skill in SKILL_REGISTRY:
            assert skill.name
            assert skill.description
            assert len(skill.triggers) > 0
            assert skill.filename.endswith(".md")

    def test_skill_names_are_unique(self):
        names = [s.name for s in SKILL_REGISTRY]
        assert len(names) == len(set(names))

    def test_get_skill_names(self):
        names = get_skill_names()
        assert len(names) == 8
        assert "investigate" in names
        assert "scan" in names
        assert "test_runner" in names
        assert "local_debug" in names

    def test_all_skills_have_budgets(self):
        for skill in SKILL_REGISTRY:
            assert skill.name in SKILL_BUDGETS, f"Skill '{skill.name}' missing budget"
            assert SKILL_BUDGETS[skill.name] > 0


class TestDetectSkill:
    @pytest.mark.parametrize("message,expected", [
        ("how does the auth flow work", "investigate"),
        ("why is this function broken", "investigate"),
        ("analyze the database module", "investigate"),
        ("explain the session logic", "investigate"),
        ("scan the codebase for bugs", "scan"),
        ("find bugs in the project", "scan"),
        ("what's wrong with the code", "scan"),
        ("audit the security", "scan"),
        ("run my tests", "test_runner"),
        ("run pytest on the project", "test_runner"),
        ("execute tests in tests/", "test_runner"),
        ("run the tests", "test_runner"),
        ("debug this test failure", "local_debug"),
        ("why is this failing", "local_debug"),
        ("this test fails intermittently", "local_debug"),
        ("what's wrong with this function", "local_debug"),
        ("fix flaky test in test_auth.py", "fix_flaky"),
        ("heal the unstable test", "fix_flaky"),
        ("the test is flaky", "fix_flaky"),
        ("production error err_123", "production_debug"),
        ("there's a prod error", "production_debug"),
        ("replay error from production", "production_debug"),
        ("continue", "deep_dive"),
        ("dig deeper into that issue", "deep_dive"),
        ("keep going", "deep_dive"),
        ("analyze yourself", "self_analysis"),
        ("find your own bugs", "self_analysis"),
        ("self-improve", "self_analysis"),
    ])
    def test_detect_skill_keywords(self, message, expected):
        assert detect_skill(message) == expected

    @pytest.mark.parametrize("message", [
        "hi", "hello", "hey", "what can you do", "help", "ok", "",
    ])
    def test_detect_skill_greetings_return_none(self, message):
        assert detect_skill(message) is None

    def test_detect_skill_unknown_returns_none(self):
        assert detect_skill("tell me a joke about python") is None

    def test_detect_skill_case_insensitive(self):
        assert detect_skill("SCAN the codebase") == "scan"
        assert detect_skill("How Does auth work") == "investigate"

    def test_local_debug_preferred_over_production_for_debug_this(self):
        """'debug this' should match local_debug, not production_debug."""
        result = detect_skill("debug this test")
        assert result == "local_debug"

    def test_production_debug_needs_production_keyword(self):
        """production_debug should only trigger with explicit production/prod keywords."""
        result = detect_skill("there's a production error")
        assert result == "production_debug"


class TestLoadSkillContent:
    def test_load_existing_skill(self):
        content = load_skill_content("investigate")
        assert content is not None
        assert "Investigate" in content

    def test_load_nonexistent_skill_returns_none(self):
        assert load_skill_content("nonexistent") is None

    def test_all_registered_skills_have_files(self):
        for name in get_skill_names():
            content = load_skill_content(name)
            assert content is not None, f"Skill '{name}' has no file"
            assert len(content) > 50, f"Skill '{name}' file is too short"

    def test_skill_files_reference_compact_tool_names(self):
        """Verify skill files don't reference legacy tool names."""
        legacy_names = [
            "fetch_production_errors", "get_error_details",
            "scan_codebase", "detect_flaky_patterns",
            "heal_flaky_test", "generate_fix_hypothesis",
            "search_similar_fixes", "view_io_transcript",
            "memory_rethink", "scan_feedback",
        ]
        for name in get_skill_names():
            content = load_skill_content(name)
            for legacy in legacy_names:
                assert f"`{legacy}`" not in content, (
                    f"Skill '{name}' references legacy tool `{legacy}` — "
                    f"use compact MCP tool name instead"
                )


class TestBuildSkillMenu:
    def test_menu_contains_all_skills(self):
        menu = build_skill_menu()
        for name in get_skill_names():
            assert name in menu

    def test_menu_is_markdown(self):
        menu = build_skill_menu()
        assert "## Available Skills" in menu

    def test_menu_contains_descriptions(self):
        menu = build_skill_menu()
        assert "Targeted code analysis" in menu
        assert "Semgrep" in menu

    def test_menu_references_compact_tools(self):
        menu = build_skill_menu()
        assert "knowledge_memory" in menu
