"""discovery モジュールのテスト."""

from pathlib import Path

from skill_search.discovery import discover_resources, discover_skills, parse_skill_md


class TestParseSkillMd:
    """parse_skill_md のテスト."""

    def test_valid_frontmatter(self):
        content = """---
name: test-skill
description: A test skill
---

# Test Skill

Some instructions here.
"""
        frontmatter, body = parse_skill_md(content)
        assert frontmatter["name"] == "test-skill"
        assert frontmatter["description"] == "A test skill"
        assert "# Test Skill" in body
        assert "Some instructions here." in body

    def test_no_frontmatter(self):
        content = "# Just a markdown file\n\nNo frontmatter."
        frontmatter, body = parse_skill_md(content)
        assert frontmatter == {}
        assert "# Just a markdown file" in body

    def test_invalid_yaml(self):
        content = """---
invalid: [unterminated
---

# Body
"""
        frontmatter, body = parse_skill_md(content)
        assert frontmatter == {}
        assert "# Body" in body


class TestDiscoverSkills:
    """discover_skills のテスト."""

    def test_discover_single_skill(self, tmp_path: Path):
        # スキルディレクトリを作成
        skill_dir = tmp_path / "my-skill"
        skill_dir.mkdir()
        (skill_dir / "SKILL.md").write_text(
            """---
name: my-skill
description: My test skill
---

# My Skill

Instructions here.
""",
            encoding="utf-8",
        )

        skills = discover_skills(tmp_path)
        assert len(skills) == 1
        assert skills[0].name == "my-skill"
        assert skills[0].description == "My test skill"
        assert "Instructions here." in skills[0].content

    def test_discover_multiple_skills(self, tmp_path: Path):
        for i in range(3):
            skill_dir = tmp_path / f"skill-{i}"
            skill_dir.mkdir()
            (skill_dir / "SKILL.md").write_text(
                f"""---
name: skill-{i}
description: Skill number {i}
---

# Skill {i}
""",
                encoding="utf-8",
            )

        skills = discover_skills(tmp_path)
        assert len(skills) == 3
        names = {s.name for s in skills}
        assert names == {"skill-0", "skill-1", "skill-2"}

    def test_discover_with_resources(self, tmp_path: Path):
        skill_dir = tmp_path / "my-skill"
        skill_dir.mkdir()
        (skill_dir / "SKILL.md").write_text(
            """---
name: my-skill
description: Has resources
---

# Skill
""",
            encoding="utf-8",
        )
        docs_dir = skill_dir / "docs"
        docs_dir.mkdir()
        (docs_dir / "README.md").write_text("# Docs", encoding="utf-8")
        (docs_dir / "data.json").write_text('{"key": "value"}', encoding="utf-8")

        skills = discover_skills(tmp_path)
        assert len(skills) == 1
        resource_names = {r.name for r in skills[0].resources}
        assert "docs/README.md" in resource_names
        assert "docs/data.json" in resource_names

    def test_fallback_name_from_directory(self, tmp_path: Path):
        """name が frontmatter に無い場合、ディレクトリ名を使用."""
        skill_dir = tmp_path / "fallback-name"
        skill_dir.mkdir()
        (skill_dir / "SKILL.md").write_text(
            """---
description: No name field
---

# Fallback
""",
            encoding="utf-8",
        )

        skills = discover_skills(tmp_path)
        assert len(skills) == 1
        assert skills[0].name == "fallback-name"

    def test_nonexistent_directory(self):
        """存在しないディレクトリを渡すと空リスト."""
        skills = discover_skills("/nonexistent/path")
        assert skills == []

    def test_max_depth(self, tmp_path: Path):
        """max_depth による深度制限."""
        # depth=1: 直下に SKILL.md
        skill_dir = tmp_path / "top-skill"
        skill_dir.mkdir()
        (skill_dir / "SKILL.md").write_text(
            "---\nname: top\ndescription: top\n---\n# Top",
            encoding="utf-8",
        )

        # depth=3: deep/nested/skill/SKILL.md
        deep = tmp_path / "deep" / "nested" / "skill"
        deep.mkdir(parents=True)
        (deep / "SKILL.md").write_text(
            "---\nname: deep\ndescription: deep\n---\n# Deep",
            encoding="utf-8",
        )

        # max_depth=1 だと top のみ発見
        skills_shallow = discover_skills(tmp_path, max_depth=1)
        names_shallow = {s.name for s in skills_shallow}
        assert "top" in names_shallow
        assert "deep" not in names_shallow

        # max_depth=3 だと両方発見
        skills_deep = discover_skills(tmp_path, max_depth=3)
        names_deep = {s.name for s in skills_deep}
        assert "top" in names_deep
        assert "deep" in names_deep


class TestDiscoverResources:
    """discover_resources のテスト."""

    def test_skips_skill_md(self, tmp_path: Path):
        """SKILL.md はリソースに含まれない."""
        (tmp_path / "SKILL.md").write_text("---\nname: x\n---\n# X", encoding="utf-8")
        (tmp_path / "README.md").write_text("# Readme", encoding="utf-8")

        resources = discover_resources(tmp_path)
        names = {r.name for r in resources}
        assert "SKILL.md" not in names
        assert "README.md" in names

    def test_filters_by_extension(self, tmp_path: Path):
        """許可されていない拡張子は除外."""
        (tmp_path / "doc.md").write_text("doc", encoding="utf-8")
        (tmp_path / "binary.exe").write_text("binary", encoding="utf-8")
        (tmp_path / "image.png").write_text("image", encoding="utf-8")

        resources = discover_resources(tmp_path)
        names = {r.name for r in resources}
        assert "doc.md" in names
        assert "binary.exe" not in names
        assert "image.png" not in names
