"""Tests for the smart_read_file wrapper in timmy.tools.

Covers the wrapper's behavior for:
- Handling directories (return listing instead of error)
- Accepting `path=` keyword as alias for `file_name=` (the LLM pattern bug fix)
"""

from unittest.mock import MagicMock

import pytest

from timmy.tools import _make_smart_read_file


class TestSmartReadFile:
    """Test suite for the smart_read_file wrapper function."""

    @pytest.fixture
    def mock_file_tools(self, tmp_path):
        """Create a mock FileTools instance for testing.

        - check_escape returns (True, Path) for safe paths
        - read_file returns file contents
        """
        file_tools = MagicMock()

        def mock_check_escape(file_name):
            """Mock implementation that returns safe paths."""
            resolved = tmp_path / file_name
            return (True, resolved)

        file_tools.check_escape = mock_check_escape
        file_tools.read_file = MagicMock(return_value="file contents")

        return file_tools

    def test_read_file_with_file_name(self, mock_file_tools):
        """Test normal call with file_name positional arg."""
        smart_read_file = _make_smart_read_file(mock_file_tools)

        result = smart_read_file("test.txt")

        assert result == "file contents"
        mock_file_tools.read_file.assert_called_once_with("test.txt", encoding="utf-8")

    def test_read_file_with_path_kwarg(self, mock_file_tools):
        """Test call with path='./config/agents.yaml' (the LLM pattern).

        LLMs often call read_file(path=...) instead of read_file(file_name=...).
        The wrapper should accept path= as an alias for file_name=.
        """
        smart_read_file = _make_smart_read_file(mock_file_tools)

        result = smart_read_file(path="./config/agents.yaml")

        assert result == "file contents"
        mock_file_tools.read_file.assert_called_once_with("./config/agents.yaml", encoding="utf-8")

    def test_read_file_no_args(self, mock_file_tools):
        """Test call with no args returns error message."""
        smart_read_file = _make_smart_read_file(mock_file_tools)

        result = smart_read_file()

        assert result == "Error: no file_name or path provided."
        mock_file_tools.read_file.assert_not_called()

    def test_read_file_directory(self, mock_file_tools, tmp_path):
        """Test call with directory path returns listing.

        When the user (or the LLM) passes a directory path to read_file,
        the wrapper detects that case, lists the directory entries, and returns
        a helpful message so the model can pick the right file on its own.
        """
        # Create a test directory with some files
        test_dir = tmp_path / "config"
        test_dir.mkdir()
        (test_dir / "agents.yaml").write_text("")
        (test_dir / "settings.json").write_text("")
        (test_dir / "README.md").write_text("")

        smart_read_file = _make_smart_read_file(mock_file_tools)

        result = smart_read_file("config")

        assert "'config' is a directory, not a file." in result
        assert "Files inside:" in result
        assert "  - agents.yaml" in result
        assert "  - README.md" in result
        assert "  - settings.json" in result
        assert "Please call read_file with one of the files listed above." in result
        mock_file_tools.read_file.assert_not_called()

    def test_read_file_empty_directory(self, mock_file_tools, tmp_path):
        """Test call with empty directory returns empty directory message."""
        # Create an empty test directory
        test_dir = tmp_path / "empty_dir"
        test_dir.mkdir()

        smart_read_file = _make_smart_read_file(mock_file_tools)

        result = smart_read_file("empty_dir")

        assert "'empty_dir' is a directory, not a file." in result
        assert "  (empty directory)" in result
        mock_file_tools.read_file.assert_not_called()

    def test_read_file_directory_hides_hidden_files(self, mock_file_tools, tmp_path):
        """Test that hidden files (starting with .) are not listed."""
        # Create a test directory with hidden files
        test_dir = tmp_path / "config"
        test_dir.mkdir()
        (test_dir / "visible.txt").write_text("")
        (test_dir / ".hidden").write_text("")
        (test_dir / ".gitignore").write_text("")

        smart_read_file = _make_smart_read_file(mock_file_tools)

        result = smart_read_file("config")

        assert "visible.txt" in result
        assert ".hidden" not in result
        assert ".gitignore" not in result
