"""Tests for ScopedMemoryManager — memory scopes for multi-project isolation."""

import pytest
from pathlib import Path

from memotrail.core.scopes import ScopedMemoryManager, MemoryScope
from memotrail.storage.sqlite_store import SQLiteStore


def _make_manager(tmp_path: Path) -> tuple[ScopedMemoryManager, SQLiteStore]:
    store = SQLiteStore(db_path=tmp_path / "test.db")
    store.connect()
    manager = ScopedMemoryManager(store)
    return manager, store


class TestSaveMemory:
    def test_save_user_scoped(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory("Global fact", scope=MemoryScope.USER)
        assert mem_id.startswith("mem_")

    def test_save_project_scoped(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory(
            "Project-specific fact",
            scope=MemoryScope.PROJECT,
            project="myapp",
        )
        assert mem_id.startswith("mem_")

    def test_project_scope_requires_project(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        with pytest.raises(ValueError, match="Project is required"):
            manager.save_memory("test", scope=MemoryScope.PROJECT)

    def test_save_with_tags(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory(
            "Tagged memory", tags=["db", "config"], scope=MemoryScope.USER,
        )
        memories = manager.get_memories()
        assert len(memories) == 1
        assert "db" in memories[0]["tags"]

    def test_save_session_scoped(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory("Session fact", scope=MemoryScope.SESSION)
        assert mem_id.startswith("mem_")


class TestGetMemories:
    def test_get_all(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        manager.save_memory("Fact 1", scope=MemoryScope.USER)
        manager.save_memory("Fact 2", scope=MemoryScope.PROJECT, project="proj1")

        memories = manager.get_memories()
        assert len(memories) == 2

    def test_filter_by_user_scope(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        manager.save_memory("Global", scope=MemoryScope.USER)
        manager.save_memory("Project", scope=MemoryScope.PROJECT, project="proj1")

        memories = manager.get_memories(scope=MemoryScope.USER)
        assert len(memories) == 1
        assert memories[0]["content"] == "Global"

    def test_filter_by_project(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        manager.save_memory("Global", scope=MemoryScope.USER)
        manager.save_memory("Proj1 fact", scope=MemoryScope.PROJECT, project="proj1")
        manager.save_memory("Proj2 fact", scope=MemoryScope.PROJECT, project="proj2")

        # With project context: should see global + proj1 memories
        memories = manager.get_memories(project="proj1")
        contents = [m["content"] for m in memories]
        assert "Global" in contents
        assert "Proj1 fact" in contents
        assert "Proj2 fact" not in contents

    def test_filter_by_project_scope(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        manager.save_memory("Proj1 fact", scope=MemoryScope.PROJECT, project="proj1")
        manager.save_memory("Proj2 fact", scope=MemoryScope.PROJECT, project="proj2")

        memories = manager.get_memories(scope=MemoryScope.PROJECT, project="proj1")
        assert len(memories) == 1
        assert memories[0]["content"] == "Proj1 fact"

    def test_empty_db(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        assert manager.get_memories() == []


class TestUpdateScope:
    def test_change_to_project_scope(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory("Was global", scope=MemoryScope.USER)
        manager.update_scope(mem_id, MemoryScope.PROJECT, project="proj1")

        memories = manager.get_memories(scope=MemoryScope.PROJECT, project="proj1")
        assert len(memories) == 1

    def test_change_to_user_scope(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory("Was project", scope=MemoryScope.PROJECT, project="proj1")
        manager.update_scope(mem_id, MemoryScope.USER)

        memories = manager.get_memories(scope=MemoryScope.USER)
        assert len(memories) == 1

    def test_project_scope_requires_project(self, tmp_path):
        manager, _ = _make_manager(tmp_path)
        mem_id = manager.save_memory("test", scope=MemoryScope.USER)
        with pytest.raises(ValueError):
            manager.update_scope(mem_id, MemoryScope.PROJECT)


class TestMemoryScopeEnum:
    def test_scope_values(self):
        assert MemoryScope.USER.value == "user"
        assert MemoryScope.PROJECT.value == "project"
        assert MemoryScope.SESSION.value == "session"
