"""Tests for common.py: log function, constants, review strategies."""

import io
from pathlib import Path
from unittest.mock import patch

import common


class TestLog:
    def test_writes_to_fh(self):
        fh = io.StringIO()
        common.log(fh, "test message", also_stdout=False)
        output = fh.getvalue()
        assert "test message" in output
        assert output.endswith("\n")

    def test_includes_timestamp(self):
        fh = io.StringIO()
        common.log(fh, "hello", also_stdout=False)
        output = fh.getvalue()
        assert "[" in output and "]" in output

    def test_also_stdout(self, capsys):
        fh = io.StringIO()
        common.log(fh, "to stdout", also_stdout=True)
        captured = capsys.readouterr()
        assert "to stdout" in captured.out

    def test_suppress_stdout(self, capsys):
        fh = io.StringIO()
        common.log(fh, "no stdout", also_stdout=False)
        captured = capsys.readouterr()
        assert captured.out == ""

    def test_handles_broken_pipe(self):
        fh = io.StringIO()
        with patch("sys.stdout.write", side_effect=BrokenPipeError):
            common.log(fh, "should not crash", also_stdout=True)
        assert "should not crash" in fh.getvalue()


class TestConstants:
    def test_phase_hard_timeout(self):
        assert common.PHASE_HARD_TIMEOUT == 90 * 60

    def test_max_iterations_effectively_infinite(self):
        assert common.MAX_ITERATIONS >= 999_999

    def test_task_num_width(self):
        assert common.TASK_NUM_WIDTH == 4

    def test_review_strategies_not_empty(self):
        assert len(common.REVIEW_STRATEGIES) > 0

    def test_review_strategies_have_required_keys(self):
        for s in common.REVIEW_STRATEGIES:
            assert "name" in s
            assert "focus" in s
            assert isinstance(s["name"], str)
            assert isinstance(s["focus"], str)

    def test_review_strategy_names_unique(self):
        names = [s["name"] for s in common.REVIEW_STRATEGIES]
        assert len(names) == len(set(names))

    def test_default_cursor_model(self):
        assert "opus" in common.DEFAULT_CURSOR_MODEL.lower() or "claude" in common.DEFAULT_CURSOR_MODEL.lower()


class TestPaths:
    def test_script_dir_exists(self):
        assert common.SCRIPT_DIR.exists()

    def test_autobuilder_dir_exists(self):
        assert common.AUTOBUILDER_DIR.exists()

    def test_path_hierarchy(self):
        assert common.SCRIPT_DIR.parent.parent == common.AUTOBUILDER_DIR
        assert common.AUTOBUILDER_DIR.parent == common.REPO_ROOT
