"""Tests for procedural memory — confidence decay, cache, contradiction, directives."""

from __future__ import annotations

import asyncio
from datetime import UTC, datetime, timedelta

from arandu.read.procedural import (
    ContradictionResult,
    DirectiveBlock,
    _clear_all_caches,
    _cosine_similarity,
    effective_confidence,
)


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


# ---------------------------------------------------------------------------
# effective_confidence
# ---------------------------------------------------------------------------


def test_effective_confidence_no_decay():
    """Just created → ~base_confidence."""
    now = datetime.now(UTC)
    result = effective_confidence(0.9, now, now)
    assert abs(result - 0.9) < 0.01


def test_effective_confidence_one_week():
    """After 1 week → base * 0.95."""
    now = datetime.now(UTC)
    one_week_ago = now - timedelta(weeks=1)
    result = effective_confidence(1.0, one_week_ago, now)
    assert abs(result - 0.95) < 0.01


def test_effective_confidence_four_weeks():
    """After ~4 weeks → base * 0.95^4 ≈ 0.815."""
    now = datetime.now(UTC)
    four_weeks_ago = now - timedelta(weeks=4)
    result = effective_confidence(1.0, four_weeks_ago, now)
    expected = 0.95**4
    assert abs(result - expected) < 0.01


def test_effective_confidence_floor():
    """Very old → floored at 0.10."""
    now = datetime.now(UTC)
    very_old = now - timedelta(days=365 * 5)
    result = effective_confidence(0.5, very_old, now)
    assert result == 0.10


def test_effective_confidence_naive_datetime():
    """Naive datetime should be treated as UTC."""
    now = datetime.now(UTC)
    naive = now.replace(tzinfo=None)
    result = effective_confidence(0.9, naive, now)
    assert abs(result - 0.9) < 0.01


# ---------------------------------------------------------------------------
# DirectiveBlock defaults
# ---------------------------------------------------------------------------


def test_directive_block_defaults():
    """DirectiveBlock should have sane defaults."""
    block = DirectiveBlock()
    assert block.text == ""
    assert block.directive_count == 0
    assert block.cache_hit is False


# ---------------------------------------------------------------------------
# ContradictionResult defaults
# ---------------------------------------------------------------------------


def test_contradiction_result_defaults():
    """ContradictionResult should have sane defaults."""
    result = ContradictionResult()
    assert result.has_contradiction is False
    assert result.conflicting_directive is None
    assert result.resolution is None


# ---------------------------------------------------------------------------
# _cosine_similarity
# ---------------------------------------------------------------------------


def test_cosine_identical():
    """Identical vectors → 1.0."""
    v = [0.5, 0.5, 0.5]
    assert abs(_cosine_similarity(v, v) - 1.0) < 0.001


def test_cosine_empty():
    """Empty vectors → 0.0."""
    assert _cosine_similarity([], []) == 0.0


# ---------------------------------------------------------------------------
# Cache
# ---------------------------------------------------------------------------


def test_clear_all_caches():
    """_clear_all_caches should not raise."""
    _clear_all_caches()  # Just verify it works without error
