#!/usr/bin/env python3
"""Tests for pr_triage.py — issue #659."""
import json
import sys
from pathlib import Path

import pytest

sys.path.insert(0, str(Path(__file__).resolve().parent.parent / "scripts"))
from pr_triage import categorize, refs, find_dupes, find_stale, to_markdown, to_json


class TestCategorize:
    def test_training_data_pairs(self):
        assert categorize("feat: 500 emotional weather pairs (#603)") == "training_data"

    def test_training_data_scene(self):
        assert categorize("feat: 100 jazz scene descriptions (#612)") == "training_data"

    def test_training_data_corpus(self):
        assert categorize("Add crisis manipulation corpus (#598)") == "training_data"

    def test_bug_fix(self):
        assert categorize("fix: broken import in cli.py") == "bug_fix"

    def test_bug_resolve(self):
        assert categorize("resolve: memory leak in session store") == "bug_fix"

    def test_feature(self):
        assert categorize("feat: add token budget tracker") == "feature"

    def test_feature_new(self):
        assert categorize("new: nightly pipeline scheduler") == "feature"

    def test_docs(self):
        assert categorize("docs: update README config format") == "docs"

    def test_ops(self):
        assert categorize("ops: deploy config to Ezra VPS") == "ops"

    def test_ops_ci(self):
        assert categorize("ci: add smoke test workflow") == "ops"

    def test_security(self):
        assert categorize("security: fix XSS in gallery panel") == "security"

    def test_other(self):
        assert categorize("chore: cleanup whitespace") == "other"

    def test_empty(self):
        assert categorize("") == "other"

    def test_none(self):
        assert categorize(None) == "other"

    def test_case_insensitive(self):
        assert categorize("FIX: Resolve import error") == "bug_fix"


class TestRefs:
    def test_single(self):
        assert refs({"title": "Fix #123", "body": ""}) == [123]

    def test_multiple(self):
        assert refs({"title": "#10", "body": "Related to #20 and #30"}) == [10, 20, 30]

    def test_dedup(self):
        assert refs({"title": "#100", "body": "Closes #100"}) == [100]

    def test_none(self):
        assert refs({"title": "No refs", "body": ""}) == []

    def test_body_only(self):
        assert refs({"title": "Fix", "body": "Closes #42"}) == [42]

    def test_null_body(self):
        assert refs({"title": "#7", "body": None}) == [7]


class TestFindDupes:
    def test_no_dupes(self):
        prs = [{"number": 1, "title": "#10", "body": ""},
               {"number": 2, "title": "#11", "body": ""}]
        assert find_dupes(prs) == {}

    def test_duplicate(self):
        prs = [{"number": 1, "title": "#10", "body": ""},
               {"number": 2, "title": "#10", "body": ""}]
        d = find_dupes(prs)
        assert d[10] == [1, 2]

    def test_triple(self):
        prs = [{"number": i, "title": "#42", "body": ""} for i in range(1, 4)]
        d = find_dupes(prs)
        assert len(d[42]) == 3

    def test_partial_overlap(self):
        prs = [{"number": 1, "title": "#10 #20", "body": ""},
               {"number": 2, "title": "#10", "body": ""}]
        d = find_dupes(prs)
        assert 10 in d
        assert 20 not in d


class TestFindStale:
    def test_clean(self):
        prs = [{"number": 1, "title": "#10", "body": ""}]
        assert find_stale(prs, set()) == []

    def test_stale(self):
        prs = [{"number": 1, "title": "#10", "body": ""}]
        s = find_stale(prs, {10})
        assert len(s) == 1
        assert s[0]["stale_refs"] == [10]

    def test_mixed(self):
        prs = [{"number": 1, "title": "#10 #20", "body": ""}]
        s = find_stale(prs, {10})
        assert s[0]["stale_refs"] == [10]

    def test_multiple_prs(self):
        prs = [
            {"number": 1, "title": "#10", "body": ""},
            {"number": 2, "title": "#20", "body": ""},
        ]
        s = find_stale(prs, {10, 20})
        assert len(s) == 2


class TestToMarkdown:
    def test_basic_structure(self):
        a = {
            "repo": "test/repo", "total_open": 3,
            "total_files_changed": 10, "total_additions": 100, "total_deletions": 20,
            "categories": {"feature": 2, "bug_fix": 1},
            "category_details": {
                "feature": [{"number": 1, "title": "feat: x", "refs": [], "head": "f1", "files": 2, "created": "2026-04-01"}],
                "bug_fix": [],
            },
            "duplicates": {}, "stale_prs": [],
            "closed_issues_checked": 50,
            "safe_merge_candidates": 0,
            "timestamp": "2026-04-14T12:00:00Z",
        }
        md = to_markdown(a)
        assert "test/repo" in md
        assert "3" in md
        assert "feature" in md
        assert "## PR Triage Report" in md

    def test_duplicates_section(self):
        a = {"repo": "x", "total_open": 2, "total_files_changed": 0,
             "total_additions": 0, "total_deletions": 0,
             "categories": {}, "category_details": {},
             "duplicates": {42: [1, 2]}, "stale_prs": [],
             "closed_issues_checked": 0, "safe_merge_candidates": 0,
             "timestamp": "2026-01-01"}
        md = to_markdown(a)
        assert "Duplicate" in md
        assert "#42" in md

    def test_stale_section(self):
        a = {"repo": "x", "total_open": 1, "total_files_changed": 0,
             "total_additions": 0, "total_deletions": 0,
             "categories": {}, "category_details": {},
             "duplicates": {},
             "stale_prs": [{"pr": 5, "title": "old fix", "stale_refs": [10]}],
             "closed_issues_checked": 50, "safe_merge_candidates": 0,
             "timestamp": "2026-01-01"}
        md = to_markdown(a)
        assert "#5" in md
        assert "Stale" in md


class TestToJson:
    def test_roundtrip(self):
        a = {"repo": "test", "total_open": 0}
        out = to_json(a)
        assert json.loads(out)["repo"] == "test"

    def test_complex(self):
        a = {"repo": "x", "duplicates": {1: [2, 3]}, "stale_prs": []}
        out = to_json(a)
        d = json.loads(out)
        assert d["duplicates"]["1"] == [2, 3]
