"""Tests for REST API — /api/v1/ endpoints."""

import pytest
from unittest.mock import patch, MagicMock

pytest.importorskip("fastapi")
pytest.importorskip("httpx")

from fastapi.testclient import TestClient


@pytest.fixture
def api_client(tmp_path):
    """Create a test client with REST API."""
    from memotrail.storage.sqlite_store import SQLiteStore
    from memotrail.core.temporal import TemporalTracker

    sqlite = SQLiteStore(db_path=tmp_path / "test.db")
    sqlite.connect()
    temporal = TemporalTracker(sqlite)

    mock_chroma = MagicMock()
    mock_chroma.get_collection_count.return_value = 0
    mock_searcher = MagicMock()
    mock_searcher.search_chats.return_value = []
    mock_searcher.search_keyword.return_value = []
    mock_searcher.search_hybrid.return_value = []
    mock_context = MagicMock()
    mock_context.pack_query_context.return_value = "test context"
    mock_graph = MagicMock()
    mock_graph.get_all_entities.return_value = []
    mock_graph.get_entities_by_type.return_value = []
    mock_graph.get_entity.return_value = None
    mock_graph.get_entity_relations.return_value = []

    with patch("memotrail.web.app.sqlite_store", sqlite), \
         patch("memotrail.web.app.chroma_store", mock_chroma), \
         patch("memotrail.web.app.searcher", mock_searcher), \
         patch("memotrail.web.app.context_packer", mock_context), \
         patch("memotrail.web.app.knowledge_graph", mock_graph), \
         patch("memotrail.web.app.temporal_tracker", temporal):

        # Also patch the API module globals
        from memotrail.web import api_routes
        api_routes._sqlite = sqlite
        api_routes._chroma = mock_chroma
        api_routes._searcher = mock_searcher
        api_routes._context_packer = mock_context
        api_routes._graph = mock_graph
        api_routes._temporal = temporal

        from memotrail.web.app import app
        yield TestClient(app), sqlite, temporal


class TestStatsEndpoint:
    def test_get_stats(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        response = client.get("/api/v1/stats")
        assert response.status_code == 200
        data = response.json()
        assert "total_sessions" in data
        assert "total_messages" in data


class TestSessionsEndpoint:
    def test_list_sessions_empty(self, api_client, tmp_path):
        client, _, _ = api_client
        response = client.get("/api/v1/sessions")
        assert response.status_code == 200
        data = response.json()
        assert data["total"] == 0
        assert data["sessions"] == []

    def test_list_sessions_with_data(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        sqlite.create_session(project="test")
        response = client.get("/api/v1/sessions")
        data = response.json()
        assert data["total"] == 1
        assert data["sessions"][0]["project"] == "test"

    def test_session_pagination(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        for i in range(5):
            sqlite.create_session(project=f"proj{i}")
        response = client.get("/api/v1/sessions?per_page=2&page=1")
        data = response.json()
        assert len(data["sessions"]) == 2
        assert data["total"] == 5

    def test_session_detail(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        session = sqlite.create_session(project="test")
        sqlite.add_message(session.id, "user", "Hello")
        response = client.get(f"/api/v1/sessions/{session.id}")
        data = response.json()
        assert data["id"] == session.id
        assert len(data["messages"]) == 1


class TestSearchEndpoint:
    def test_search(self, api_client, tmp_path):
        client, _, _ = api_client
        response = client.post("/api/v1/search", json={"query": "test"})
        assert response.status_code == 200
        data = response.json()
        assert "results" in data


class TestDecisionsEndpoint:
    def test_list_decisions(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        session = sqlite.create_session(project="test")
        sqlite.add_decision(session.id, "Use Python", category="technology")
        response = client.get("/api/v1/decisions")
        data = response.json()
        assert data["count"] == 1
        assert "Python" in data["decisions"][0]["decision_text"]


class TestMemoriesEndpoint:
    def test_list_memories(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        sqlite.save_memory("Test memory", tags=["test"])
        response = client.get("/api/v1/memories")
        data = response.json()
        assert data["count"] == 1

    def test_delete_memory(self, api_client, tmp_path):
        client, sqlite, _ = api_client
        mem_id = sqlite.save_memory("To delete")
        response = client.delete(f"/api/v1/memories/{mem_id}")
        assert response.status_code == 200
        assert response.json()["deleted"] == mem_id


class TestContextEndpoint:
    def test_get_context(self, api_client, tmp_path):
        client, _, _ = api_client
        response = client.post("/api/v1/context", json={"query": "auth"})
        assert response.status_code == 200
        data = response.json()
        assert "context" in data


class TestGraphEndpoint:
    def test_list_entities(self, api_client, tmp_path):
        client, _, _ = api_client
        response = client.get("/api/v1/graph/entities")
        assert response.status_code == 200
        data = response.json()
        assert "entities" in data


class TestHistoryEndpoint:
    def test_get_history_empty(self, api_client, tmp_path):
        client, _, _ = api_client
        response = client.get("/api/v1/history/nonexistent")
        assert response.status_code == 200
        data = response.json()
        assert data["count"] == 0

    def test_get_history_with_data(self, api_client, tmp_path):
        client, _, temporal = api_client
        temporal.record_change("decision", "dec_test", "v1", "created")
        temporal.record_change("decision", "dec_test", "v2", "updated", previous_value="v1")

        response = client.get("/api/v1/history/dec_test")
        data = response.json()
        assert data["count"] == 2
        assert data["history"][0]["new_value"] == "v1"
