"""Tests for mock implementations."""


from pydanticai_multiagent.dependencies.mocks import (
    SAMPLE_DOCUMENTS,
    SAMPLE_ORDERS,
    SAMPLE_USERS,
    MockCache,
    MockDatabase,
    MockHttpClient,
    MockVectorStore,
)


class TestMockHttpClient:
    """Tests for MockHttpClient."""

    async def test_get_web_search(self) -> None:
        """Test mock web search response."""
        client = MockHttpClient()

        response = await client.get(
            "https://api.search.example/search",
            params={"q": "python programming"},
        )

        data = response.json()
        assert "results" in data
        assert len(data["results"]) == 2
        assert "python programming" in data["results"][0]["title"]

    async def test_get_github_issues(self) -> None:
        """Test mock GitHub issues search."""
        client = MockHttpClient()

        response = await client.get(
            "https://api.github.com/search/issues",
            params={"q": "bug"},
        )

        data = response.json()
        assert "items" in data
        assert len(data["items"]) == 2
        assert data["items"][0]["number"] == 123

    async def test_get_github_issue_details(self) -> None:
        """Test mock GitHub issue details."""
        client = MockHttpClient()

        response = await client.get(
            "https://api.github.com/repos/owner/repo/issues/123",
        )

        data = response.json()
        assert data["number"] == 123
        assert data["title"] == "Bug: Login not working"
        assert data["state"] == "open"

    async def test_get_github_repo(self) -> None:
        """Test mock GitHub repo info."""
        client = MockHttpClient()

        response = await client.get(
            "https://api.github.com/repos/example/repo",
        )

        data = response.json()
        assert data["full_name"] == "example/repo"
        assert data["stargazers_count"] == 1250

    async def test_get_slack_messages(self) -> None:
        """Test mock Slack messages."""
        client = MockHttpClient()

        response = await client.get(
            "https://slack.com/api/conversations.history",
        )

        data = response.json()
        assert data["ok"] is True
        assert len(data["messages"]) == 2

    async def test_post_slack_message(self) -> None:
        """Test mock Slack post message."""
        client = MockHttpClient()

        response = await client.post(
            "https://slack.com/api/chat.postMessage",
            json={"channel": "C123", "text": "Hello"},
        )

        data = response.json()
        assert data["ok"] is True
        assert "ts" in data

    async def test_get_default_response(self) -> None:
        """Test default mock response for unknown URLs."""
        client = MockHttpClient()

        response = await client.get("https://unknown.example.com/page")

        assert response.status_code == 200
        assert b"Mock webpage content" in response.content


class TestMockDatabase:
    """Tests for MockDatabase."""

    async def test_fetch_users(self) -> None:
        """Test fetching users."""
        db = MockDatabase()

        users = await db.fetch_all("SELECT * FROM users")

        assert len(users) == 5
        assert users[0]["email"] == "alice@example.com"

    async def test_fetch_users_by_email(self) -> None:
        """Test fetching user by email."""
        db = MockDatabase()

        users = await db.fetch_all(
            "SELECT * FROM users WHERE email = $1",
            "alice@example.com",
        )

        assert len(users) == 1
        assert users[0]["name"] == "Alice Smith"

    async def test_fetch_orders(self) -> None:
        """Test fetching orders."""
        db = MockDatabase()

        orders = await db.fetch_all("SELECT * FROM orders")

        assert len(orders) == 6

    async def test_fetch_orders_by_user(self) -> None:
        """Test fetching orders by user."""
        db = MockDatabase()

        orders = await db.fetch_all(
            "SELECT * FROM orders WHERE user_id = $1",
            "user-001",
        )

        assert len(orders) == 3
        assert all(o["user_id"] == "user-001" for o in orders)

    async def test_fetch_user_stats(self) -> None:
        """Test fetching user statistics."""
        db = MockDatabase()

        stats = await db.fetch_one(
            "SELECT count(*) FROM orders WHERE user_id = $1",
            "user-001",
        )

        assert stats is not None
        assert stats["total_orders"] == 3

    async def test_sample_data_integrity(self) -> None:
        """Test sample data is correctly initialized."""
        db = MockDatabase()

        assert len(db.users) == len(SAMPLE_USERS)
        assert len(db.orders) == len(SAMPLE_ORDERS)


class TestMockCache:
    """Tests for MockCache."""

    async def test_get_nonexistent(self) -> None:
        """Test getting nonexistent key."""
        cache = MockCache()

        value = await cache.get("nonexistent")

        assert value is None

    async def test_set_and_get(self) -> None:
        """Test setting and getting value."""
        cache = MockCache()

        await cache.set("key", "value")
        result = await cache.get("key")

        assert result == "value"

    async def test_delete(self) -> None:
        """Test deleting value."""
        cache = MockCache()

        await cache.set("key", "value")
        await cache.delete("key")
        result = await cache.get("key")

        assert result is None

    async def test_delete_nonexistent(self) -> None:
        """Test deleting nonexistent key doesn't error."""
        cache = MockCache()

        # Should not raise
        await cache.delete("nonexistent")


class TestMockVectorStore:
    """Tests for MockVectorStore."""

    async def test_search_returns_results(self) -> None:
        """Test semantic search returns results."""
        store = MockVectorStore()

        results = await store.search("getting started guide")

        assert len(results) > 0
        assert all("score" in r for r in results)

    async def test_search_with_filter(self) -> None:
        """Test search with category filter."""
        store = MockVectorStore()

        results = await store.search(
            "help",
            filters={"category": "support"},
        )

        assert all(r["category"] == "support" for r in results)

    async def test_search_top_k(self) -> None:
        """Test search respects top_k limit."""
        store = MockVectorStore()

        results = await store.search("test", top_k=2)

        assert len(results) <= 2

    async def test_get_document(self) -> None:
        """Test getting document by ID."""
        store = MockVectorStore()

        doc = await store.get("doc-001")

        assert doc is not None
        assert doc["title"] == "Getting Started Guide"

    async def test_get_nonexistent_document(self) -> None:
        """Test getting nonexistent document."""
        store = MockVectorStore()

        doc = await store.get("nonexistent")

        assert doc is None

    async def test_upsert_new_document(self) -> None:
        """Test inserting new document."""
        store = MockVectorStore()
        initial_count = len(store.documents)

        await store.upsert(
            "new-doc",
            "New document content",
            {"title": "New Doc", "category": "test"},
        )

        assert len(store.documents) == initial_count + 1
        doc = await store.get("new-doc")
        assert doc is not None
        assert doc["content"] == "New document content"

    async def test_upsert_existing_document(self) -> None:
        """Test updating existing document."""
        store = MockVectorStore()

        await store.upsert(
            "doc-001",
            "Updated content",
            {"title": "Updated Title"},
        )

        doc = await store.get("doc-001")
        assert doc["content"] == "Updated content"
        assert doc["title"] == "Updated Title"

    async def test_sample_documents_loaded(self) -> None:
        """Test sample documents are loaded."""
        store = MockVectorStore()

        assert len(store.documents) == len(SAMPLE_DOCUMENTS)
