"""Tests for Claude and Codex event handlers."""

from ml_ralph_cli.cli import _handle_claude_event, _handle_codex_event


class TestHandleClaudeEvent:
    """Tests for _handle_claude_event function."""

    def test_text_event_prints_text(self, claude_text_event, capsys):
        """Text events should print the text content."""
        _handle_claude_event(claude_text_event)
        captured = capsys.readouterr()
        assert "Hello, this is a test message." in captured.out

    def test_tool_use_bash_with_description(self, capsys):
        """Bash tool_use with description shows the description."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Bash",
                        "input": {"command": "ls -la", "description": "List all files"},
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Bash" in captured.out
        assert "List all files" in captured.out

    def test_tool_use_bash_without_description(self, capsys):
        """Bash tool_use without description shows truncated command."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Bash",
                        "input": {
                            "command": "ls -la /very/long/path/that/might/need/truncation"
                        },
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Bash" in captured.out
        assert "ls -la" in captured.out

    def test_tool_use_bash_long_command_truncated(self, capsys):
        """Long bash commands should be truncated."""
        long_cmd = "x" * 100
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {"type": "tool_use", "name": "Bash", "input": {"command": long_cmd}}
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "..." in captured.out

    def test_tool_use_read(self, capsys):
        """Read tool shows file path."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Read",
                        "input": {"file_path": "/path/to/file.txt"},
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Read" in captured.out
        assert "/path/to/file.txt" in captured.out

    def test_tool_use_write(self, capsys):
        """Write tool shows file path."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Write",
                        "input": {"file_path": "/path/to/output.txt"},
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Write" in captured.out
        assert "/path/to/output.txt" in captured.out

    def test_tool_use_edit(self, capsys):
        """Edit tool shows file path."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Edit",
                        "input": {"file_path": "/path/to/edit.py"},
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Edit" in captured.out
        assert "/path/to/edit.py" in captured.out

    def test_tool_use_glob(self, capsys):
        """Glob tool shows pattern."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Glob",
                        "input": {"pattern": "**/*.py"},
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Glob" in captured.out
        assert "**/*.py" in captured.out

    def test_tool_use_grep(self, capsys):
        """Grep tool shows pattern."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {
                        "type": "tool_use",
                        "name": "Grep",
                        "input": {"pattern": "def test_"},
                    }
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "Grep" in captured.out
        assert "def test_" in captured.out

    def test_tool_use_unknown(self, capsys):
        """Unknown tools just show the tool name."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {"type": "tool_use", "name": "UnknownTool", "input": {"foo": "bar"}}
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "UnknownTool" in captured.out

    def test_tool_result_success(self, claude_tool_result_success, capsys):
        """Successful tool results show green checkmark."""
        _handle_claude_event(claude_tool_result_success)
        captured = capsys.readouterr()
        # Rich formatting makes exact matching hard, just check it ran without error
        assert captured.out is not None

    def test_tool_result_error(self, claude_tool_result_error, capsys):
        """Error tool results show red X."""
        _handle_claude_event(claude_tool_result_error)
        captured = capsys.readouterr()
        assert captured.out is not None

    def test_result_event_no_output(self, claude_result_event, capsys):
        """Result events don't produce output."""
        _handle_claude_event(claude_result_event)
        captured = capsys.readouterr()
        # Result events should not print anything directly
        assert "iteration_complete" not in captured.out

    def test_empty_event(self, capsys):
        """Empty events are handled gracefully."""
        _handle_claude_event({})
        captured = capsys.readouterr()
        assert captured.out == ""

    def test_unknown_event_type(self, capsys):
        """Unknown event types are handled gracefully."""
        _handle_claude_event({"type": "unknown_type", "data": "test"})
        captured = capsys.readouterr()
        assert captured.out == ""

    def test_multiple_content_blocks(self, capsys):
        """Events with multiple content blocks process all of them."""
        event = {
            "type": "assistant",
            "message": {
                "content": [
                    {"type": "text", "text": "First message."},
                    {"type": "text", "text": "Second message."},
                ]
            },
        }
        _handle_claude_event(event)
        captured = capsys.readouterr()
        assert "First message." in captured.out
        assert "Second message." in captured.out


