"""Edge-case tests for dependency synchronisation (specter_cli.deps).

Covers the main() entry point with correct patch targets.
"""

from __future__ import annotations

from pathlib import Path
from unittest.mock import MagicMock, patch


class TestMainEntryPoint:
    """Tests for deps.main() with correct patch targets.

    The main() function uses local imports, so we patch the source
    modules directly (specter_cli.config, not specter_cli.deps).
    """

    @patch("specter_cli.deps.sync_deps", return_value=True)
    @patch("specter_cli.config.load_remote_config")
    @patch.dict("os.environ", {"VIRTUAL_ENV": "/tmp/test-venv"})
    def test_main_syncs_when_configured(
        self,
        mock_config: MagicMock,
        mock_sync: MagicMock,
        tmp_path: Path,
    ) -> None:
        """main() should call sync_deps when config and venv exist."""
        mock_config.return_value = {
            "host": "1.2.3.4",
            "user": "root",
            "ssh_port": 22,
        }

        # Create the fake venv directory so Path.is_dir() returns True.

        fake_venv = tmp_path / "test-venv"
        fake_venv.mkdir()

        with patch.dict("os.environ", {"VIRTUAL_ENV": str(fake_venv)}):
            from specter_cli.deps import main

            main()

        mock_sync.assert_called_once()

    @patch("specter_cli.deps.sync_deps")
    @patch("specter_cli.config.load_remote_config", return_value={})
    def test_main_no_config_skips(
        self,
        _config: MagicMock,
        mock_sync: MagicMock,
    ) -> None:
        """No remote config → skip sync."""
        from specter_cli.deps import main

        main()

        mock_sync.assert_not_called()

    @patch("specter_cli.deps.sync_deps")
    @patch(
        "specter_cli.config.load_remote_config",
        return_value={"host": "1.2.3.4", "user": "root"},
    )
    @patch.dict("os.environ", {}, clear=True)
    def test_main_no_venv_skips(
        self,
        _config: MagicMock,
        mock_sync: MagicMock,
    ) -> None:
        """No VIRTUAL_ENV env var → skip sync."""
        from specter_cli.deps import main

        main()

        mock_sync.assert_not_called()

    @patch("specter_cli.deps.sync_deps", side_effect=Exception("SSH failed"))
    @patch(
        "specter_cli.config.load_remote_config",
        return_value={
            "host": "1.2.3.4",
            "user": "root",
            "ssh_port": 22,
        },
    )
    def test_main_handles_errors_gracefully(
        self,
        _config: MagicMock,
        _sync: MagicMock,
        tmp_path: Path,
    ) -> None:
        """sync failure should not crash — just print a warning."""
        fake_venv = tmp_path / "test-venv"
        fake_venv.mkdir()

        with patch.dict("os.environ", {"VIRTUAL_ENV": str(fake_venv)}):
            from specter_cli.deps import main

            # Should not raise — errors are caught and logged.
            main()

    @patch("specter_cli.deps.sync_deps")
    @patch(
        "specter_cli.config.load_remote_config",
        return_value={"host": "1.2.3.4", "user": "root", "ssh_port": 22},
    )
    def test_main_nonexistent_venv_skips(
        self,
        _config: MagicMock,
        mock_sync: MagicMock,
    ) -> None:
        """VIRTUAL_ENV points to nonexistent dir → skip sync."""
        with patch.dict(
            "os.environ",
            {"VIRTUAL_ENV": "/nonexistent/path/to/.venv"},
        ):
            from specter_cli.deps import main

            main()

        mock_sync.assert_not_called()
