"""Tests for formatters module."""

import json

from priorart.formatters import format_json, format_markdown, format_table

SAMPLE_RESULT = {
    "query": "AI personal finance tracker",
    "queries": ["AI personal finance tracker", "AI personal finance"],
    "sources": [
        {
            "type": "github",
            "results": [
                {
                    "name": "org/finance-ai",
                    "stars": 1234,
                    "description": "AI-powered finance tracker",
                    "url": "https://github.com/org/finance-ai",
                    "updated": "2024-01-01",
                    "language": "Python",
                },
            ],
        },
        {
            "type": "hn",
            "results": [
                {
                    "title": "Ask HN: Best AI finance tools?",
                    "points": 42,
                    "comments": 17,
                    "url": "https://news.ycombinator.com/item?id=12345",
                    "date": "2024-03-01",
                },
            ],
        },
    ],
    "signal": {
        "score": 45,
        "verdict": "MODERATE",
        "breakdown": {"github": 30, "hn": 15},
    },
    "meta": {
        "timestamp": "2026-03-07T00:00:00+00:00",
        "version": "0.1.0",
    },
}

EMPTY_RESULT = {
    "query": "totally obscure niche idea",
    "queries": ["totally obscure niche idea"],
    "sources": [
        {"type": "github", "results": []},
        {"type": "hn", "results": []},
    ],
    "signal": {"score": 0, "verdict": "LOW", "breakdown": {"github": 0, "hn": 0}},
    "meta": {"timestamp": "2026-03-07T00:00:00+00:00", "version": "0.1.0"},
}


class TestFormatJson:
    def test_returns_valid_json(self):
        output = format_json(SAMPLE_RESULT)
        parsed = json.loads(output)
        assert parsed["query"] == "AI personal finance tracker"

    def test_json_has_required_keys(self):
        parsed = json.loads(format_json(SAMPLE_RESULT))
        assert "query" in parsed
        assert "sources" in parsed
        assert "signal" in parsed
        assert "meta" in parsed

    def test_signal_structure(self):
        parsed = json.loads(format_json(SAMPLE_RESULT))
        signal = parsed["signal"]
        assert "score" in signal
        assert "verdict" in signal
        assert "breakdown" in signal

    def test_empty_results_valid_json(self):
        output = format_json(EMPTY_RESULT)
        parsed = json.loads(output)
        assert parsed["signal"]["score"] == 0


class TestFormatMarkdown:
    def test_contains_header(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "## 🔍 Prior Art Scan" in output

    def test_contains_signal(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "45/100" in output

    def test_contains_verdict_moderate(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "MODERATE" in output

    def test_contains_github_section(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "### GitHub Repositories" in output
        assert "org/finance-ai" in output

    def test_contains_hn_section(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "### Hacker News Discussions" in output
        assert "Ask HN: Best AI finance tools?" in output

    def test_empty_shows_no_results_message(self):
        output = format_markdown(EMPTY_RESULT)
        assert "No relevant repositories found." in output
        assert "No relevant discussions found." in output

    def test_pipe_in_description_escaped(self):
        result = {
            **SAMPLE_RESULT,
            "sources": [
                {
                    "type": "github",
                    "results": [
                        {
                            "name": "org/repo",
                            "stars": 100,
                            "description": "A | B tool",
                            "url": "https://github.com/org/repo",
                            "updated": "2024-01-01",
                            "language": "Python",
                        }
                    ],
                },
                {"type": "hn", "results": []},
            ],
        }
        output = format_markdown(result)
        assert "A \\| B tool" in output

    def test_low_verdict_label(self):
        output = format_markdown(EMPTY_RESULT)
        assert "🟢 LOW" in output

    def test_high_verdict_label(self):
        high_result = {
            **SAMPLE_RESULT,
            "signal": {
                "score": 75,
                "verdict": "HIGH",
                "breakdown": {"github": 60, "hn": 15},
            },
        }
        output = format_markdown(high_result)
        assert "🔴 HIGH" in output


class TestFormatTable:
    def test_contains_title(self):
        output = format_table(SAMPLE_RESULT)
        assert "Prior Art Scan" in output

    def test_contains_signal(self):
        output = format_table(SAMPLE_RESULT)
        assert "45/100" in output
        assert "MODERATE" in output

    def test_contains_github_section(self):
        output = format_table(SAMPLE_RESULT)
        assert "GitHub Repositories" in output
        assert "org/finance-ai" in output

    def test_contains_hn_section(self):
        output = format_table(SAMPLE_RESULT)
        assert "Hacker News Discussions" in output
        assert "Ask HN" in output

    def test_empty_shows_no_results(self):
        output = format_table(EMPTY_RESULT)
        assert "No relevant repositories found." in output
        assert "No relevant discussions found." in output

    def test_star_count_comma_formatted(self):
        output = format_table(SAMPLE_RESULT)
        assert "1,234" in output

    def test_shows_hn_url(self):
        output = format_table(SAMPLE_RESULT)
        assert "https://news.ycombinator.com/item?id=12345" in output

    def test_shows_queries(self):
        output = format_table(SAMPLE_RESULT)
        assert "AI personal finance tracker" in output


# ---------------------------------------------------------------------------
# Additional cross-format edge cases
# ---------------------------------------------------------------------------


class TestFormatJsonEdgeCases:
    def test_output_is_pretty_printed(self):
        output = format_json(SAMPLE_RESULT)
        # Pretty-printed JSON has newlines and indentation
        assert "\n" in output
        assert "  " in output

    def test_preserves_all_source_types(self):
        parsed = __import__("json").loads(format_json(SAMPLE_RESULT))
        types = [s["type"] for s in parsed["sources"]]
        assert "github" in types
        assert "hn" in types


class TestFormatMarkdownEdgeCases:
    def test_shows_queries_in_output(self):
        output = format_markdown(SAMPLE_RESULT)
        # Queries listed with backtick formatting
        assert "`AI personal finance tracker`" in output

    def test_caps_repos_at_8_rows(self):
        many_repos = [
            {
                "name": f"org/repo{i}",
                "stars": 100 - i,
                "description": f"Repo {i}",
                "url": f"https://github.com/org/repo{i}",
                "updated": "2024-01-01",
                "language": "Python",
            }
            for i in range(9)
        ]
        result = {
            **SAMPLE_RESULT,
            "sources": [
                {"type": "github", "results": many_repos},
                {"type": "hn", "results": []},
            ],
        }
        output = format_markdown(result)
        # Only first 8 repos should appear; repo8 should NOT
        assert "org/repo7" in output
        assert "org/repo8" not in output

    def test_hn_shows_points_and_comments(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "42 pts" in output
        assert "17 comments" in output

    def test_moderate_verdict_label(self):
        output = format_markdown(SAMPLE_RESULT)
        assert "🟡 MODERATE" in output
