"""Surprisal-based memory sampling for dream cycles.

Inspired by Honcho's geometric surprisal. Simplified to use
energy, access frequency, and recency as proxy for information novelty.

High surprisal = high energy + rarely accessed + not too old
= memories worth revisiting during dream consolidation.
"""

import time


def surprisal_score(
    energy: float,
    access_count: int,
    days_old: float,
) -> float:
    """Compute surprisal score for a memory.

    High score means the memory is surprising/novel:
    - High energy (important)
    - Low access count (rarely recalled)
    - Moderate age (not too old, not brand new)

    Returns: float in [0, 1] range
    """
    # Access rarity: 1/(1+count) — ranges from 1.0 (never accessed) to ~0
    rarity = 1.0 / (1.0 + access_count)

    # Recency factor: peaks around 1-7 days, decays after
    recency = 1.0 / (1.0 + max(0, days_old) / 7.0)

    return energy * rarity * recency


def select_by_surprisal(
    dream_data: list[dict],
    n: int = 5,
) -> list[str]:
    """Select top-N memory IDs by surprisal score.

    Args:
        dream_data: List of dicts with keys: id, energy, access_count, timestamp
        n: Number of memories to select
    """
    if not dream_data:
        return []

    now = time.time()
    scored = []
    for d in dream_data:
        days_old = (now - d.get("timestamp", now)) / 86400
        score = surprisal_score(
            energy=d.get("energy", 0.5),
            access_count=d.get("access_count", 0) or 0,
            days_old=days_old,
        )
        scored.append((d["id"], score))

    scored.sort(key=lambda x: -x[1])
    return [s[0] for s in scored[:n]]
