"""P13 Neuroscience Refinements — Tests (Items 46-50)."""
import importlib.util as _ilu, json, sqlite3, sys, types
from pathlib import Path
from unittest.mock import patch

ROOT = Path(__file__).parent.parent
sys.path.insert(0, str(ROOT))

# ── Minimal stubs for heavy pulse deps ────────────────────────────────────────
_STUBS = {
    "pulse": {}, "pulse.core": {}, "pulse.brain": {},
    "pulse.core.paths": {"get_state_dir": lambda: Path("."), "get_brain_dir": lambda: Path(".")},
    "pulse.core.brain_utils": {"AGENT_REGISTRY_FILE": Path("r.json"), "HIPPOCAMPUS_DIR": Path("."),
                                "load_json_dict": lambda f: {}, "_make_fingerprint": lambda s: "fp"},
    "pulse.core.interoception": {"get_signals": lambda: {}},
    "pulse.core.event_bus": {"publish": lambda *a, **kw: None},
}
for _n, _a in _STUBS.items():
    if _n not in sys.modules:
        _m = types.ModuleType(_n)
        for _k, _v in _a.items():
            setattr(_m, _k, _v)
        sys.modules[_n] = _m

# ── SQLite helpers ────────────────────────────────────────────────────────────
_COLS = ("id TEXT PRIMARY KEY,content TEXT,domain TEXT DEFAULT 'general',"
         "confidence REAL DEFAULT 0.5,agent TEXT DEFAULT 'unknown',"
         "validity TEXT DEFAULT 'valid',metadata TEXT DEFAULT '{{}}'")


def _conn(rows=None):
    """In-memory SQLite with lessons/failures/procedures."""
    c = sqlite3.connect(":memory:")
    c.row_factory = sqlite3.Row
    for t, extra in [("lessons", ",access_count INTEGER DEFAULT 0"),
                     ("failures", ",access_count INTEGER DEFAULT 0"),
                     ("procedures", ",name TEXT DEFAULT ''")]:
        c.execute(f"CREATE TABLE {t}({_COLS.format()}{extra})")
    if rows:
        for tbl, data in rows.items():
            for r in data:
                k, v = zip(*r.items())
                c.execute(f"INSERT INTO {tbl}({','.join(k)}) VALUES ({','.join('?'*len(v))})", v)
    c.commit()
    return c


def _fdb(c):
    m = types.ModuleType("pulse.core.brain_db")
    m.get_conn = lambda: c
    return m


# ── Module loaders (spec_from_file_location avoids stub package conflicts) ────

def _briefing(c=None):
    qs = types.ModuleType("pulse.brain.brain_query.query_search")
    for attr in ("_find_refinable_items","_load_active_broadcasts",
                 "_get_recommended_sequences","_get_competence_lines"):
        setattr(qs, attr, lambda *a: [])
    qs._search_skills = qs._search_tools = lambda q: ""
    mm = types.ModuleType("pulse.brain.metacognition.metamemory")
    mm.get_metamemory = lambda: {}
    sys.modules.update({"pulse.brain.brain_query.query_search": qs,
        "pulse.brain.query_search": qs,
        "pulse.brain.workspace.workspace_integrator": types.ModuleType("pulse.brain.workspace.workspace_integrator"),
        "pulse.brain.metacognition.metamemory": mm, "pulse.core.brain_db": _fdb(c or _conn())})
    spec = _ilu.spec_from_file_location("briefing46", ROOT/"pulse/brain/brain_query/briefing.py")
    mod = _ilu.module_from_spec(spec); spec.loader.exec_module(mod)
    return mod


def _res(hits, total=1):
    return {"results": hits, "total_results": total, "elapsed_ms": 0}


# ── Item 46: Surprise detection ───────────────────────────────────────────────

def test_46_surprise_prepended():
    """SURPRISE prepended on high-conf contradiction (>0.95 + flag)."""
    out = _briefing().format_briefing("q", _res(
        {"wins": [{"_contradiction_flag": True, "confidence": 0.97, "text": "Conflict!"}]}))
    assert "!! SURPRISE:" in out


def test_46_no_surprise_below_threshold():
    # Threshold lowered to 0.6 (Fix 7: contradiction penalty floors at 0.7x so 0.95 unreachable)
    out = _briefing().format_briefing("q", _res(
        {"wins": [{"_contradiction_flag": True, "confidence": 0.55, "text": "low"}]}))
    assert "!! SURPRISE:" not in out


def test_46_no_surprise_without_flag():
    out = _briefing().format_briefing("q", _res({"wins": [{"confidence": 0.99, "text": "ok"}]}))
    assert "!! SURPRISE:" not in out


