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

from relace_mcp.clients.repo import RelaceRepoClient
from relace_mcp.tools.repo.clear import cloud_clear_logic
from relace_mcp.tools.repo.state import SyncState


def _create_mock_repo_client(repo_name: str) -> MagicMock:
    """Create mock client with configurable repo name."""
    client = MagicMock(spec=RelaceRepoClient)
    client.list_repos.return_value = [{"metadata": {"name": repo_name}, "repo_id": "api-repo-id"}]
    client.delete_repo.return_value = True
    return client


def test_cloud_clear_requires_confirm(tmp_path: Path) -> None:
    """Should return cancelled status if confirm is False."""
    mock_repo_client = _create_mock_repo_client(tmp_path.name)
    result = cloud_clear_logic(mock_repo_client, str(tmp_path), confirm=False)

    assert result["status"] == "cancelled"
    mock_repo_client.delete_repo.assert_not_called()


def test_cloud_clear_uses_sync_state(tmp_path: Path) -> None:
    """Should use repo_id from sync state if available."""
    mock_repo_client = _create_mock_repo_client(tmp_path.name)
    cached = SyncState(repo_id="state-repo-id", repo_head="abc", last_sync="", files={})

    with patch("relace_mcp.tools.repo.clear.load_sync_state", return_value=cached):
        with patch("relace_mcp.tools.repo.clear.clear_sync_state") as mock_clear_state:
            result = cloud_clear_logic(mock_repo_client, str(tmp_path), confirm=True)

            assert result["status"] == "deleted"
            assert result["repo_id"] == "state-repo-id"
            mock_repo_client.delete_repo.assert_called_with("state-repo-id", trace_id=ANY)
            mock_clear_state.assert_called_with(tmp_path.name)


def test_cloud_clear_searches_api_fallback(tmp_path: Path) -> None:
    """Should fallback to API search if sync state missing."""
    mock_repo_client = _create_mock_repo_client(tmp_path.name)

    with patch("relace_mcp.tools.repo.clear.load_sync_state", return_value=None):
        with patch("relace_mcp.tools.repo.clear.clear_sync_state"):
            result = cloud_clear_logic(mock_repo_client, str(tmp_path), confirm=True)

            assert result["status"] == "deleted"
            assert result["repo_id"] == "api-repo-id"
            mock_repo_client.list_repos.assert_called_once()
            mock_repo_client.delete_repo.assert_called_with("api-repo-id", trace_id=ANY)


def test_cloud_clear_not_found(tmp_path: Path) -> None:
    """Should handle repo not found scenario."""
    mock_repo_client = _create_mock_repo_client(tmp_path.name)
    mock_repo_client.list_repos.return_value = []

    with patch("relace_mcp.tools.repo.clear.load_sync_state", return_value=None):
        with patch("relace_mcp.tools.repo.clear.clear_sync_state") as mock_clear_state:
            result = cloud_clear_logic(mock_repo_client, str(tmp_path), confirm=True)

            assert result["status"] == "not_found"
            mock_repo_client.delete_repo.assert_not_called()
            # Should still clear sync state just in case
            mock_clear_state.assert_called_with(tmp_path.name)


def test_cloud_clear_delete_failure(tmp_path: Path) -> None:
    """Should handle delete failure."""
    mock_repo_client = _create_mock_repo_client(tmp_path.name)
    cached = SyncState(repo_id="id", repo_head="", last_sync="")
    mock_repo_client.delete_repo.return_value = False

    with patch("relace_mcp.tools.repo.clear.load_sync_state", return_value=cached):
        with patch("relace_mcp.tools.repo.clear.clear_sync_state") as mock_clear_state:
            result = cloud_clear_logic(mock_repo_client, str(tmp_path), confirm=True)

            assert result["status"] == "error"
            # Should NOT clear sync state on failure
            mock_clear_state.assert_not_called()
