# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
"""Tests for pulse/brain/grounding.py — Grounded Knowledge system."""
import json
import pytest
from pulse.core.brain_db import get_conn, insert_knowledge


# Helper: insert a test item and return its id + fingerprint
def _insert_test_item(table="lessons", content="grounding test item", conf=0.5):
    from pulse.brain.save_writers.jsonl_store import build_jsonl_entry
    entry = build_jsonl_entry(content, "test_agent", "2026-03-19T12:00:00Z", "testing", conf, 3.0)
    insert_knowledge(table, entry)
    return entry["id"], entry["fingerprint"]


class TestMaybePromote:
    """Test grounding promotion logic."""

    def test_promote_on_reward_credit(self):
        """Item promoted to CONFIRMED when reward credit >= 0.40."""
        from pulse.brain.integrity.grounding import maybe_promote
        item_id, fp = _insert_test_item(content="promote on reward test xyz123")
        result = maybe_promote(item_id, "lessons", trigger="reward",
                               evidence={"credit": 0.50, "relevance": 0.8})
        assert result is True
        # Verify metadata
        conn = get_conn()
        row = conn.execute("SELECT metadata FROM lessons WHERE id = ?", (item_id,)).fetchone()
        meta = json.loads(row["metadata"])
        assert meta["source_type"] == "CONFIRMED"
        assert len(meta["ground_events"]) >= 1
        assert meta["ground_events"][-1]["trigger"] == "reward"
        # Cleanup
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_no_promote_below_credit_threshold(self):
        """Item NOT promoted when credit < 0.40."""
        from pulse.brain.integrity.grounding import maybe_promote
        item_id, fp = _insert_test_item(content="no promote low credit abc456")
        result = maybe_promote(item_id, "lessons", trigger="reward",
                               evidence={"credit": 0.20, "relevance": 0.8})
        assert result is False
        conn = get_conn()
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_ec2_relevance_gate(self):
        """EC2: Item NOT promoted when relevance < 0.5 even with high credit."""
        from pulse.brain.integrity.grounding import maybe_promote
        item_id, fp = _insert_test_item(content="relevance gate test def789")
        result = maybe_promote(item_id, "lessons", trigger="reward",
                               evidence={"credit": 0.90, "relevance": 0.3})
        assert result is False, "Should reject low-relevance promotion"
        conn = get_conn()
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_hard_trigger_always_promotes(self):
        """Hard triggers (test_pass, task_success) always promote."""
        from pulse.brain.integrity.grounding import maybe_promote
        item_id, fp = _insert_test_item(content="hard trigger test ghi012")
        result = maybe_promote(item_id, "lessons", trigger="task_success",
                               evidence={"task_id": "T-999"})
        assert result is True
        conn = get_conn()
        meta = json.loads(conn.execute("SELECT metadata FROM lessons WHERE id = ?",
                                       (item_id,)).fetchone()["metadata"])
        assert meta["source_type"] == "CONFIRMED"
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_already_confirmed_skipped(self):
        """Already CONFIRMED items are not re-promoted."""
        from pulse.brain.integrity.grounding import maybe_promote
        item_id, fp = _insert_test_item(content="already confirmed test jkl345")
        # First promote
        maybe_promote(item_id, "lessons", trigger="task_success", evidence={})
        # Second attempt should return False
        result = maybe_promote(item_id, "lessons", trigger="reward",
                               evidence={"credit": 0.90, "relevance": 0.9})
        assert result is False
        conn = get_conn()
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_ec5_ground_events_capped(self):
        """EC5: ground_events capped at MAX_GROUND_EVENTS."""
        from pulse.brain.integrity.grounding import maybe_promote, MAX_GROUND_EVENTS
        item_id, fp = _insert_test_item(content="events cap test mno678")
        conn = get_conn()
        # Seed with 25 fake events
        meta = {"ground_events": [{"ts": "old", "trigger": f"t{i}"} for i in range(25)]}
        conn.execute("UPDATE lessons SET metadata = ? WHERE id = ?",
                     (json.dumps(meta), item_id))
        conn.commit()
        # Promote — should cap events
        maybe_promote(item_id, "lessons", trigger="task_success", evidence={})
        row = conn.execute("SELECT metadata FROM lessons WHERE id = ?", (item_id,)).fetchone()
        final_meta = json.loads(row["metadata"])
        assert len(final_meta["ground_events"]) <= MAX_GROUND_EVENTS
        assert final_meta.get("ground_event_count", 0) >= 1
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()


class TestMaybeDemote:
    """EC1: Test demotion from CONFIRMED → CONTESTED."""

    def test_demote_confirmed_to_contested(self):
        """CONFIRMED item demoted to CONTESTED on contradiction."""
        from pulse.brain.integrity.grounding import maybe_promote, maybe_demote
        item_id, fp = _insert_test_item(content="demote test pqr901")
        maybe_promote(item_id, "lessons", trigger="task_success", evidence={})
        # Now demote
        result = maybe_demote(item_id, "lessons", reason="contradiction_detected")
        assert result is True
        conn = get_conn()
        meta = json.loads(conn.execute("SELECT metadata FROM lessons WHERE id = ?",
                                       (item_id,)).fetchone()["metadata"])
        assert meta["source_type"] == "CONTESTED"
        assert any(e["trigger"] == "demotion" for e in meta["ground_events"])
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_demote_conversational_is_noop(self):
        """CONVERSATIONAL items can't be demoted (not promoted yet)."""
        from pulse.brain.integrity.grounding import maybe_demote
        item_id, fp = _insert_test_item(content="no demote conversational stu234")
        result = maybe_demote(item_id, "lessons")
        assert result is False
        conn = get_conn()
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()

    def test_contested_item_cannot_be_promoted(self):
        """Contested items must not be promotable."""
        from pulse.brain.integrity.grounding import maybe_promote
        item_id, fp = _insert_test_item(content="contested no promote vwx567")
        conn = get_conn()
        conn.execute("UPDATE lessons SET validity = 'contested' WHERE id = ?", (item_id,))
        conn.commit()
        result = maybe_promote(item_id, "lessons", trigger="task_success", evidence={})
        assert result is False
        conn.execute("DELETE FROM lessons WHERE id = ?", (item_id,))
        conn.execute("DELETE FROM knowledge_fts WHERE item_id = ?", (item_id,))
        conn.commit()
