"""
Phase 3A: Global Workspace Bus

Competition arena, ignition, broadcast.
Replaces feed-forward pipeline with competitive broadcasting.
Sacred Boundary #3: suppression audit trail — logs what was rejected and why.
"""
import json
from datetime import datetime, timezone
from pathlib import Path

from pulse.brain.specialists import (
    get_memory_coalition, get_prediction_coalition, get_dmn_coalition,
    get_reflex_coalition, get_neural_state_coalition, get_working_memory_coalition,
    get_governance_coalition
)
from pulse.core import interoception
from pulse.core import event_bus
from pulse.core.paths import get_state_dir

_SUPPRESSION_LOG = get_state_dir() / "workspace_suppression.jsonl"

def compute_dynamic_threshold() -> float:
    """Returns 0.5 under high load, else 0.3"""
    interoception.load_signals()
    load = interoception._signals.get("agent_load", {}).get("current_value", 0.0)
    return 0.5 if load > 5.0 else 0.3

def run_workspace_ignition(agent: str, query: str, search_results: dict, task_type: str = "general") -> dict:
    """
    Runs the workspace competition.
    Returns the broadcast message containing the winning items.
    """
    threshold = compute_dynamic_threshold()
    
    coalitions = [
        get_memory_coalition(query, search_results, task_type),
        get_prediction_coalition(),
        get_dmn_coalition(),
        get_reflex_coalition(),
        get_neural_state_coalition(),
        get_working_memory_coalition(agent),
        get_governance_coalition() # Governance always admitted (high urgency)
    ]
    
    # Governance is special - ensure it passes threshold but doesn't always dominate top-3
    for c in coalitions:
        if c.source == "governance" and c.items:
            c.activation = max(c.activation, threshold + 0.01)
            
    # Filter by threshold and sort
    valid_coalitions = [c for c in coalitions if c.activation >= threshold or c.source == "governance"]
    valid_coalitions.sort(key=lambda x: x.activation, reverse=True)

    # Top 3
    winners = valid_coalitions[:3]

    # Sacred Boundary #3: log suppressed candidates (append-only audit trail)
    rejected = [c for c in coalitions if c not in valid_coalitions]
    suppressed = valid_coalitions[3:]  # valid but below top-3
    if rejected or suppressed:
        try:
            entry = {
                "ts": datetime.now(timezone.utc).isoformat(),
                "agent": agent, "query": query[:200], "threshold": threshold,
                "rejected": [{"src": c.source, "act": round(c.activation, 3),
                              "n": len(c.items), "reason": "below_threshold"} for c in rejected],
                "suppressed": [{"src": c.source, "act": round(c.activation, 3),
                                "n": len(c.items), "reason": "below_top3"} for c in suppressed],
                "winners": [c.source for c in winners],
            }
            _SUPPRESSION_LOG.parent.mkdir(parents=True, exist_ok=True)
            with open(_SUPPRESSION_LOG, "a", encoding="utf-8") as f:
                f.write(json.dumps(entry) + "\n")
        except Exception:
            pass  # Never break workspace over audit logging

    # Merge into broadcast
    broadcast_items = []
    for w in winners:
        broadcast_items.extend(w.items)

    # Skip empty broadcasts early
    if not broadcast_items:
        return {"agent": agent, "query": query, "task_type": task_type, "winning_sources": [], "items": []}

    broadcast = {
        "agent": agent,
        "query": query,
        "task_type": task_type,
        "winning_sources": [w.source for w in winners],
        "items": broadcast_items
    }

    # Recurrent loop: reinforce winning items in SQLite (DMN / Predictions)
    try:
        from pulse.core.brain_db import get_conn
        conn = get_conn()
        for item in broadcast_items:
            item_id = item.get("id") or item.get("item_id")
            if item_id:
                conn.execute("UPDATE lessons SET access_count = access_count + 1 WHERE id = ?", (item_id,))
                conn.execute("UPDATE failures SET access_count = access_count + 1 WHERE id = ?", (item_id,))
                conn.execute("UPDATE patterns SET access_count = access_count + 1 WHERE id = ?", (item_id,))
        conn.commit()
    except Exception:
        pass

    # Gentleness Principle: flag low-confidence broadcasts for human review
    try:
        confidences = [item.get("confidence", 1.0) for item in broadcast_items if isinstance(item, dict)]
        if confidences:
            avg_conf = sum(confidences) / len(confidences)
            if avg_conf < 0.7:
                broadcast["requires_human_review"] = True
    except Exception:
        pass

    event_bus.publish("workspace.broadcast", "global_workspace", broadcast)
    
    return broadcast
