"""
Tests for Phase 4: Router Generation with GitHub Integration

Tests the enhanced router generator that integrates GitHub insights:
- Enhanced topic definition using issue labels (2x weight)
- Router template with repository stats and top issues
- Sub-skill templates with "Common Issues" section
- GitHub issue linking
"""

import json

from skill_seekers.cli.generate_router import RouterGenerator
from skill_seekers.cli.github_fetcher import CodeStream, DocsStream, InsightsStream, ThreeStreamData


class TestRouterGeneratorBasic:
    """Test basic router generation without GitHub streams (backward compat)."""

    def test_router_generator_init(self, tmp_path):
        """Test router generator initialization."""
        # Create test configs
        config1 = {
            "name": "test-oauth",
            "description": "OAuth authentication",
            "base_url": "https://example.com",
            "categories": {"authentication": ["auth", "oauth"]},
        }
        config2 = {
            "name": "test-async",
            "description": "Async operations",
            "base_url": "https://example.com",
            "categories": {"async": ["async", "await"]},
        }

        config_path1 = tmp_path / "config1.json"
        config_path2 = tmp_path / "config2.json"

        with open(config_path1, "w") as f:
            json.dump(config1, f)
        with open(config_path2, "w") as f:
            json.dump(config2, f)

        # Create generator
        generator = RouterGenerator([str(config_path1), str(config_path2)])

        assert generator.router_name == "test"
        assert len(generator.configs) == 2
        assert generator.github_streams is None

    def test_infer_router_name(self, tmp_path):
        """Test router name inference from sub-skill names."""
        config1 = {"name": "fastmcp-oauth", "base_url": "https://example.com"}
        config2 = {"name": "fastmcp-async", "base_url": "https://example.com"}

        config_path1 = tmp_path / "config1.json"
        config_path2 = tmp_path / "config2.json"

        with open(config_path1, "w") as f:
            json.dump(config1, f)
        with open(config_path2, "w") as f:
            json.dump(config2, f)

        generator = RouterGenerator([str(config_path1), str(config_path2)])

        assert generator.router_name == "fastmcp"

    def test_extract_routing_keywords_basic(self, tmp_path):
        """Test basic keyword extraction without GitHub."""
        config = {
            "name": "test-oauth",
            "base_url": "https://example.com",
            "categories": {"authentication": ["auth", "oauth"], "tokens": ["token", "jwt"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        generator = RouterGenerator([str(config_path)])
        routing = generator.extract_routing_keywords()

        assert "test-oauth" in routing
        keywords = routing["test-oauth"]
        assert "authentication" in keywords
        assert "tokens" in keywords
        assert "oauth" in keywords  # From name


class TestRouterGeneratorWithGitHub:
    """Test router generation with GitHub streams (Phase 4)."""

    def test_router_with_github_metadata(self, tmp_path):
        """Test router generator with GitHub metadata."""
        config = {
            "name": "test-oauth",
            "description": "OAuth skill",
            "base_url": "https://github.com/test/repo",
            "categories": {"oauth": ["oauth", "auth"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        # Create GitHub streams
        code_stream = CodeStream(directory=tmp_path, files=[])
        docs_stream = DocsStream(
            readme="# Test Project\n\nA test OAuth library.", contributing=None, docs_files=[]
        )
        insights_stream = InsightsStream(
            metadata={
                "stars": 1234,
                "forks": 56,
                "language": "Python",
                "description": "OAuth helper",
            },
            common_problems=[
                {
                    "title": "OAuth fails on redirect",
                    "number": 42,
                    "state": "open",
                    "comments": 15,
                    "labels": ["bug", "oauth"],
                }
            ],
            known_solutions=[],
            top_labels=[{"label": "oauth", "count": 20}, {"label": "bug", "count": 10}],
        )
        github_streams = ThreeStreamData(code_stream, docs_stream, insights_stream)

        # Create generator with GitHub streams
        generator = RouterGenerator([str(config_path)], github_streams=github_streams)

        assert generator.github_metadata is not None
        assert generator.github_metadata["stars"] == 1234
        assert generator.github_docs is not None
        assert generator.github_docs["readme"].startswith("# Test Project")
        assert generator.github_issues is not None

    def test_extract_keywords_with_github_labels(self, tmp_path):
        """Test keyword extraction with GitHub issue labels (2x weight)."""
        config = {
            "name": "test-oauth",
            "base_url": "https://example.com",
            "categories": {"oauth": ["oauth", "auth"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        # Create GitHub streams with top labels
        code_stream = CodeStream(directory=tmp_path, files=[])
        docs_stream = DocsStream(readme=None, contributing=None, docs_files=[])
        insights_stream = InsightsStream(
            metadata={},
            common_problems=[],
            known_solutions=[],
            top_labels=[
                {"label": "oauth", "count": 50},  # Matches 'oauth' keyword
                {"label": "authentication", "count": 30},  # Related
                {"label": "bug", "count": 20},  # Not related
            ],
        )
        github_streams = ThreeStreamData(code_stream, docs_stream, insights_stream)

        generator = RouterGenerator([str(config_path)], github_streams=github_streams)
        routing = generator.extract_routing_keywords()

        keywords = routing["test-oauth"]
        # 'oauth' label should appear twice (2x weight)
        oauth_count = keywords.count("oauth")
        assert oauth_count >= 4  # Base 'oauth' from categories + name + 2x from label

    def test_generate_skill_md_with_github(self, tmp_path):
        """Test SKILL.md generation with GitHub metadata."""
        config = {
            "name": "test-oauth",
            "description": "OAuth authentication skill",
            "base_url": "https://github.com/test/oauth",
            "categories": {"oauth": ["oauth"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        # Create GitHub streams
        code_stream = CodeStream(directory=tmp_path, files=[])
        docs_stream = DocsStream(
            readme="# OAuth Library\n\nQuick start: Install with pip install oauth",
            contributing=None,
            docs_files=[],
        )
        insights_stream = InsightsStream(
            metadata={
                "stars": 5000,
                "forks": 200,
                "language": "Python",
                "description": "OAuth 2.0 library",
            },
            common_problems=[
                {
                    "title": "Redirect URI mismatch",
                    "number": 100,
                    "state": "open",
                    "comments": 25,
                    "labels": ["bug", "oauth"],
                },
                {
                    "title": "Token refresh fails",
                    "number": 95,
                    "state": "open",
                    "comments": 18,
                    "labels": ["oauth"],
                },
            ],
            known_solutions=[],
            top_labels=[],
        )
        github_streams = ThreeStreamData(code_stream, docs_stream, insights_stream)

        generator = RouterGenerator([str(config_path)], github_streams=github_streams)
        skill_md = generator.generate_skill_md()

        # Check GitHub metadata section
        assert "⭐ 5,000" in skill_md
        assert "Python" in skill_md
        assert "OAuth 2.0 library" in skill_md

        # Check Quick Start from README
        assert "## Quick Start" in skill_md
        assert "OAuth Library" in skill_md

        # Check that issue was converted to question in Examples section (Fix 1)
        assert "## Common Issues" in skill_md or "## Examples" in skill_md
        assert (
            "how do i handle redirect uri mismatch" in skill_md.lower()
            or "how do i fix redirect uri mismatch" in skill_md.lower()
        )
        # Note: Issue #100 may appear in Common Issues or as converted question in Examples

    def test_generate_skill_md_without_github(self, tmp_path):
        """Test SKILL.md generation without GitHub (backward compat)."""
        config = {
            "name": "test-oauth",
            "description": "OAuth skill",
            "base_url": "https://example.com",
            "categories": {"oauth": ["oauth"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        # No GitHub streams
        generator = RouterGenerator([str(config_path)])
        skill_md = generator.generate_skill_md()

        # Should not have GitHub-specific sections
        assert "⭐" not in skill_md
        assert "Repository Info" not in skill_md
        assert "Quick Start (from README)" not in skill_md
        assert "Common Issues (from GitHub)" not in skill_md

        # Should have basic sections
        assert "When to Use This Skill" in skill_md
        assert "How It Works" in skill_md


class TestSubSkillIssuesSection:
    """Test sub-skill issue section generation (Phase 4)."""

    def test_generate_subskill_issues_section(self, tmp_path):
        """Test generation of issues section for sub-skills."""
        config = {
            "name": "test-oauth",
            "base_url": "https://example.com",
            "categories": {"oauth": ["oauth"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        # Create GitHub streams with issues
        code_stream = CodeStream(directory=tmp_path, files=[])
        docs_stream = DocsStream(readme=None, contributing=None, docs_files=[])
        insights_stream = InsightsStream(
            metadata={},
            common_problems=[
                {
                    "title": "OAuth redirect fails",
                    "number": 50,
                    "state": "open",
                    "comments": 20,
                    "labels": ["oauth", "bug"],
                },
                {
                    "title": "Token expiration issue",
                    "number": 45,
                    "state": "open",
                    "comments": 15,
                    "labels": ["oauth"],
                },
            ],
            known_solutions=[
                {
                    "title": "Fixed OAuth flow",
                    "number": 40,
                    "state": "closed",
                    "comments": 10,
                    "labels": ["oauth"],
                }
            ],
            top_labels=[],
        )
        github_streams = ThreeStreamData(code_stream, docs_stream, insights_stream)

        generator = RouterGenerator([str(config_path)], github_streams=github_streams)

        # Generate issues section for oauth topic
        issues_section = generator.generate_subskill_issues_section("test-oauth", ["oauth"])

        # Check content
        assert "Common Issues (from GitHub)" in issues_section
        assert "OAuth redirect fails" in issues_section
        assert "Issue #50" in issues_section
        assert "20 comments" in issues_section
        assert "🔴" in issues_section  # Open issue icon
        assert "✅" in issues_section  # Closed issue icon

    def test_generate_subskill_issues_no_matches(self, tmp_path):
        """Test issues section when no issues match the topic."""
        config = {
            "name": "test-async",
            "base_url": "https://example.com",
            "categories": {"async": ["async"]},
        }

        config_path = tmp_path / "config.json"
        with open(config_path, "w") as f:
            json.dump(config, f)

        # Create GitHub streams with oauth issues (not async)
        code_stream = CodeStream(directory=tmp_path, files=[])
        docs_stream = DocsStream(readme=None, contributing=None, docs_files=[])
        insights_stream = InsightsStream(
            metadata={},
            common_problems=[
                {
                    "title": "OAuth fails",
                    "number": 1,
                    "state": "open",
                    "comments": 5,
                    "labels": ["oauth"],
                }
            ],
            known_solutions=[],
            top_labels=[],
        )
        github_streams = ThreeStreamData(code_stream, docs_stream, insights_stream)

        generator = RouterGenerator([str(config_path)], github_streams=github_streams)

        # Generate issues section for async topic (no matches)
        issues_section = generator.generate_subskill_issues_section("test-async", ["async"])

        # Unmatched issues go to 'other' category, so section is generated
        assert "Common Issues (from GitHub)" in issues_section
        assert "Other" in issues_section  # Unmatched issues
        assert "OAuth fails" in issues_section  # The oauth issue


class TestIntegration:
    """Integration tests for Phase 4."""

    def test_full_router_generation_with_github(self, tmp_path):
        """Test complete router generation workflow with GitHub streams."""
        # Create multiple sub-skill configs
        config1 = {
            "name": "fastmcp-oauth",
            "description": "OAuth authentication in FastMCP",
            "base_url": "https://github.com/test/fastmcp",
            "categories": {"oauth": ["oauth", "auth"]},
        }
        config2 = {
            "name": "fastmcp-async",
            "description": "Async operations in FastMCP",
            "base_url": "https://github.com/test/fastmcp",
            "categories": {"async": ["async", "await"]},
        }

        config_path1 = tmp_path / "config1.json"
        config_path2 = tmp_path / "config2.json"

        with open(config_path1, "w") as f:
            json.dump(config1, f)
        with open(config_path2, "w") as f:
            json.dump(config2, f)

        # Create comprehensive GitHub streams
        code_stream = CodeStream(directory=tmp_path, files=[])
        docs_stream = DocsStream(
            readme="# FastMCP\n\nFast MCP server framework.\n\n## Installation\n\n```bash\npip install fastmcp\n```",
            contributing="# Contributing\n\nPull requests welcome!",
            docs_files=[
                {"path": "docs/oauth.md", "content": "# OAuth Guide"},
                {"path": "docs/async.md", "content": "# Async Guide"},
            ],
        )
        insights_stream = InsightsStream(
            metadata={
                "stars": 10000,
                "forks": 500,
                "language": "Python",
                "description": "Fast MCP server framework",
            },
            common_problems=[
                {
                    "title": "OAuth setup fails",
                    "number": 150,
                    "state": "open",
                    "comments": 30,
                    "labels": ["bug", "oauth"],
                },
                {
                    "title": "Async deadlock",
                    "number": 142,
                    "state": "open",
                    "comments": 25,
                    "labels": ["async", "bug"],
                },
                {
                    "title": "Token refresh issue",
                    "number": 130,
                    "state": "open",
                    "comments": 20,
                    "labels": ["oauth"],
                },
            ],
            known_solutions=[
                {
                    "title": "Fixed OAuth redirect",
                    "number": 120,
                    "state": "closed",
                    "comments": 15,
                    "labels": ["oauth"],
                },
                {
                    "title": "Resolved async race",
                    "number": 110,
                    "state": "closed",
                    "comments": 12,
                    "labels": ["async"],
                },
            ],
            top_labels=[
                {"label": "oauth", "count": 45},
                {"label": "async", "count": 38},
                {"label": "bug", "count": 30},
            ],
        )
        github_streams = ThreeStreamData(code_stream, docs_stream, insights_stream)

        # Create router generator
        generator = RouterGenerator(
            [str(config_path1), str(config_path2)], github_streams=github_streams
        )

        # Generate SKILL.md
        skill_md = generator.generate_skill_md()

        # Verify all Phase 4 enhancements present
        # 1. Repository metadata
        assert "⭐ 10,000" in skill_md
        assert "Python" in skill_md
        assert "Fast MCP server framework" in skill_md

        # 2. Quick start from README
        assert "## Quick Start" in skill_md
        assert "pip install fastmcp" in skill_md

        # 3. Sub-skills listed
        assert "fastmcp-oauth" in skill_md
        assert "fastmcp-async" in skill_md

        # 4. Examples section with converted questions (Fix 1)
        assert "## Examples" in skill_md
        # Issues converted to natural questions
        assert (
            "how do i fix oauth setup" in skill_md.lower()
            or "how do i handle oauth setup" in skill_md.lower()
        )
        assert (
            "how do i handle async deadlock" in skill_md.lower()
            or "how do i fix async deadlock" in skill_md.lower()
        )
        # Common Issues section may still exist with other issues
        # Note: Issue numbers may appear in Common Issues or Common Patterns sections

        # 5. Routing keywords include GitHub labels (2x weight)
        routing = generator.extract_routing_keywords()
        oauth_keywords = routing["fastmcp-oauth"]
        async_keywords = routing["fastmcp-async"]

        # Labels should be included with 2x weight
        assert oauth_keywords.count("oauth") >= 2
        assert async_keywords.count("async") >= 2

        # Generate config
        router_config = generator.create_router_config()
        assert router_config["name"] == "fastmcp"
        assert router_config["_router"] is True
        assert len(router_config["_sub_skills"]) == 2
