"""Tests for shadow mode claims_detail (#1285) and backward compat."""

from __future__ import annotations

import dataclasses
from unittest.mock import AsyncMock, MagicMock, patch

import pytest

from cortex.extraction.models import ClaimExtraction, EntityMention, ExtractionResult


@pytest.fixture
def sample_claim():
    """A ClaimExtraction with ALL 25 fields populated."""
    return ClaimExtraction(
        action="ADD",
        subject="Andrew",
        predicate="lives in",
        object_value="Bangkok",
        confidence=0.95,
        temporal="current",
        temporal_marker="now",
        entities_mentioned=[
            EntityMention(name="Andrew", entity_type="person", aliases=["Andy"]),
        ],
        sensitivity="normal",
        category="identity",
        intrinsic_type="fact",
        human_family="friend",
        explicitness="explicit",
        stability="stable",
        memory_class="semantic",
        status="active",
        event_date="2026-03-19",
        sequence_order=1,
        salience="high",
        cause="conversation",
        effect="stored",
        state_before="unknown",
        state_after="known",
    )


EXPECTED_FIELDS = {
    "action", "subject", "predicate", "object_value", "confidence",
    "temporal", "temporal_marker", "entities_mentioned", "sensitivity",
    "category", "intrinsic_type", "human_family", "explicitness",
    "stability", "memory_class", "status", "event_date", "sequence_order",
    "salience", "cause", "effect", "state_before", "state_after",
}


@pytest.mark.asyncio
async def test_shadow_remember_returns_claims_detail(sample_claim):
    """_shadow_remember() should return claims_detail with all ClaimExtraction fields."""
    from cortex.api.routes.memory.helpers import _shadow_remember

    mock_result = MagicMock()
    mock_result.claims = [sample_claim]
    mock_result.noise_filtered = 0

    mock_extractor = AsyncMock()
    mock_extractor.extract = AsyncMock(return_value=mock_result)

    mock_plugin = MagicMock()
    mock_plugin.extractor = mock_extractor

    result = await _shadow_remember(mock_plugin, "Andrew lives in Bangkok", "test-session", "owner-1")

    # claims_detail must exist
    assert "claims_detail" in result
    assert len(result["claims_detail"]) == 1

    detail = result["claims_detail"][0]

    # All expected fields present
    for f in EXPECTED_FIELDS:
        assert f in detail, f"Missing field: {f}"

    # Spot-check values
    assert detail["subject"] == "Andrew"
    assert detail["predicate"] == "lives in"
    assert detail["object_value"] == "Bangkok"
    assert detail["temporal"] == "current"
    assert detail["confidence"] == 0.95
    assert detail["category"] == "identity"
    assert detail["memory_class"] == "semantic"
    assert detail["salience"] == "high"

    # entities_mentioned should be serialized as dicts
    assert isinstance(detail["entities_mentioned"], list)
    assert len(detail["entities_mentioned"]) == 1
    ent = detail["entities_mentioned"][0]
    assert isinstance(ent, dict)
    assert ent["name"] == "Andrew"
    assert ent["entity_type"] == "person"


@pytest.mark.asyncio
async def test_shadow_remember_backward_compat_would_store(sample_claim):
    """would_store list must still be present for backward compatibility."""
    from cortex.api.routes.memory.helpers import _shadow_remember

    mock_result = MagicMock()
    mock_result.claims = [sample_claim]
    mock_result.noise_filtered = 0

    mock_extractor = AsyncMock()
    mock_extractor.extract = AsyncMock(return_value=mock_result)

    mock_plugin = MagicMock()
    mock_plugin.extractor = mock_extractor

    result = await _shadow_remember(mock_plugin, "Andrew lives in Bangkok", "test-session", "owner-1")

    assert "would_store" in result
    assert len(result["would_store"]) == 1
    assert "Andrew" in result["would_store"][0]
    assert "lives in" in result["would_store"][0]
    assert "Bangkok" in result["would_store"][0]


@pytest.mark.asyncio
async def test_shadow_remember_empty_claims():
    """Shadow mode with zero claims should return empty lists."""
    from cortex.api.routes.memory.helpers import _shadow_remember

    mock_result = MagicMock()
    mock_result.claims = []
    mock_result.noise_filtered = 0

    mock_extractor = AsyncMock()
    mock_extractor.extract = AsyncMock(return_value=mock_result)

    mock_plugin = MagicMock()
    mock_plugin.extractor = mock_extractor

    result = await _shadow_remember(mock_plugin, "hello", "test-session", "owner-1")

    assert result["claims_detail"] == []
    assert result["would_store"] == []
    assert result["claims_extracted"] == 0
