"""
Unit tests for buffer.py.

Tests verify:
- Pending operations are written and read correctly
- Buffer is cleared after replay
- Fail-fast: write failures raise BufferError immediately
- has_pending correctly detects presence/absence of buffer
"""

from __future__ import annotations

import json
from pathlib import Path

import pytest

from active_claude_github_mcp.buffer import (
    BufferError,
    clear_pending,
    has_pending,
    read_pending,
    write_pending,
)


class TestWritePending:
    def test_creates_buffer_file(self, tmp_path):
        path = write_pending(tmp_path, "post_turn", {"thread_id": "D_abc"}, "timeout")
        assert path.exists()

    def test_appends_multiple_entries(self, tmp_path):
        write_pending(tmp_path, "post_turn", {"thread_id": "D_1"}, "error 1")
        write_pending(tmp_path, "create_issue", {"title": "bug"}, "error 2")
        pending = read_pending(tmp_path)
        assert len(pending) == 2

    def test_creates_claude_dir_if_missing(self, tmp_path):
        # No .claude/ dir exists yet
        write_pending(tmp_path, "post_turn", {}, "err")
        assert (tmp_path / ".claude").exists()

    def test_entry_contains_tool_name(self, tmp_path):
        write_pending(tmp_path, "my_tool", {"key": "val"}, "some error")
        pending = read_pending(tmp_path)
        assert pending[0]["tool"] == "my_tool"

    def test_entry_contains_error_message(self, tmp_path):
        write_pending(tmp_path, "post_turn", {}, "connection refused")
        pending = read_pending(tmp_path)
        assert pending[0]["error"] == "connection refused"

    def test_entry_contains_args(self, tmp_path):
        args = {"thread_id": "D_abc", "body": "hello"}
        write_pending(tmp_path, "post_turn", args, "err")
        pending = read_pending(tmp_path)
        assert pending[0]["args"] == args


class TestReadPending:
    def test_returns_empty_list_if_no_buffer(self, tmp_path):
        assert read_pending(tmp_path) == []

    def test_does_not_clear_after_read(self, tmp_path):
        write_pending(tmp_path, "post_turn", {}, "err")
        read_pending(tmp_path)
        assert has_pending(tmp_path)


class TestClearPending:
    def test_deletes_buffer_file(self, tmp_path):
        write_pending(tmp_path, "post_turn", {}, "err")
        assert has_pending(tmp_path)
        clear_pending(tmp_path)
        assert not has_pending(tmp_path)

    def test_no_error_if_no_buffer(self, tmp_path):
        # Should not raise
        clear_pending(tmp_path)


class TestHasPending:
    def test_false_when_no_buffer(self, tmp_path):
        assert not has_pending(tmp_path)

    def test_true_after_write(self, tmp_path):
        write_pending(tmp_path, "post_turn", {}, "err")
        assert has_pending(tmp_path)

    def test_false_after_clear(self, tmp_path):
        write_pending(tmp_path, "post_turn", {}, "err")
        clear_pending(tmp_path)
        assert not has_pending(tmp_path)

    def test_false_when_file_empty(self, tmp_path):
        (tmp_path / ".claude").mkdir()
        (tmp_path / ".claude" / "pending-posts.md").touch()
        assert not has_pending(tmp_path)

    def test_false_when_file_whitespace_only(self, tmp_path):
        (tmp_path / ".claude").mkdir()
        (tmp_path / ".claude" / "pending-posts.md").write_text("\n\n   \n")
        assert not has_pending(tmp_path)

    def test_true_when_file_has_pending_section(self, tmp_path):
        (tmp_path / ".claude").mkdir()
        (tmp_path / ".claude" / "pending-posts.md").write_text(
            "\n## Pending — 2026-04-23T00:00:00+00:00\n"
            "**Tool:** `post_turn`\n"
        )
        assert has_pending(tmp_path)
if __name__ == "__main__":
    import sys
    import pytest
    sys.exit(pytest.main([__file__, "-v"]))
