"""Tests for watch mode module."""

from unittest.mock import AsyncMock, MagicMock, patch

import pytest

from autodebug import watch


class TestFetchErrors:
    """Test error fetching helper."""

    @pytest.mark.asyncio
    async def test_fetch_errors_success(self):
        """Test successful error fetch."""
        mock_response = MagicMock()
        mock_response.status_code = 200
        mock_response.json.return_value = {
            "errors": [
                {"error_id": "err_1", "exception_type": "KeyError"},
                {"error_id": "err_2", "exception_type": "ValueError"},
            ]
        }

        with patch("httpx.AsyncClient") as mock_client:
            mock_client.return_value.__aenter__.return_value.get = AsyncMock(
                return_value=mock_response
            )

            result = await watch._fetch_errors(
                "https://api.example.com",
                "test-token",
                environment=None,
            )

            assert len(result) == 2
            assert result[0]["id"] == "err_1"

    @pytest.mark.asyncio
    async def test_fetch_errors_failure(self):
        """Test error fetch returns empty on failure."""
        mock_response = MagicMock()
        mock_response.status_code = 401

        with patch("httpx.AsyncClient") as mock_client:
            mock_client.return_value.__aenter__.return_value.get = AsyncMock(
                return_value=mock_response
            )

            result = await watch._fetch_errors(
                "https://api.example.com",
                "bad-token",
                environment=None,
            )

            assert result == []


class TestPrintNewError:
    """Test new error printing."""

    def test_print_new_error(self, capsys):
        """Test error is printed correctly."""
        error = {
            "id": "err_123",
            "exception_type": "RuntimeError",
            "message": "Something went wrong",
            "count": 3,
        }

        # Mock desktop notification to avoid actual notifications during tests
        with patch("autodebug.watch.send_desktop_notification", return_value=True):
            watch._print_new_error(error)

        captured = capsys.readouterr()
        # Rich output may contain ANSI codes, so just check key content
        # The output goes to Rich console, not stdout directly in tests


class TestTimestamp:
    """Test timestamp formatting."""

    def test_timestamp_format(self):
        """Test timestamp returns HH:MM:SS format."""
        ts = watch._timestamp()

        # Should be in format HH:MM:SS
        parts = ts.split(":")
        assert len(parts) == 3
        assert all(len(p) == 2 for p in parts)


class TestWatchErrorsRequiresAuth:
    """Test watch_errors authentication requirement."""

    @pytest.mark.asyncio
    async def test_watch_errors_requires_token(self, tmp_path, monkeypatch, capsys):
        """Test watch_errors requires authentication — exits with code 1."""
        # Mock config without token - patch in autodebug.auth since that's where it's imported from
        with patch("autodebug.auth.load_config", return_value={"api_base": "https://api.example.com"}):
            # Should raise SystemExit(1) when not authenticated
            with pytest.raises(SystemExit) as exc_info:
                await watch.watch_errors(interval=1)
            assert exc_info.value.code == 1


class TestWatchFilesImport:
    """Test watchfiles dependency."""

    def test_watchfiles_import(self):
        """Test watchfiles module is importable."""
        from watchfiles import Change, awatch
        assert awatch is not None
        assert Change is not None
