"""Tests for JSON parsing in enrichment and wiki selector crews."""

import pytest


class TestEnrichmentJSONParsing:
    """Test JSON parsing in enrichment crew."""

    def test_parse_json_response_with_updated_sections(self):
        """Test parsing JSON response with updated_sections field."""
        # Mock result with JSON response
        result_str = """{
            "updated_sections": "# Updated Documentation\\n\\nThis is the updated content.",
            "needs_update": true
        }"""

        # Simulate the parsing logic from the enrichment crew
        import json

        parsed = json.loads(result_str)

        assert parsed["needs_update"] is True
        assert parsed["updated_sections"] == "# Updated Documentation\n\nThis is the updated content."

    def test_parse_json_in_markdown_code_block(self):
        """Test parsing JSON wrapped in markdown code blocks."""
        # Test the parsing logic directly
        result_str = """```json
{
    "updated_sections": "# New Content\\n\\nUpdated documentation here.",
    "needs_update": true
}
```"""

        # Import the parsing logic
        import json
        import re

        # Extract JSON from code block
        json_match = re.search(r"```(?:json)?\n(.*?)\n```", result_str, re.DOTALL)
        assert json_match is not None

        json_str = json_match.group(1)
        parsed = json.loads(json_str)

        assert parsed["needs_update"] is True
        assert "# New Content" in parsed["updated_sections"]

    def test_fallback_to_markdown_extraction(self):
        """Test fallback to markdown extraction when not JSON."""
        result_str = """```markdown
# Updated README

This is the new content for the README file.
```"""

        import re

        # Try JSON first (should fail)
        # Fall back to markdown
        code_block_match = re.search(r"```(?:markdown)?\n(.*?)\n```", result_str, re.DOTALL)
        assert code_block_match is not None

        content = code_block_match.group(1)
        assert "# Updated README" in content
        assert "This is the new content" in content


class TestWikiSelectorJSONParsing:
    """Test JSON parsing in wiki selector crew."""

    def test_parse_json_response_with_selected_articles(self):
        """Test parsing JSON response with selected_articles field."""
        result_str = """{
            "selected_articles": ["Usage.md", "Configuration.md", "Installation.md"]
        }"""

        wiki_files = ["Usage.md", "Configuration.md", "Installation.md", "FAQ.md"]

        # Test the parsing logic
        import json

        parsed = json.loads(result_str)

        assert "selected_articles" in parsed
        selected = parsed["selected_articles"]

        # Filter to only valid wiki files
        filtered = [f for f in selected if f in wiki_files]

        assert filtered == ["Usage.md", "Configuration.md", "Installation.md"]

    def test_parse_json_list_directly(self):
        """Test parsing direct JSON list of articles."""
        result_str = '["Usage.md", "Configuration.md"]'
        wiki_files = ["Usage.md", "Configuration.md", "FAQ.md"]

        import json

        parsed = json.loads(result_str)

        assert isinstance(parsed, list)
        filtered = [f for f in parsed if f in wiki_files]

        assert filtered == ["Usage.md", "Configuration.md"]

    def test_fallback_to_regex_parsing(self):
        """Test fallback to regex when not valid JSON."""
        result_str = """Based on the changes, I recommend updating:
        - "Usage.md" for the new commands
        - "Configuration.md" for the new settings
        """

        wiki_files = ["Usage.md", "Configuration.md", "FAQ.md"]

        import re

        # This should fail JSON parsing
        try:
            import json

            json.loads(result_str)
            raise AssertionError("Should have failed JSON parsing")
        except json.JSONDecodeError:
            # Fall back to regex
            matches = re.findall(r'["\']([A-Za-z-]+\.md)["\']', result_str)
            filtered = [m for m in matches if m in wiki_files]

            assert filtered == ["Usage.md", "Configuration.md"]

    def test_fallback_to_text_search(self):
        """Test fallback to simple text search."""
        result_str = "We should update Usage.md and Configuration.md based on these changes."
        wiki_files = ["Usage.md", "Configuration.md", "FAQ.md"]

        # No quotes, so regex won't match
        import re

        matches = re.findall(r'["\']([A-Za-z-]+\.md)["\']', result_str)
        assert matches == []

        # Fall back to text search
        selected = []
        for wiki_file in wiki_files:
            if wiki_file in result_str:
                selected.append(wiki_file)

        assert selected == ["Usage.md", "Configuration.md"]


class TestIntegrationScenarios:
    """Test integration scenarios that caused issues."""

    def test_json_not_written_to_file(self):
        """Test that JSON response is not written directly to files."""
        # This test verifies the fix we made
        # Mock a JSON response that was being written to files
        json_response = """{
  "updated_sections": "# Project\\n\\nThis is the actual content that should be written.",
  "needs_update": true
}"""

        # The crew should parse this and return only the content
        import json

        parsed = json.loads(json_response)

        # What should be written to file
        content_to_write = parsed["updated_sections"]

        # Ensure we're not writing the JSON structure
        assert "{" not in content_to_write
        assert '"updated_sections"' not in content_to_write
        assert content_to_write.startswith("# Project")

    @pytest.mark.parametrize(
        "crew_output,expected_articles",
        [
            # JSON with selected_articles
            ('{"selected_articles": ["Usage.md", "FAQ.md"]}', ["Usage.md", "FAQ.md"]),
            # JSON list
            ('["Configuration.md", "Installation.md"]', ["Configuration.md", "Installation.md"]),
            # JSON in code block
            ('```json\n{"selected_articles": ["Usage.md"]}\n```', ["Usage.md"]),
            # Plain text with quotes
            ('Update "Usage.md" and "Configuration.md"', ["Usage.md", "Configuration.md"]),
            # Plain text without quotes
            ("Update Usage.md and Configuration.md files", ["Usage.md", "Configuration.md"]),
        ],
    )
    def test_wiki_selector_various_formats(self, crew_output, expected_articles):
        """Test wiki selector handles various output formats."""
        wiki_files = ["Usage.md", "Configuration.md", "Installation.md", "FAQ.md"]

        # Import the parsing logic components
        import json
        import re

        selected = []

        # Try JSON parsing first
        try:
            # Remove code blocks if present
            json_match = re.search(r"```(?:json)?\n(.*?)\n```", crew_output, re.DOTALL)
            json_str = json_match.group(1) if json_match else crew_output

            parsed = json.loads(json_str)
            if isinstance(parsed, dict) and "selected_articles" in parsed:
                selected = [f for f in parsed["selected_articles"] if f in wiki_files]
            elif isinstance(parsed, list):
                selected = [f for f in parsed if f in wiki_files]
        except (json.JSONDecodeError, AttributeError):
            # Try regex
            matches = re.findall(r'["\']([A-Za-z-]+\.md)["\']', crew_output)
            if matches:
                selected = [m for m in matches if m in wiki_files]
            else:
                # Text search
                for wiki_file in wiki_files:
                    if wiki_file in crew_output:
                        selected.append(wiki_file)

        assert selected == expected_articles
