"""Tests for memory provenance tagging (issue #748).

Verifies that source_session_id, source_message_id, source_channel, source_type
flow through the pipeline and are stored and retrieved correctly.
"""

import json
import pytest
from cortex.api.models import RememberRequest, EnhancedRememberRequest
from cortex.types import CandidateClaim, SemanticClaim


class TestProvenanceSchema:
    """Verify provenance fields on request models."""

    def test_remember_request_has_provenance(self):
        req = RememberRequest(
            conversation="test",
            source_session_id="sess-abc",
            source_message_id="msg-123",
            source_channel="telegram",
            source_type="plugin_capture",
        )
        assert req.source_session_id == "sess-abc"
        assert req.source_message_id == "msg-123"
        assert req.source_channel == "telegram"
        assert req.source_type == "plugin_capture"

    def test_enhanced_remember_request_has_provenance(self):
        req = EnhancedRememberRequest(
            conversation=[{"role": "user", "content": "test"}],
            source_session_id="sess-xyz",
            source_message_id="msg-456",
            source_channel="webchat",
        )
        assert req.source_session_id == "sess-xyz"
        assert req.source_message_id == "msg-456"
        assert req.source_channel == "webchat"


class TestCandidateClaimMetadata:
    """Verify CandidateClaim can carry provenance metadata."""

    def test_metadata_with_provenance(self):
        claim = CandidateClaim(
            subject="Andrew",
            predicate="prefers",
            object_value="dark mode",
            metadata={
                "source_session_id": "sess-abc",
                "source_message_id": "msg-123",
            },
        )
        assert claim.metadata["source_session_id"] == "sess-abc"
        assert claim.metadata["source_message_id"] == "msg-123"


class TestSemanticClaimMetadataJson:
    """Verify SemanticClaim stores metadata_json."""

    def test_metadata_json_field(self):
        meta = {
            "source_session_id": "sess-abc",
            "source_message_id": "msg-123",
            "source_channel": "telegram",
        }
        claim = SemanticClaim(
            id="test-123",
            owner_id="default",
            subject="Andrew",
            predicate="prefers",
            object_value="dark mode",
            metadata_json=json.dumps(meta),
        )
        assert claim.metadata_json is not None
        parsed = json.loads(claim.metadata_json)
        assert parsed["source_session_id"] == "sess-abc"


class TestMigration:
    """Verify v15 migration exists."""

    def test_migration_v15_has_required_fields(self):
        from cortex.storage.migrations import v15_provenance
        assert v15_provenance.VERSION == 15
        assert v15_provenance.DESCRIPTION is not None
        assert "metadata_json" in v15_provenance.SQL_UP


class TestProvenanceFlow:
    """Integration-style test of provenance flow."""

    def test_provenance_in_metadata_json(self):
        """Verify provenance serializes to JSON."""
        candidate = CandidateClaim(
            subject="Andrew",
            predicate="prefers",
            object_value="dark mode",
            metadata={
                "source_session_id": "sess-test",
                "source_message_id": "msg-001",
                "source_channel": "webchat",
                "source_type": "plugin_capture",
            },
        )
        metadata_json = json.dumps(candidate.metadata, separators=(",", ":"))
        parsed = json.loads(metadata_json)
        assert parsed["source_session_id"] == "sess-test"
        assert parsed["source_message_id"] == "msg-001"
        assert parsed["source_channel"] == "webchat"
        assert parsed["source_type"] == "plugin_capture"
