"""Unit tests for github.py — Issue operations.

Covers create_issue, get_issue_body, close_issue.
"""
from __future__ import annotations

import json
from unittest.mock import MagicMock, patch

import pytest

from active_claude_github_mcp.github.core import GitHubError
from active_claude_github_mcp.github.issues import (
    close_issue,
    create_issue,
    get_issue_body,
)


TOKEN = "ghp_test_token"


def _mock_response(data: dict, status_code: int = 200):
    mock = MagicMock()
    mock.status_code = status_code
    mock.json.return_value = data
    mock.text = json.dumps(data)
    return mock


class TestCreateIssue:
    def test_success(self):
        response_data = {
            "data": {
                "createIssue": {
                    "issue": {
                        "id": "I_issue123",
                        "number": 3,
                        "url": "https://github.com/owner/repo/issues/3",
                    }
                }
            }
        }
        with patch("httpx.post", return_value=_mock_response(response_data)):
            result = create_issue(
                TOKEN, "R_repo123", "Bug title", "Bug body", ["LA_label123"]
            )
        assert result["number"] == 3

    def test_empty_title_raises(self):
        with pytest.raises(ValueError, match="title"):
            create_issue(TOKEN, "R_repo123", "", "body", [])


class TestGetIssueBody:
    def test_success(self):
        response_data = {"data": {"node": {"body": "## Overview\nsubtasks..."}}}
        with patch("httpx.post", return_value=_mock_response(response_data)):
            body = get_issue_body(TOKEN, "I_abc123")
        assert "Overview" in body

    def test_missing_issue_raises(self):
        response_data = {"data": {"node": None}}
        with patch("httpx.post", return_value=_mock_response(response_data)):
            with pytest.raises(GitHubError, match="not found"):
                get_issue_body(TOKEN, "I_missing")

    def test_empty_id_raises(self):
        with pytest.raises(ValueError, match="issue_id"):
            get_issue_body(TOKEN, "")


class TestCloseIssue:
    def test_completed(self):
        response_data = {
            "data": {
                "closeIssue": {
                    "issue": {
                        "url": "https://github.com/o/r/issues/42",
                        "closedAt": "2026-04-23T17:00:00Z",
                    }
                }
            }
        }
        captured = {}

        def _capture(url, headers, json, timeout):
            captured["variables"] = json.get("variables", {})
            return _mock_response(response_data)

        with patch("httpx.post", side_effect=_capture):
            out = close_issue(TOKEN, "I_abc", state_reason="completed")
        assert out["url"].endswith("/42")
        assert out["closed_at"].startswith("2026-04-23")
        assert captured["variables"]["reason"] == "COMPLETED"

    def test_not_planned(self):
        response_data = {
            "data": {
                "closeIssue": {
                    "issue": {
                        "url": "https://github.com/o/r/issues/43",
                        "closedAt": "2026-04-23T18:00:00Z",
                    }
                }
            }
        }
        captured = {}

        def _capture(url, headers, json, timeout):
            captured["variables"] = json.get("variables", {})
            return _mock_response(response_data)

        with patch("httpx.post", side_effect=_capture):
            close_issue(TOKEN, "I_abc", state_reason="not_planned")
        assert captured["variables"]["reason"] == "NOT_PLANNED"

    def test_empty_issue_id_raises(self):
        with pytest.raises(ValueError, match="issue_id"):
            close_issue(TOKEN, "", state_reason="completed")

    def test_invalid_state_reason_raises(self):
        with pytest.raises(ValueError, match="state_reason"):
            close_issue(TOKEN, "I_abc", state_reason="bogus")
if __name__ == "__main__":
    import sys
    import pytest
    sys.exit(pytest.main([__file__, "-v"]))
