"""Tests for socket path resolution with XDG_RUNTIME_DIR support.

The socket path should be resolved in this priority order:
1. CLAUDE_ENGRAM_SOCKET env var (explicit override)
2. XDG_RUNTIME_DIR/claude-engram.sock (if XDG_RUNTIME_DIR set)
3. /run/user/$UID/claude-engram.sock (if exists)
4. /tmp/claude-engram.sock (fallback)
"""

from __future__ import annotations

import os
from pathlib import Path
from unittest.mock import patch


class TestResolveSocketPath:
    """Tests for resolve_socket_path() function."""

    def test_explicit_env_override_takes_priority(self) -> None:
        """CLAUDE_ENGRAM_SOCKET env var should override all other paths."""
        from claude_engram.paths import resolve_socket_path

        with patch.dict(os.environ, {"CLAUDE_ENGRAM_SOCKET": "/custom/path.sock"}):
            result = resolve_socket_path()
            assert result == Path("/custom/path.sock")

    def test_xdg_runtime_dir_used_when_set(self, tmp_path: Path) -> None:
        """XDG_RUNTIME_DIR should be used when set and exists."""
        from claude_engram.paths import resolve_socket_path

        runtime_dir = tmp_path / "runtime"
        runtime_dir.mkdir()

        with patch.dict(
            os.environ,
            {"XDG_RUNTIME_DIR": str(runtime_dir)},
            clear=False,
        ):
            # Remove CLAUDE_ENGRAM_SOCKET if present
            env = os.environ.copy()
            env.pop("CLAUDE_ENGRAM_SOCKET", None)
            with patch.dict(os.environ, env, clear=True):
                result = resolve_socket_path()
                assert result == runtime_dir / "claude-engram.sock"

    def test_run_user_uid_used_when_exists(self, tmp_path: Path) -> None:
        """When XDG_RUNTIME_DIR not set, /run/user/$UID should be used if it exists."""
        from claude_engram.paths import resolve_socket_path

        # Mock /run/user/$UID check
        with (
            patch.dict(os.environ, {}, clear=True),
            patch("claude_engram.paths._get_run_user_dir") as mock_run_user,
        ):
            mock_run_user.return_value = tmp_path
            result = resolve_socket_path()
            assert result == tmp_path / "claude-engram.sock"

    def test_tmp_fallback_when_no_runtime_dir(self) -> None:
        """Fall back to /tmp when no XDG_RUNTIME_DIR or /run/user/$UID."""
        from claude_engram.paths import resolve_socket_path

        with (
            patch.dict(os.environ, {}, clear=True),
            patch("claude_engram.paths._get_run_user_dir") as mock_run_user,
        ):
            mock_run_user.return_value = None
            result = resolve_socket_path()
            assert result == Path("/tmp/claude-engram.sock")

    def test_legacy_socket_env_var_still_works(self) -> None:
        """CLAUDE_MEMORY_SOCKET (legacy name) should still work."""
        from claude_engram.paths import resolve_socket_path

        # Clear all env vars and set only the legacy one
        with patch.dict(
            os.environ,
            {"CLAUDE_MEMORY_SOCKET": "/legacy/path.sock"},
            clear=True,
        ):
            result = resolve_socket_path()
            assert result == Path("/legacy/path.sock")

    def test_newer_env_var_takes_priority_over_legacy(self) -> None:
        """CLAUDE_ENGRAM_SOCKET should take priority over CLAUDE_MEMORY_SOCKET."""
        from claude_engram.paths import resolve_socket_path

        with patch.dict(
            os.environ,
            {
                "CLAUDE_ENGRAM_SOCKET": "/new/path.sock",
                "CLAUDE_MEMORY_SOCKET": "/old/path.sock",
            },
        ):
            result = resolve_socket_path()
            assert result == Path("/new/path.sock")


class TestGetRunUserDir:
    """Tests for _get_run_user_dir() helper."""

    def test_returns_path_on_linux_with_run_user(self) -> None:
        """On Linux systems with /run/user/$UID, should return a Path."""
        from claude_engram.paths import _get_run_user_dir

        result = _get_run_user_dir()
        # On Linux systems (like this test environment), /run/user/$UID typically exists
        # Result is either Path (exists) or None (doesn't exist/no access)
        if result is not None:
            assert isinstance(result, Path)
            assert result.exists()
            assert result.is_dir()

    def test_returns_correct_uid_path(self) -> None:
        """Should construct path using actual UID."""
        from claude_engram.paths import _get_run_user_dir

        result = _get_run_user_dir()
        if result is not None:
            expected = Path(f"/run/user/{os.getuid()}")
            assert result == expected


class TestSocketPathConsistency:
    """Ensure daemon, CLI, and MCP server use the same resolution logic."""

    def test_all_modules_use_paths_module(self) -> None:
        """All socket users should import from paths module."""
        # This is a design test - verifying the refactor was done correctly
        import claude_engram.cli as cli_module
        import claude_engram.daemon as daemon_module
        import claude_engram.mcp_server as mcp_module

        # After refactor, all should import resolve_socket_path from paths
        # For now, just verify the modules load without error
        assert cli_module is not None
        assert daemon_module is not None
        assert mcp_module is not None