def test_46_fails_open_bad_confidence():
    """Surprise block is fail-open: bad confidence in one item doesn't prevent output."""
    # Provide one valid item + one item with bad confidence in a different source
    out = _briefing().format_briefing("q", _res(
        {"wins": [{"confidence": 0.8, "text": "valid result"}],
         "fails": [{"_contradiction_flag": True, "confidence": "bad", "text": "x"}]}))
    assert isinstance(out, str)


def test_46_uses_content_fallback():
    out = _briefing().format_briefing("q", _res(
        {"fails": [{"_contradiction_flag": True, "confidence": 0.96, "text": "", "content": "cb"}]}))
    assert "!! SURPRISE:" in out

# ── Item 47: Predictive triage ────────────────────────────────────────────────

def test_47_triage_shown_for_declining():
    c = _conn(rows={"lessons": [{"id":"L1","content":"dying","domain":"general",
        "confidence":0.25,"agent":"t","validity":"valid","metadata":"{}","access_count":0}]})
    b = _briefing(c)
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    out = b.format_briefing("q", _res({"wins":[{"text":"r","confidence":0.8,"domain":"general"}]}))
    assert "!! PREDICTIVE TRIAGE:" in out


def test_47_triage_absent_healthy():
    c = _conn(rows={"lessons": [{"id":"L2","content":"ok","domain":"general",
        "confidence":0.85,"agent":"t","validity":"valid","metadata":"{}","access_count":0}]})
    b = _briefing(c)
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    out = b.format_briefing("q", _res({"wins":[{"text":"r","confidence":0.8,"domain":"general"}]}))
    assert "!! PREDICTIVE TRIAGE:" not in out


def test_47_fails_open_db_error():
    bad = types.ModuleType("pulse.core.brain_db")
    bad.get_conn = lambda: (_ for _ in ()).throw(RuntimeError("down"))
    b = _briefing()
    sys.modules["pulse.core.brain_db"] = bad
    assert isinstance(b.format_briefing("q", _res({"wins":[{"text":"r","confidence":0.7}]})), str)


def test_47_excludes_very_low_conf():
    c = _conn(rows={"lessons": [{"id":"L3","content":"dead","domain":"general",
        "confidence":0.05,"agent":"t","validity":"valid","metadata":"{}","access_count":0}]})
    b = _briefing(c)
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    out = b.format_briefing("q", _res({"wins":[{"text":"r","confidence":0.7,"domain":"general"}]}))
    assert "!! PREDICTIVE TRIAGE:" not in out


# ── Item 48: Cross-agent procedure sharing ────────────────────────────────────

def _ap(c=None):
    if c:
        sys.modules["pulse.core.brain_db"] = _fdb(c)
    spec = _ilu.spec_from_file_location("ap48", ROOT/"pulse/brain/agent_procedures.py")
    mod = _ilu.module_from_spec(spec); spec.loader.exec_module(mod)
    return mod


_PROFILE = {"agent_id":"claude","model":"claude","total_tasks":5,"tasks_succeeded":1,
            "tasks_failed":4,"overall_success_rate":0.2,
            "domains":{"python":{"success":1,"failure":4,"total":5,"success_rate":0.2}}}


def test_48_cross_agent_included():
    c = _conn(rows={"procedures":[{"id":"P1","content":"step","domain":"python",
        "confidence":0.9,"agent":"gemini","validity":"valid","metadata":"{}","name":"Sh"}]})
    ap = _ap(c)
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    with patch.object(ap,"get_agent_profile",return_value=_PROFILE), \
         patch.object(ap,"_load_procedures",return_value=[]):
        r = ap.match_procedures("claude",max_items=10)
    assert any(x.get("_cross_agent") for x in r)


def test_48_excludes_same_agent():
    c = _conn(rows={"procedures":[{"id":"P2","content":"own","domain":"python",
        "confidence":0.95,"agent":"claude","validity":"valid","metadata":"{}","name":"Ow"}]})
    ap = _ap(c)
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    with patch.object(ap,"get_agent_profile",return_value=_PROFILE), \
         patch.object(ap,"_load_procedures",return_value=[]):
        r = ap.match_procedures("claude",max_items=10)
    assert not any(x.get("_cross_agent") for x in r)


def test_48_min_confidence_0_8():
    c = _conn(rows={"procedures":[{"id":"P3","content":"weak","domain":"python",
        "confidence":0.6,"agent":"gemini","validity":"valid","metadata":"{}","name":"Wk"}]})
    ap = _ap(c)
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    with patch.object(ap,"get_agent_profile",return_value=_PROFILE), \
         patch.object(ap,"_load_procedures",return_value=[]):
        r = ap.match_procedures("claude",max_items=10)
    assert not any(x.get("_cross_agent") for x in r)