class TestHandleCodexEvent:
    """Tests for _handle_codex_event function."""

    def test_thread_started(self, codex_thread_started, capsys):
        """thread.started shows truncated session ID."""
        result = _handle_codex_event(codex_thread_started)
        captured = capsys.readouterr()
        assert "Session:" in captured.out
        assert "019c0639" in captured.out
        assert result is None

    def test_turn_started_no_output(self, codex_turn_started, capsys):
        """turn.started produces no output."""
        result = _handle_codex_event(codex_turn_started)
        captured = capsys.readouterr()
        assert captured.out == ""
        assert result is None

    def test_reasoning_completed(self, codex_reasoning_completed, capsys):
        """reasoning item.completed shows abbreviated thinking."""
        result = _handle_codex_event(codex_reasoning_completed)
        captured = capsys.readouterr()
        assert "Analyzing the situation" in captured.out
        assert result is None

    def test_reasoning_long_text_truncated(self, capsys):
        """Long reasoning text is truncated."""
        long_text = "A" * 200
        event = {
            "type": "item.completed",
            "item": {"id": "item_0", "type": "reasoning", "text": long_text},
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert "..." in captured.out
        assert result is None

    def test_file_change_add(self, capsys):
        """file_change with add kind shows + icon."""
        event = {
            "type": "item.completed",
            "item": {
                "id": "item_1",
                "type": "file_change",
                "changes": [{"path": "/tmp/new_file.txt", "kind": "add"}],
                "status": "completed",
            },
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert "File" in captured.out
        assert "/tmp/new_file.txt" in captured.out
        assert result is None

    def test_file_change_modify(self, capsys):
        """file_change with modify kind shows edit icon."""
        event = {
            "type": "item.completed",
            "item": {
                "id": "item_1",
                "type": "file_change",
                "changes": [{"path": "/tmp/existing.txt", "kind": "modify"}],
                "status": "completed",
            },
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert "File" in captured.out
        assert "/tmp/existing.txt" in captured.out
        assert result is None

    def test_file_change_delete(self, capsys):
        """file_change with delete kind shows delete icon."""
        event = {
            "type": "item.completed",
            "item": {
                "id": "item_1",
                "type": "file_change",
                "changes": [{"path": "/tmp/deleted.txt", "kind": "delete"}],
                "status": "completed",
            },
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert "File" in captured.out
        assert "/tmp/deleted.txt" in captured.out
        assert result is None

    def test_file_change_multiple(self, codex_file_change_completed, capsys):
        """Multiple file changes are all shown."""
        result = _handle_codex_event(codex_file_change_completed)
        captured = capsys.readouterr()
        assert "/tmp/test/file.txt" in captured.out
        assert "/tmp/test/config.json" in captured.out
        assert result is None

    def test_command_started(self, codex_command_started, capsys):
        """command_execution item.started shows command."""
        result = _handle_codex_event(codex_command_started)
        captured = capsys.readouterr()
        assert "Bash" in captured.out
        # Should extract command from shell wrapper
        assert "ls -la" in captured.out
        assert result is None

    def test_command_started_extracts_from_shell_wrapper(self, capsys):
        """Command is extracted from shell wrapper like /bin/zsh -lc '...'."""
        event = {
            "type": "item.started",
            "item": {
                "id": "item_2",
                "type": "command_execution",
                "command": "/bin/zsh -lc 'echo hello world'",
                "status": "in_progress",
            },
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert "echo hello world" in captured.out
        assert result is None

    def test_command_completed_success(self, codex_command_completed_success, capsys):
        """Successful command shows green checkmark."""
        result = _handle_codex_event(codex_command_completed_success)
        capsys.readouterr()
        # Just verify it runs without error
        assert result is None

    def test_command_completed_error(self, codex_command_completed_error, capsys):
        """Failed command shows error with exit code."""
        result = _handle_codex_event(codex_command_completed_error)
        captured = capsys.readouterr()
        assert "exit 1" in captured.out
        assert result is None

    def test_agent_message(self, codex_agent_message, capsys):
        """agent_message returns text for completion detection."""
        result = _handle_codex_event(codex_agent_message)
        captured = capsys.readouterr()
        assert "I've completed the task" in captured.out
        assert "<iteration_complete>" in captured.out
        assert result == "I've completed the task. <iteration_complete>"

    def test_agent_message_empty(self, capsys):
        """Empty agent_message returns None."""
        event = {
            "type": "item.completed",
            "item": {"id": "item_4", "type": "agent_message", "text": ""},
        }
        result = _handle_codex_event(event)
        assert result is None

    def test_turn_completed(self, codex_turn_completed, capsys):
        """turn.completed shows token usage."""
        result = _handle_codex_event(codex_turn_completed)
        captured = capsys.readouterr()
        assert "Tokens:" in captured.out
        assert "50,000" in captured.out
        assert "40,000" in captured.out
        assert "500" in captured.out
        assert result is None

    def test_empty_event(self, capsys):
        """Empty events are handled gracefully."""
        result = _handle_codex_event({})
        captured = capsys.readouterr()
        assert captured.out == ""
        assert result is None

    def test_unknown_event_type(self, capsys):
        """Unknown event types are handled gracefully."""
        result = _handle_codex_event({"type": "unknown_type", "data": "test"})
        captured = capsys.readouterr()
        assert captured.out == ""
        assert result is None

    def test_unknown_item_type(self, capsys):
        """Unknown item types in item.completed are handled gracefully."""
        event = {
            "type": "item.completed",
            "item": {"id": "item_x", "type": "unknown_item_type", "data": "test"},
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert captured.out == ""
        assert result is None

    def test_reasoning_item_started_no_output(self, capsys):
        """reasoning item.started produces no output (only completed does)."""
        event = {
            "type": "item.started",
            "item": {"id": "item_0", "type": "reasoning", "text": "Thinking..."},
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert captured.out == ""
        assert result is None

    def test_long_command_truncated(self, capsys):
        """Long commands are truncated in display."""
        long_cmd = "echo " + "x" * 100
        event = {
            "type": "item.started",
            "item": {
                "id": "item_2",
                "type": "command_execution",
                "command": long_cmd,
                "status": "in_progress",
            },
        }
        result = _handle_codex_event(event)
        captured = capsys.readouterr()
        assert "..." in captured.out
        assert result is None
