"""HandlerProtocol compliance tests.

Verifies that PersistentHandler implements the HandlerProtocol interface
and that core CRUD operations work correctly.
"""

import pytest

from conftest import MockAIClient
from trustmem.handler.protocol import HandlerProtocol
from trustmem.handler.persistent import PersistentHandler


# ============================================================
# Protocol compliance
# ============================================================


class TestProtocolCompliance:
    """PersistentHandler must satisfy isinstance(h, HandlerProtocol)."""

    def test_persistent_handler_is_protocol(self):
        h = PersistentHandler(database_url=":memory:", ai_client=MockAIClient())
        assert isinstance(h, HandlerProtocol)


# ============================================================
# CRUD tests using PersistentHandler via conftest fixture
# ============================================================


class TestAddMemory:
    def test_add_returns_required_keys(self, handler):
        result = handler.add_memory("Test content", user_id="test")
        assert "memory_id" in result
        assert "content_hash" in result
        assert "confidence" in result
        assert "embedding_status" in result

    def test_add_returns_content_hash(self, handler):
        result = handler.add_memory("Test content", user_id="test")
        assert result["content_hash"].startswith("mem_")

    def test_confidence_default(self, handler):
        """All memories start with a default confidence value."""
        r1 = handler.add_memory("Direct input", user_id="test")
        r2 = handler.add_memory("Scraped content", user_id="test")
        assert r1["confidence"] in ("high", "medium", "low")
        assert r2["confidence"] in ("high", "medium", "low")

    def test_confidence_high(self, handler):
        """Memories with _confidence='high' store that confidence."""
        result = handler.add_memory("Content", _confidence="high", user_id="test")
        assert result["confidence"] == "high"

    def test_confidence_low(self, handler):
        """Memories with _confidence='low' store that confidence."""
        result = handler.add_memory("Content", _confidence="low", user_id="test")
        assert result["confidence"] == "low"


class TestSearchMemory:
    def test_search_returns_dict_with_results(self, handler):
        handler.add_memory("Python is great for data science", user_id="test")
        result = handler.search_memory("Python", user_id="test")
        assert isinstance(result, dict)
        assert "results" in result

    def test_search_filters_by_user(self, handler):
        handler.add_memory("Agent 1 memory", user_id="agent-1")
        handler.add_memory("Agent 2 memory", user_id="agent-2")
        result = handler.search_memory("memory", user_id="agent-1")
        results = result["results"]
        for r in results:
            assert "Agent 1" in r["content"] or r.get("user_id") == "agent-1"

    def test_search_no_min_zone_param(self, handler):
        """search_memory does not accept min_zone — only (query, limit)."""
        handler.add_memory("Some content", user_id="test")
        # Should not raise TypeError
        result = handler.search_memory("content", limit=5, user_id="test")
        assert "results" in result


class TestListMemories:
    def test_list_returns_memories(self, handler):
        handler.add_memory("Memory 1", user_id="agent-1")
        handler.add_memory("Memory 2", user_id="agent-1")
        result = handler.list_memories(user_id="agent-1")
        memories = result["memories"]
        assert len(memories) == 2

    def test_list_filters_by_user(self, handler):
        handler.add_memory("A1", user_id="agent-1")
        handler.add_memory("A2", user_id="agent-2")
        result = handler.list_memories(user_id="agent-1")
        memories = result["memories"]
        assert len(memories) == 1


class TestDeleteMemory:
    def test_delete_existing(self, handler):
        result = handler.add_memory("To delete", user_id="test")
        mid = result["memory_id"]
        assert handler.delete_memory(mid) is True

    def test_delete_nonexistent(self, handler):
        import pytest
        with pytest.raises(KeyError):
            handler.delete_memory("nonexistent-id")

class TestGetMemoryStats:
    def test_stats_structure(self, handler):
        handler.add_memory("Test", user_id="agent-1")
        stats = handler.get_memory_stats(user_id="agent-1")
        assert "total_memories" in stats
        assert stats["total_memories"] == 1


class TestVerifyMemory:
    def test_verify_valid(self, handler):
        result = handler.add_memory("Verify me", user_id="test")
        mid = result["memory_id"]
        v = handler.verify_memory(mid)
        assert v["valid"] is True

    def test_verify_nonexistent(self, handler):
        v = handler.verify_memory("nonexistent")
        assert v["valid"] is False


class TestAuditTrail:
    def test_audit_trail_recorded(self, handler):
        result = handler.add_memory("Audited", user_id="test")
        mid = result["memory_id"]
        trail = handler.get_audit_trail(mid)
        assert len(trail) >= 1

    def test_record_audit_trail_signature(self, handler):
        """record_audit_trail accepts old_confidence/new_confidence (string), not trust_score/zone."""
        result = handler.add_memory("For audit", user_id="test")
        mid = result["memory_id"]
        entry = handler.record_audit_trail(
            mid,
            "test_event",
            triggered_by="test",
            detail={"note": "manual"},
            old_confidence="medium",
            new_confidence="high",
        )
        assert entry["memory_id"] == mid
        assert entry["event_type"] == "test_event"
        assert entry["old_confidence"] == "medium"
        assert entry["new_confidence"] == "high"


class TestResetStores:
    def test_reset_clears_memories(self, handler):
        handler.add_memory("Will be cleared", user_id="agent-1")
        handler.reset_stores()
        result = handler.list_memories(user_id="agent-1")
        memories = result["memories"]
        assert len(memories) == 0


# ============================================================
# Provenance (contradicts edges)
# ============================================================


class TestProvenanceContradicts:
    """Verify that add_memory does not create spurious provenance records."""

    def test_add_memory_creates_no_provenance(self, handler):
        """add_memory should not create any provenance records on its own."""
        result = handler.add_memory("Some fact", user_id="test")
        prov = handler._provenance
        assert len(prov) == 0
        assert result["memory_id"]
