"""Tests for context compression — clean LLM-ready format."""

from __future__ import annotations

import asyncio
from datetime import UTC, datetime
from types import SimpleNamespace

from arandu.config import MemoryConfig
from arandu.read.context_compression import (
    CompressedContext,
    _est_tokens,
    compress_broad_context,
    compress_context,
)


def run_async(coro):
    return asyncio.run(coro)


def _make_fact_entry(
    entity: str = "person:Ana",
    attribute: str = "nome",
    value: str = "Ana",
    score: float = 0.9,
    *,
    is_stale: bool = False,
    valid_from: datetime | None = None,
) -> dict:
    """Create a fact entry dict with an embedded fact-like object."""
    fact = SimpleNamespace(
        is_stale=is_stale,
        attribute_key=attribute,
        valid_from=valid_from or datetime.now(UTC),
    )
    return {
        "fact": fact,
        "entity": entity,
        "attribute": attribute,
        "value": value,
        "score": score,
        "date": "2025-01-01",
    }


def test_est_tokens_basic():
    assert _est_tokens("abcd") == 1
    assert _est_tokens("12345678") == 2


def test_est_tokens_empty():
    assert _est_tokens("") == 0


def test_compressed_context_defaults():
    cc = CompressedContext()
    assert cc.context_text == ""
    assert cc.hot_count == 0


def test_compress_empty_facts():
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_context([], [], config))
    assert result.context_text == ""
    assert result.hot_count == 0


def test_compress_facts_clean_format():
    """Facts appear under 'Known facts:' with clean format (no timestamps)."""
    facts = [_make_fact_entry(score=0.9 - i * 0.1) for i in range(3)]
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_context(facts, [], config))
    assert "Known facts:" in result.context_text
    assert "- Ana" in result.context_text
    # No old-style formatting
    assert "CORE MEMORY" not in result.context_text
    assert "since" not in result.context_text
    assert "assert confidently" not in result.context_text


def test_compress_many_facts():
    facts = [_make_fact_entry(entity=f"person:P{i}", score=0.9 - i * 0.05) for i in range(10)]
    config = MemoryConfig(context_max_tokens=5000)
    result = run_async(compress_context(facts, [], config))
    assert result.hot_count + result.warm_count == 10


def test_compress_token_budget_respected():
    facts = [_make_fact_entry(entity=f"person:P{i}", value="x" * 200, score=0.9 - i * 0.01) for i in range(20)]
    config = MemoryConfig(context_max_tokens=500)
    result = run_async(compress_context(facts, [], config))
    assert result.total_tokens <= 800


def test_compress_with_events():
    """Events appear under 'Relevant conversations:' header."""
    facts = [_make_fact_entry(score=0.9)]
    events = [{"date": "2025-01-15", "text": "User mentioned feeling happy about the weekend"}]
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_context(facts, events, config))
    assert "Relevant conversations:" in result.context_text
    assert "feeling happy" in result.context_text
    assert result.cold_count >= 1


def test_compress_with_meta_observations():
    """Meta-observations appear under 'Observed patterns:' header."""
    facts = [_make_fact_entry(score=0.9)]
    obs = SimpleNamespace(
        observation_type="pattern",
        title="Weekly routine detected",
        confidence=0.85,
        times_reinforced=3,
    )
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_context(facts, [], config, meta_observations=[obs]))
    assert "Observed patterns:" in result.context_text
    assert "Weekly routine" in result.context_text


def test_compress_broad_context_basic():
    cluster = SimpleNamespace(label="work", summary_text="Work-related facts", fact_count=5)
    cluster_facts = {"work": [{"attribute": "role", "value": "Engineer"}]}
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_broad_context(cluster_facts, [cluster], config))
    assert "BRAIN OVERVIEW" in result.context_text


def test_compress_broad_context_empty():
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_broad_context({}, [], config))
    assert result.context_text == ""


def test_profiles_not_in_context():
    """Entity profiles are NOT in retrieval context."""
    facts = [_make_fact_entry(score=0.9)]
    config = MemoryConfig(context_max_tokens=2000)
    profiles = {"person:ana": "Ana is a software engineer."}
    result = run_async(compress_context(facts, [], config, entity_profiles=profiles))
    assert "ENTITY PROFILES" not in result.context_text
    assert "Known facts:" in result.context_text


def test_short_events_filtered():
    """Events shorter than 15 chars are filtered out."""
    facts = [_make_fact_entry(score=0.9)]
    events = [{"date": "2025-01-15", "text": "Hi"}]
    config = MemoryConfig(context_max_tokens=2000)
    result = run_async(compress_context(facts, events, config))
    assert "Relevant conversations:" not in result.context_text
