"""Tests for per-agent Plane comment authorship (feat: per-agent bot author).

Covers:
  * _headers_for: role -> bot token; None/unknown/empty token -> shared fallback.
  * add_comment: author is propagated into the POST headers; no author keeps
    backward-compatible behaviour (shared orchestrator token).

GET/PATCH calls are intentionally NOT covered here: they stay on the shared
token by design and are unchanged by this feature.
"""

import os

# Set env defaults before importing app modules (same convention as the other
# suites) so config/settings load cleanly without a real .env.
os.environ.setdefault("ORCH_PLANE_API_TOKEN", "shared-token")
os.environ.setdefault("ORCH_GITEA_TOKEN", "test-token")

from unittest.mock import patch, MagicMock  # noqa: E402

from src import plane_sync  # noqa: E402


# --------------------------------------------------------------------------- #
# _headers_for
# --------------------------------------------------------------------------- #
def test_headers_for_known_role_uses_bot_token():
    """A known role with a configured token -> that bot's X-API-Key."""
    with patch.dict(plane_sync.PLANE_BOT_TOKENS, {"analyst": "analyst-tok"}, clear=False):
        assert plane_sync._headers_for("analyst") == {"X-API-Key": "analyst-tok"}


def test_headers_for_none_falls_back_to_shared():
    """author=None -> shared orchestrator headers."""
    assert plane_sync._headers_for(None) is plane_sync.PLANE_HEADERS


def test_headers_for_unknown_role_falls_back_to_shared():
    """Unknown role -> shared orchestrator headers."""
    assert plane_sync._headers_for("nope") is plane_sync.PLANE_HEADERS


def test_headers_for_empty_token_falls_back_to_shared():
    """Known role but empty/unconfigured token -> shared orchestrator headers."""
    with patch.dict(plane_sync.PLANE_BOT_TOKENS, {"tester": ""}, clear=False):
        assert plane_sync._headers_for("tester") is plane_sync.PLANE_HEADERS


def test_headers_for_empty_string_author_falls_back_to_shared():
    """author='' -> shared orchestrator headers."""
    assert plane_sync._headers_for("") is plane_sync.PLANE_HEADERS


# --------------------------------------------------------------------------- #
# add_comment
# --------------------------------------------------------------------------- #
def _mock_post_ok():
    resp = MagicMock()
    resp.raise_for_status.return_value = None
    return resp


def test_add_comment_with_author_posts_with_bot_headers():
    """add_comment(author='developer') -> httpx.post called with the developer
    bot's X-API-Key header."""
    with patch.object(plane_sync, "find_issue_id", return_value="issue-uuid"), \
         patch.object(plane_sync, "_resolve_project_id", return_value="proj-uuid"), \
         patch.dict(plane_sync.PLANE_BOT_TOKENS, {"developer": "dev-tok"}, clear=False), \
         patch.object(plane_sync.httpx, "post", return_value=_mock_post_ok()) as mock_post:
        plane_sync.add_comment("ET-001", "hello", author="developer")

    assert mock_post.called
    _, kwargs = mock_post.call_args
    assert kwargs["headers"] == {"X-API-Key": "dev-tok"}


def test_add_comment_without_author_uses_shared_token():
    """add_comment without author -> shared orchestrator headers (backward
    compatible)."""
    with patch.object(plane_sync, "find_issue_id", return_value="issue-uuid"), \
         patch.object(plane_sync, "_resolve_project_id", return_value="proj-uuid"), \
         patch.object(plane_sync.httpx, "post", return_value=_mock_post_ok()) as mock_post:
        plane_sync.add_comment("ET-001", "hello")

    assert mock_post.called
    _, kwargs = mock_post.call_args
    assert kwargs["headers"] is plane_sync.PLANE_HEADERS


def test_add_comment_unknown_author_uses_shared_token():
    """add_comment with an unknown role -> shared orchestrator headers."""
    with patch.object(plane_sync, "find_issue_id", return_value="issue-uuid"), \
         patch.object(plane_sync, "_resolve_project_id", return_value="proj-uuid"), \
         patch.object(plane_sync.httpx, "post", return_value=_mock_post_ok()) as mock_post:
        plane_sync.add_comment("ET-001", "hello", author="ghost")

    assert mock_post.called
    _, kwargs = mock_post.call_args
    assert kwargs["headers"] is plane_sync.PLANE_HEADERS
