# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Working memory buffer subsystem: broadcast IOR, phonological loop, visuospatial sketch."""
import contextvars
import hashlib

_active_agent: contextvars.ContextVar = contextvars.ContextVar("active_agent", default="system")
_RECENTLY_BROADCAST: dict = {}   # {agent: {item_id: timestamp}}
_PRECONSCIOUS_BUFFER: dict = {}  # {agent: []}
_PHONOLOGICAL_BUFFER: dict = {}  # {agent: {}}
_PHONOLOGICAL_TTL = 300
_VISUOSPATIAL_SKETCH: dict = {}  # {agent: []}
_SKETCH_MAX = 50


def _fingerprint(text: str) -> str:
    """Aligned with brain_search._item_key (80 chars)."""
    return hashlib.md5(text[:80].lower().strip().encode("utf-8")).hexdigest()[:12]


def _mark_broadcast(item_ids: list):
    import time
    now = time.time()
    agent = _active_agent.get()
    buf = _RECENTLY_BROADCAST.setdefault(agent, {})
    for iid in item_ids:
        buf[iid] = now
    cutoff = now - 30
    for k in list(buf):
        if buf[k] < cutoff:
            del buf[k]


def _get_ior_penalty(item_id: str) -> float:
    import time
    agent = _active_agent.get()
    buf = _RECENTLY_BROADCAST.setdefault(agent, {})
    ts = buf.get(item_id)
    if ts and (time.time() - ts) < 30:
        return 0.15
    return 0.0


def _add_phonological(text: str):
    """Item 66: phonological loop (5min TTL)."""
    import time
    try:
        agent = _active_agent.get()
        buf = _PHONOLOGICAL_BUFFER.setdefault(agent, {})
        fp = _fingerprint(text); ts = time.time()
        buf[fp] = {"text": text[:200], "ts": ts}
        cutoff = ts - _PHONOLOGICAL_TTL
        for k in list(buf):
            if buf[k]["ts"] < cutoff:
                del buf[k]
    except Exception:
        pass


def _update_sketch(node_ids: list):
    """Item 67: visuospatial sketchpad (recent graph nodes)."""
    try:
        agent = _active_agent.get()
        buf = _VISUOSPATIAL_SKETCH.setdefault(agent, [])
        for nid in node_ids:
            if nid not in buf:
                buf.append(nid)
        while len(buf) > _SKETCH_MAX:
            buf.pop(0)
    except Exception:
        pass
