"""Extended tests for timmy.tools — covers stats, type aliases, and aider tool."""

from unittest.mock import MagicMock, patch

from timmy.tools import (
    AgentTools,
    PersonaTools,
    ToolStats,
    create_aider_tool,
)


class TestToolStats:
    """Test ToolStats dataclass."""

    def test_defaults(self):
        ts = ToolStats(tool_name="calc")
        assert ts.call_count == 0
        assert ts.last_used is None
        assert ts.errors == 0


class TestAgentTools:
    """Test AgentTools dataclass and backward compat alias."""

    def test_persona_tools_alias(self):
        assert PersonaTools is AgentTools


class TestAiderTool:
    """Test AiderTool created by create_aider_tool."""

    def test_create_aider_tool(self, tmp_path):
        tool = create_aider_tool(tmp_path)
        assert hasattr(tool, "run_aider")
        assert tool.base_dir == tmp_path

    @patch("subprocess.run")
    def test_aider_success(self, mock_run, tmp_path):
        tool = create_aider_tool(tmp_path)
        mock_run.return_value = MagicMock(returncode=0, stdout="Changes applied")
        result = tool.run_aider("add fibonacci function")
        assert "Changes applied" in result

    @patch("subprocess.run")
    def test_aider_error(self, mock_run, tmp_path):
        tool = create_aider_tool(tmp_path)
        mock_run.return_value = MagicMock(returncode=1, stderr="something broke")
        result = tool.run_aider("bad prompt")
        assert "error" in result.lower()

    @patch("subprocess.run", side_effect=FileNotFoundError)
    def test_aider_not_installed(self, mock_run, tmp_path):
        tool = create_aider_tool(tmp_path)
        result = tool.run_aider("test")
        assert "not installed" in result.lower()

    @patch("subprocess.run")
    def test_aider_timeout(self, mock_run, tmp_path):
        import subprocess

        mock_run.side_effect = subprocess.TimeoutExpired(cmd="aider", timeout=120)
        tool = create_aider_tool(tmp_path)
        result = tool.run_aider("slow task")
        assert "timed out" in result.lower()