def test_48_fails_open_db_error():
    bad = types.ModuleType("pulse.core.brain_db")
    bad.get_conn = lambda: (_ for _ in ()).throw(RuntimeError("db"))
    ap = _ap(); sys.modules["pulse.core.brain_db"] = bad
    with patch.object(ap,"get_agent_profile",return_value={}), \
         patch.object(ap,"_load_procedures",return_value=[]):
        assert isinstance(ap.match_procedures("claude"), list)


# ── Item 49: STABLE validity state ───────────────────────────────────────────
_enums = _ilu.spec_from_file_location("_enums49", ROOT/"pulse/core/enums.py")
_enums_mod = _ilu.module_from_spec(_enums); _enums.loader.exec_module(_enums_mod)
_temp_spec = _ilu.spec_from_file_location("_temp49", ROOT/"pulse/core/temporal.py")
_temp_mod = _ilu.module_from_spec(_temp_spec); _temp_spec.loader.exec_module(_temp_mod)


def test_49_stable_in_enum_and_states():
    assert _enums_mod.Validity.STABLE == "stable"
    assert "stable" in _enums_mod.VALIDITY_STATES


def test_49_transitions():
    assert _enums_mod.is_valid_transition("valid", "stable")
    assert _enums_mod.is_valid_transition("stable", "superseded")
    assert not _enums_mod.is_valid_transition("historical", "stable")


def test_49_promote_qualifies():
    item = {"validity":"valid","evidence_count":5,"confidence":0.75,"half_life_days":100.0}
    result = _temp_mod.promote_to_stable(item)
    assert result["validity"] == "stable" and result["half_life_days"] == 200.0


def test_49_promote_skips_low_ec_or_conf():
    assert _temp_mod.promote_to_stable({"validity":"valid","evidence_count":3,"confidence":0.9})["validity"] == "valid"
    assert _temp_mod.promote_to_stable({"validity":"valid","evidence_count":10,"confidence":0.65})["validity"] == "valid"


def test_49_promote_fails_open():
    assert isinstance(_temp_mod.promote_to_stable({"validity":"valid","evidence_count":"bad"}), dict)


def test_49_stable_constant_in_temporal():
    assert _temp_mod.STABLE == "stable"


# ── Item 50: Tombstoning ─────────────────────────────────────────────────────
_recon_spec = _ilu.spec_from_file_location("_recon50", ROOT/"pulse/brain/reconsolidation.py")


def _rc(c):
    """Fresh reconsolidation module wired to conn c."""
    sys.modules["pulse.core.brain_db"] = _fdb(c)
    mod = _ilu.module_from_spec(_recon_spec)
    _recon_spec.loader.exec_module(mod)
    mod.get_conn = lambda: c
    return mod


def _lc(rows=None):
    c = sqlite3.connect(":memory:")
    c.row_factory = sqlite3.Row
    c.execute("CREATE TABLE lessons(id TEXT PRIMARY KEY,content TEXT,"
              "validity TEXT DEFAULT 'valid',metadata TEXT DEFAULT '{}',"
              "domain TEXT DEFAULT 'general',confidence REAL DEFAULT 0.5,"
              "agent TEXT DEFAULT 'unknown',access_count INTEGER DEFAULT 0)")
    for r in (rows or []):
        k, v = zip(*r.items())
        c.execute(f"INSERT INTO lessons({','.join(k)}) VALUES ({','.join('?'*len(v))})", v)
    c.commit()
    return c


_ROW = {"id":"o1","content":"x","validity":"valid","metadata":"{}",
        "domain":"g","confidence":0.7,"agent":"a","access_count":0}


def test_50_tombstone_marks_superseded():
    c = _lc([_ROW])
    assert _rc(c).tombstone_item("o1","lessons","n1") is True
    assert c.execute("SELECT validity FROM lessons WHERE id='o1'").fetchone()["validity"] == "superseded"


def test_50_tombstone_writes_pointer():
    c = _lc([{**_ROW,"id":"o2"}])
    _rc(c).tombstone_item("o2","lessons","n2")
    meta = json.loads(c.execute("SELECT metadata FROM lessons WHERE id='o2'").fetchone()["metadata"])
    assert meta.get("superseded_by") == "n2"


def test_50_rejects_invalid_table():
    assert _rc(_lc()).tombstone_item("x","DROP TABLE--","y") is False


def test_50_missing_item_false():
    assert _rc(_lc()).tombstone_item("ghost","lessons","n") is False


def test_50_historical_untouched():
    c = _lc([{**_ROW,"id":"h1","validity":"historical"}])
    _rc(c).tombstone_item("h1","lessons","n")
    assert c.execute("SELECT validity FROM lessons WHERE id='h1'").fetchone()["validity"] == "historical"
