"""Integration tests — full SDK import verification and component interaction."""

from __future__ import annotations

from types import SimpleNamespace

import arandu
from arandu.config import MemoryConfig
from arandu.read.pipeline import ScoredFact, format_context
from arandu.read.retrieval import (
    RetrievalCandidate,
    compute_pattern_signal,
    merge_and_rank,
)
from arandu.write.upsert import UpsertResult

# ---------------------------------------------------------------------------
# Package-level imports
# ---------------------------------------------------------------------------


def test_all_exports_accessible():
    """All public exports should be importable from the top-level package."""
    assert hasattr(arandu, "MemoryClient")
    assert hasattr(arandu, "MemoryConfig")
    assert hasattr(arandu, "EmbeddingProvider")
    assert hasattr(arandu, "LLMProvider")
    # Background
    assert hasattr(arandu, "ClusteringResult")
    assert hasattr(arandu, "ConsolidationResult")
    assert hasattr(arandu, "EntityImportanceResult")
    assert hasattr(arandu, "MemifyResult")
    assert hasattr(arandu, "SummaryRefreshResult")
    # Functions
    assert hasattr(arandu, "compute_vitality")
    assert hasattr(arandu, "run_memify")
    assert hasattr(arandu, "compute_entity_importance")


def test_version_exists():
    """Package should have a version string."""
    assert arandu.__version__


# ---------------------------------------------------------------------------
# Read pipeline components interaction
# ---------------------------------------------------------------------------


def test_merge_and_rank_integration():
    """Merge semantic + keyword candidates and rank by combined score."""
    config = MemoryConfig()
    fact1 = SimpleNamespace(
        id="f1",
        fact_text="Lives in SP",
        entity_name="user",
        attribute_key="home.city",
        confidence=0.9,
        importance=0.7,
        valid_from=None,
    )
    fact2 = SimpleNamespace(
        id="f2",
        fact_text="Works at ACME",
        entity_name="user",
        attribute_key="work.company",
        confidence=0.8,
        importance=0.5,
        valid_from=None,
    )

    sem = [RetrievalCandidate(fact=fact1, scores={"semantic": 0.85}, final_score=0.85)]
    kw = [
        RetrievalCandidate(fact=fact1, scores={"keyword": 0.7}, final_score=0.7),
        RetrievalCandidate(fact=fact2, scores={"keyword": 0.6}, final_score=0.6),
    ]

    ranked = merge_and_rank(sem, kw, config)
    assert len(ranked) == 2
    # fact1 should rank higher (has both semantic + keyword)
    assert ranked[0].fact.id == "f1"
    assert "semantic" in ranked[0].scores
    assert "keyword" in ranked[0].scores


def test_pattern_signal_boosts_reinforced():
    """Pattern signal should boost reinforced facts."""
    fact = SimpleNamespace(
        id="f1",
        reinforcement_count=5,
    )
    candidates = [RetrievalCandidate(fact=fact, scores={"semantic": 0.8}, final_score=0.8)]
    result = compute_pattern_signal(candidates)
    assert result[0].final_score > 0.8
    assert "pattern" in result[0].scores


def test_pattern_signal_no_boost_zero_reinforcement():
    """Facts with zero reinforcement should not be boosted."""
    fact = SimpleNamespace(id="f1", reinforcement_count=0)
    candidates = [RetrievalCandidate(fact=fact, scores={"semantic": 0.8}, final_score=0.8)]
    result = compute_pattern_signal(candidates)
    assert result[0].final_score == 0.8


# ---------------------------------------------------------------------------
# Context formatting
# ---------------------------------------------------------------------------


def test_format_context_with_scored_facts():
    """format_context should produce readable output."""
    facts = [
        ScoredFact(fact_id="1", entity_name="user", fact_text="Lives in SP", scores={"confidence": 0.95}),
        ScoredFact(fact_id="2", entity_name="user", fact_text="Works at ACME", scores={"confidence": 0.80}),
    ]
    ctx = format_context(facts)
    assert "Lives in SP" in ctx
    assert "Works at ACME" in ctx
    assert "confidence: 0.95" in ctx


def test_format_context_empty():
    """Empty facts → empty string."""
    assert format_context([]) == ""


# ---------------------------------------------------------------------------
# Write components
# ---------------------------------------------------------------------------


def test_upsert_result_defaults():
    """UpsertResult should have sane defaults."""
    r = UpsertResult()
    assert r.added == 0
    assert r.updated == 0
    assert r.confirmed == []
    assert r.deleted == []


# ---------------------------------------------------------------------------
# Config completeness
# ---------------------------------------------------------------------------


def test_config_has_all_sections():
    """MemoryConfig should have all configuration sections."""
    c = MemoryConfig()
    # Extraction
    assert c.extraction_timeout_sec > 0
    # Retrieval
    assert c.topk_facts > 0
    # Context compression
    assert c.context_max_tokens > 0
    # Clustering
    assert c.cluster_max_age_days > 0
    # Consolidation
    assert c.consolidation_min_events > 0
    # Sleep-time
    assert c.importance_recency_halflife_days > 0
    # Memify
    assert c.vitality_stale_threshold > 0
    # Procedural
    assert c.directive_max_tokens > 0
    assert c.contradiction_similarity_threshold > 0
