"""Tests for core types — MemoryNode, MemoryType, MemoryStatus, etc."""

from datetime import datetime, timezone
from mnemosynth.core.types import (
    MemoryNode,
    MemoryType,
    MemoryStatus,
    MemorySource,
    ExtractionMethod,
    RelationshipEdge,
)


class TestMemoryType:
    def test_values(self):
        assert MemoryType.EPISODIC.value == "episodic"
        assert MemoryType.SEMANTIC.value == "semantic"
        assert MemoryType.PROCEDURAL.value == "procedural"

    def test_from_string(self):
        assert MemoryType("episodic") == MemoryType.EPISODIC
        assert MemoryType("semantic") == MemoryType.SEMANTIC


class TestMemoryStatus:
    def test_values(self):
        assert MemoryStatus.ACTIVE.value == "active"
        assert MemoryStatus.DEPRECATED.value == "deprecated"
        assert MemoryStatus.QUARANTINED.value == "quarantined"


class TestMemorySource:
    def test_default(self):
        source = MemorySource()
        assert source.reliability == 0.95
        assert source.extraction_method == ExtractionMethod.USER_STATEMENT

    def test_serialization(self):
        source = MemorySource(
            session_id="sess_123",
            extraction_method=ExtractionMethod.LLM_EXTRACTION,
            original_text="User said hello",
            model_used="gpt-4",
            reliability=0.7,
        )
        d = source.to_dict()
        restored = MemorySource.from_dict(d)
        assert restored.session_id == "sess_123"
        assert restored.extraction_method == ExtractionMethod.LLM_EXTRACTION
        assert restored.reliability == 0.7


class TestMemoryNode:
    def test_create(self):
        node = MemoryNode.create(
            content="User prefers dark mode",
            memory_type=MemoryType.SEMANTIC,
        )
        assert node.content == "User prefers dark mode"
        assert node.memory_type == MemoryType.SEMANTIC
        assert node.status == MemoryStatus.ACTIVE
        assert node.confidence == 0.85
        assert len(node.id) > 0

    def test_touch(self):
        node = MemoryNode.create(content="Test")
        old_count = node.access_count
        node.touch()
        assert node.access_count == old_count + 1

    def test_deprecate(self):
        node = MemoryNode.create(content="Old fact")
        node.deprecate(superseded_by_id="new_id")
        assert node.status == MemoryStatus.DEPRECATED
        assert node.superseded_by == "new_id"
        assert node.valid_until is not None

    def test_corroborate(self):
        node = MemoryNode.create(content="Fact", confidence=0.80)
        old_confidence = node.confidence
        node.corroborate()
        assert node.corroboration_count == 1
        assert node.confidence > old_confidence

    def test_quarantine(self):
        node = MemoryNode.create(content="Suspicious")
        node.quarantine()
        assert node.status == MemoryStatus.QUARANTINED

    def test_serialization_roundtrip(self):
        node = MemoryNode.create(
            content="Test memory",
            memory_type=MemoryType.EPISODIC,
            confidence=0.9,
            tags=["test", "demo"],
        )
        d = node.to_dict()
        restored = MemoryNode.from_dict(d)

        assert restored.id == node.id
        assert restored.content == node.content
        assert restored.memory_type == node.memory_type
        assert restored.confidence == node.confidence
        assert restored.tags == ["test", "demo"]

    def test_repr(self):
        node = MemoryNode.create(content="A short memory")
        r = repr(node)
        assert "MemoryNode" in r
        assert "semantic" in r


class TestRelationshipEdge:
    def test_create(self):
        edge = RelationshipEdge(
            source_id="node_1",
            target_id="node_2",
            relation_type="related_to",
        )
        assert edge.source_id == "node_1"
        assert edge.confidence == 0.8

    def test_serialization(self):
        edge = RelationshipEdge(
            source_id="a",
            target_id="b",
            relation_type="overwritten_by",
            confidence=0.95,
        )
        d = edge.to_dict()
        restored = RelationshipEdge.from_dict(d)
        assert restored.relation_type == "overwritten_by"
        assert restored.confidence == 0.95
