"""Integration tests for Kioku — tests both service layer and MCP server tools."""

import uuid
import pytest
from pathlib import Path

from kioku.config import Settings
from kioku.pipeline.keyword_writer import KeywordIndex
from kioku.pipeline.embedder import FakeEmbedder
from kioku.pipeline.vector_writer import VectorStore
from kioku.pipeline.extractor import FakeExtractor
from kioku.pipeline.graph_writer import InMemoryGraphStore


@pytest.fixture(autouse=True)
def setup_test_env(tmp_path, monkeypatch):
    """Override all stores for tests — fully isolated, no external deps."""
    import os
    import kioku.server as server_module

    use_e2e = os.environ.get("KIOKU_E2E") == "1"

    # Override settings
    test_settings = Settings(
        memory_dir=tmp_path / "memory",
        data_dir=tmp_path / "data",
    )
    test_settings.ensure_dirs()

    # Override keyword index
    test_index = KeywordIndex(test_settings.sqlite_path)

    if use_e2e:
        from kioku.pipeline.embedder import OllamaEmbedder
        from kioku.pipeline.extractor import ClaudeExtractor
        from kioku.pipeline.graph_writer import FalkorGraphStore

        test_embedder = OllamaEmbedder(host="http://localhost:11434", model="nomic-embed-text")
        test_store = VectorStore(
            embedder=test_embedder,
            collection_name=f"test_vec_{uuid.uuid4().hex[:8]}",
            host="localhost",
            port=8000,
        )
        test_extractor = ClaudeExtractor(api_key=os.environ.get("KIOKU_ANTHROPIC_API_KEY", ""))
        test_graph = FalkorGraphStore(
            host="localhost",
            port=6379,
            graph_name=f"test_graph_{uuid.uuid4().hex[:8]}",
        )
    else:
        test_embedder = FakeEmbedder()
        test_store = VectorStore(
            embedder=test_embedder, collection_name=f"test_{uuid.uuid4().hex[:8]}"
        )
        test_graph = InMemoryGraphStore()
        test_extractor = FakeExtractor()

    # Patch the _svc instance attributes (service layer owns the state now)
    svc = server_module._svc
    monkeypatch.setattr(svc, "settings", test_settings)
    monkeypatch.setattr(svc, "keyword_index", test_index)
    monkeypatch.setattr(svc, "vector_store", test_store)
    monkeypatch.setattr(svc, "graph_store", test_graph)
    monkeypatch.setattr(svc, "extractor", test_extractor)

    yield

    test_index.close()


# ─── Import tool functions from server (thin wrappers) ─────────────────

from kioku.server import (
    save_memory,
    search_memories,
    get_timeline,
    list_memory_dates,
    recall_related,
    explain_connection,
)


class TestSaveMemoryTool:
    def test_save_basic(self):
        result = save_memory("Today I learned about MCP servers")
        assert result["status"] == "saved"
        assert result["indexed"] is True
        assert "timestamp" in result

    def test_save_with_mood(self):
        result = save_memory("Feeling great!", mood="happy")
        assert result["mood"] == "happy"

    def test_save_with_tags(self):
        result = save_memory("Work meeting", tags=["work", "meeting"])
        assert result["tags"] == ["work", "meeting"]

    def test_save_indexes_graph(self):
        """Saving a memory should also extract entities into the graph."""
        save_memory("Project meeting with Hung today, feeling stressed")
        result = recall_related("Hung")
        assert result["connected_count"] >= 1


class TestSearchMemoriesTool:
    def test_search_empty_store(self):
        """Search on an empty store returns no results."""
        result = search_memories("nonexistent query xyz")
        assert result["count"] == 0

    def test_search_finds_saved(self):
        save_memory("Đi ăn phở với bạn Minh ở quận 1")
        save_memory("Họp team buổi sáng về sprint mới")
        result = search_memories("phở")
        assert result["count"] >= 1
        assert "phở" in result["results"][0]["content"]

    def test_search_limit(self):
        for i in range(5):
            save_memory(f"Memory entry number {i} about testing")
        result = search_memories("testing", limit=3)
        assert result["count"] <= 3


class TestRecallRelatedTool:
    def test_recall_entities(self):
        save_memory("Hùng gọi điện hỏi dự án, stressed")
        save_memory("Hùng mời đi ăn trưa, happy")
        result = recall_related("Hùng")
        assert result["entity"] == "Hùng"
        assert result["connected_count"] >= 1

    def test_recall_no_match(self):
        result = recall_related("NotARealPerson")
        assert result["connected_count"] == 0


class TestExplainConnectionTool:
    def test_explain_connected(self):
        save_memory("Hùng làm tôi stressed")
        result = explain_connection("Hùng", "stressed")
        assert result["from"] == "Hùng"
        assert result["to"] == "stressed"
        assert "connected" in result

    def test_explain_not_connected(self):
        result = explain_connection("A_entity", "B_entity")
        assert result["connected"] is False


class TestListMemoryDatesTool:
    def test_list_dates(self):
        save_memory("Some entry")
        result = list_memory_dates()
        assert result["count"] >= 1
        assert len(result["dates"]) >= 1


from kioku import server as server_module


class TestTimelineAndPatternsTools:
    def test_get_timeline(self, setup_test_env):
        server_module.save_memory("First event", mood="neutral", tags=["test1"])
        server_module.save_memory("Second event", mood="happy", tags=["test2"])

        result = server_module.get_timeline(limit=10)
        assert result["count"] >= 2

        timeline = result["timeline"]
        assert timeline[-2]["text"] == "First event"
        assert timeline[-1]["text"] == "Second event"


class TestResourcesAndPrompts:
    def test_memory_resource(self, setup_test_env):
        server_module.save_memory("Test string in memory", mood="happy")
        from datetime import datetime

        today = datetime.now().strftime("%Y-%m-%d")

        res = server_module.read_memory_resource(today)
        assert "Test string in memory" in res

        res_empty = server_module.read_memory_resource("1900-01-01")
        assert "No memories found" in res_empty

    def test_entity_resource(self, setup_test_env):
        server_module.save_memory("Hôm nay đi tập gym với Minh, rất vui.")
        res = server_module.read_entity_resource("Minh")
        assert "Entity Profile: Minh" in res or "Entity 'Minh' not found" in res

    def test_prompts(self):
        prompt1 = server_module.reflect_on_day()
        assert "kioku://memories/" in prompt1
        assert "overall emotional tone" in prompt1

        prompt2 = server_module.analyze_relationships("Hùng")
        assert "kioku://entities/Hùng" in prompt2
        assert "What is my primary emotional response" in prompt2

        prompt3 = server_module.weekly_review()
        assert "weekly retrospective" in prompt3
