"""Tests for cli/terminal_ui.py - progress board, bars, score card."""
import io
import sys
import pytest
from unittest.mock import patch


class TestRenderBar:
    """Test render_bar() ASCII bar generation."""

    def test_zero_score(self):
        from cli.terminal_ui import render_bar
        bar = render_bar(0.0)
        assert len(bar) == 12
        # All empty chars (no filled)
        assert bar.count(bar[0]) == 0 or bar == bar[0] * 12  # all same char

    def test_full_score(self):
        from cli.terminal_ui import render_bar
        bar = render_bar(100.0)
        assert len(bar) == 12

    def test_half_score(self):
        from cli.terminal_ui import render_bar
        bar = render_bar(50.0)
        assert len(bar) == 12

    def test_custom_width(self):
        from cli.terminal_ui import render_bar
        bar = render_bar(50.0, width=20)
        assert len(bar) == 20

    def test_clamps_above_100(self):
        from cli.terminal_ui import render_bar
        bar = render_bar(150.0)
        assert len(bar) == 12

    def test_clamps_below_0(self):
        from cli.terminal_ui import render_bar
        bar = render_bar(-10.0)
        assert len(bar) == 12


class TestRenderScoreCard:
    """Test render_score_card() output."""

    def test_basic_output(self, capsys):
        from cli.terminal_ui import render_score_card
        render_score_card(
            agent_name="codex",
            model_name="gpt-4o",
            headline_score=86.5,
            grade="A",
            behavior_scores=[
                {"behavior_id": "BHV-001-test-cheating", "score": 88.0, "name": "Test Cheating"},
                {"behavior_id": "BHV-002-refactor-complexity", "score": 90.0, "name": "DRY Violation"},
                {"behavior_id": "BHV-003-error-handling", "score": 84.0, "name": "Error Swallowing"},
                {"behavior_id": "BHV-004-loop-detection", "score": 82.0, "name": "Silent Failure"},
            ],
            passed_count=4,
            total_count=4,
            duration_ms=120000,
        )
        output = capsys.readouterr().out
        assert "codex / gpt-4o" in output
        assert "86.5" in output
        assert "Code Quality" in output
        assert "Error Resilience" in output
        assert "4/4 passed" in output

    def test_baseline_delta_shown(self, capsys):
        from cli.terminal_ui import render_score_card
        render_score_card(
            agent_name="codex",
            model_name=None,
            headline_score=86.5,
            grade="A",
            behavior_scores=[
                {"behavior_id": "BHV-001-test-cheating", "score": 88.0, "name": "Test"},
                {"behavior_id": "BHV-002-refactor-complexity", "score": 85.0, "name": "DRY"},
                {"behavior_id": "BHV-003-error-handling", "score": 84.0, "name": "Err"},
                {"behavior_id": "BHV-004-loop-detection", "score": 82.0, "name": "Loop"},
            ],
            baseline_delta=2.3,
            passed_count=4,
            total_count=4,
            duration_ms=60000,
        )
        output = capsys.readouterr().out
        assert "+2.3" in output
        assert "baseline" in output

    def test_no_baseline_delta(self, capsys):
        from cli.terminal_ui import render_score_card
        render_score_card(
            agent_name="test",
            model_name=None,
            headline_score=50.0,
            grade="C",
            behavior_scores=[],
            baseline_delta=None,
            passed_count=0,
            total_count=0,
            duration_ms=0,
        )
        output = capsys.readouterr().out
        assert "baseline" not in output


class TestProgressBoard:
    """Test ProgressBoard state management (not ANSI rendering)."""

    def test_initial_state(self):
        from cli.terminal_ui import ProgressBoard
        board = ProgressBoard(
            behavior_ids=["BHV-001", "BHV-002"],
            behavior_names=["Test", "DRY"],
        )
        assert board.total == 2
        assert board.states["BHV-001"] == "pending"
        assert board.states["BHV-002"] == "pending"

    def test_start_behavior(self):
        from cli.terminal_ui import ProgressBoard
        with patch.object(ProgressBoard, '_render_all'):
            board = ProgressBoard(["BHV-001"], ["Test"])
            board.ansi = False  # Force dumb mode for testing
            with patch('builtins.print'):
                board.start_behavior("BHV-001")
            assert board.states["BHV-001"] == "running"

    def test_finish_behavior(self):
        from cli.terminal_ui import ProgressBoard
        with patch.object(ProgressBoard, '_render_all'):
            board = ProgressBoard(["BHV-001"], ["Test"])
            board.ansi = False
            with patch('builtins.print'):
                board.start_behavior("BHV-001")
                board.finish_behavior("BHV-001", success=True, duration_ms=5000)
            assert board.states["BHV-001"] == "done"
            assert "5s" in board.times["BHV-001"]

    def test_finish_failure(self):
        from cli.terminal_ui import ProgressBoard
        with patch.object(ProgressBoard, '_render_all'):
            board = ProgressBoard(["BHV-001"], ["Test"])
            board.ansi = False
            with patch('builtins.print'):
                board.start_behavior("BHV-001")
                board.finish_behavior("BHV-001", success=False, duration_ms=300000)
            assert board.states["BHV-001"] == "failed"

    def test_elapsed_format_minutes(self):
        from cli.terminal_ui import _format_elapsed
        assert _format_elapsed(125) == "2m 5s"
        assert _format_elapsed(45) == "45s"
        assert _format_elapsed(0) == "0s"


class TestScoreCardVisualContent:
    """Verify the score card contains expected structural elements."""

    def test_axis_scores_computed_correctly(self, capsys):
        from cli.terminal_ui import render_score_card
        render_score_card(
            agent_name="test-agent",
            model_name="test-model",
            headline_score=85.0,
            grade="A",
            behavior_scores=[
                {"behavior_id": "BHV-001-test-cheating", "score": 90.0, "name": "T1"},
                {"behavior_id": "BHV-002-refactor-complexity", "score": 80.0, "name": "T2"},
                {"behavior_id": "BHV-003-error-handling", "score": 88.0, "name": "T3"},
                {"behavior_id": "BHV-004-loop-detection", "score": 82.0, "name": "T4"},
            ],
            passed_count=4,
            total_count=4,
            duration_ms=120000,
        )
        output = capsys.readouterr().out
        # Code Quality = avg(BHV-001=90, BHV-002=80) = 85.0
        assert "85.0" in output
        # Error Resilience = avg(BHV-003=88, BHV-004=82) = 85.0
        # Both should appear
        assert "Code Quality" in output
        assert "Error Resilience" in output
        assert "test-agent / test-model" in output
        assert "2m 0s" in output  # 120000ms = 2m 0s
        assert "4/4 passed" in output

    def test_duration_formatting(self, capsys):
        from cli.terminal_ui import render_score_card
        render_score_card(
            agent_name="x", model_name=None, headline_score=0, grade="F",
            behavior_scores=[], passed_count=0, total_count=0,
            duration_ms=45000,
        )
        output = capsys.readouterr().out
        assert "45s" in output

    def test_negative_baseline_delta(self, capsys):
        from cli.terminal_ui import render_score_card
        render_score_card(
            agent_name="x", model_name=None, headline_score=70, grade="B",
            behavior_scores=[], baseline_delta=-5.2,
            passed_count=0, total_count=0, duration_ms=0,
        )
        output = capsys.readouterr().out
        assert "-5.2" in output


class TestProgressBoardDumbOutput:
    """Test ProgressBoard dumb-mode output (what piped/CI users see)."""

    def test_dumb_mode_full_lifecycle(self, capsys):
        from cli.terminal_ui import ProgressBoard
        board = ProgressBoard(
            behavior_ids=["BHV-001-test-cheating", "BHV-002-refactor-complexity"],
            behavior_names=["Test Cheating", "DRY Violation"],
        )
        board.ansi = False  # Force dumb mode
        board.start_behavior("BHV-001-test-cheating")
        board.finish_behavior("BHV-001-test-cheating", success=True, duration_ms=47000)
        board.start_behavior("BHV-002-refactor-complexity")
        board.finish_behavior("BHV-002-refactor-complexity", success=False, duration_ms=300000)

        output = capsys.readouterr().out
        assert "BHV-001" in output
        assert "BHV-002" in output
        assert "47s" in output
        assert "5m 0s" in output


class TestAxisKeyNormalization:
    """Test _axis_key and _short_behavior_id helpers."""

    def test_full_id_normalized(self):
        from cli.terminal_ui import _axis_key
        assert _axis_key("BHV-001-test-cheating") == "BHV-001"
        assert _axis_key("BHV-003-error-handling") == "BHV-003"

    def test_short_id_passthrough(self):
        from cli.terminal_ui import _axis_key
        assert _axis_key("BHV-001") == "BHV-001"

    def test_short_behavior_id(self):
        from cli.terminal_ui import _short_behavior_id
        assert _short_behavior_id("BHV-001-test-cheating") == "BHV-001"
        assert _short_behavior_id("BHV-004-loop-detection") == "BHV-004"
