"""
Phase 3A: Global Workspace Specialists

7 Competing Specialists:
1. Memory Retrieval (brain_search results)
2. Prediction Oracle (prediction_alerts.json)
3. DMN Ideation (recent proposals)
4. Reflex Arc (mistake detections)
5. Neural State (session context + recommendations)
6. Working Memory (session buffer)
7. Governance (always-admit)
"""
import json
from pathlib import Path
from pulse.core.paths import get_state_dir
from pulse.brain.working_memory import get_active_contexts
from pulse.brain.attention import get_attention_weights

class Coalition:
    def __init__(self, source: str, items: list, activation: float):
        self.source = source
        self.items = items[:5] # Max 5 items per coalition
        self.activation = min(1.0, max(0.0, float(activation)))
        
    def to_dict(self):
        return {
            "source": self.source,
            "activation": self.activation,
            "items": self.items
        }

def _calc_activation(relevance: float, salience: float, urgency: float, reliability: float) -> float:
    return relevance * min(1.0, salience / 7.0) * urgency * reliability

# 1. Memory Retrieval
def get_memory_coalition(query: str, search_results: dict, task_type: str = "general") -> Coalition:
    if not search_results or not search_results.get("results"):
        return Coalition("memory", [], 0.0)
        
    weights = get_attention_weights(task_type)
    best_items = []
    
    # Flatten and sort
    for src, hits in search_results["results"].items():
        weight = weights.get(src, 1.0)
        for hit in hits:
            # Reconstruct an activation
            rel = hit.get("confidence", 0.5)
            sal = hit.get("salience", 1.0)
            act = _calc_activation(rel, sal, 0.5, weight) # baseline urgency 0.5
            hit["_gw_activation"] = act
            best_items.append(hit)
            
    best_items.sort(key=lambda x: x.get("_gw_activation", 0), reverse=True)
    top_items = best_items[:5]
    avg_act = sum(i["_gw_activation"] for i in top_items) / len(top_items) if top_items else 0.0
    
    return Coalition("memory", top_items, avg_act)

# 2. Prediction Oracle
def get_prediction_coalition() -> Coalition:
    alerts_file = get_state_dir() / "prediction_alerts.json"
    if not alerts_file.exists():
        return Coalition("prediction", [], 0.0)
        
    try:
        with open(alerts_file, "r", encoding="utf-8") as f:
            data = json.load(f)
            alerts = data.get("active_alerts", [])
            if not alerts:
                return Coalition("prediction", [], 0.0)
                
            # Highest confidence alert
            alerts.sort(key=lambda x: x.get("confidence", 0), reverse=True)
            top = alerts[:3]
            act = _calc_activation(1.0, 5.0, 0.9, top[0].get("confidence", 0.5))
            return Coalition("prediction", top, act)
    except Exception:
        pass
    return Coalition("prediction", [], 0.0)

# 3. DMN Ideation
def get_dmn_coalition() -> Coalition:
    proposals_file = get_state_dir() / "dmn" / "proposals.json"
    if not proposals_file.exists():
        return Coalition("dmn", [], 0.0)
        
    try:
        with open(proposals_file, "r", encoding="utf-8") as f:
            data = json.load(f)
            if not data:
                return Coalition("dmn", [], 0.0)
                
            # Get latest
            latest = data[-3:]
            act = _calc_activation(0.6, 3.0, 0.3, 0.8) # Low urgency, moderate relevance
            return Coalition("dmn", latest, act)
    except Exception:
        pass
    return Coalition("dmn", [], 0.0)

# 4. Reflex Arc (Mistakes)
def get_reflex_coalition() -> Coalition:
    try:
        from pulse.core.interoception import get_alerts
        alerts = get_alerts()
        error_alerts = [a for a in alerts if a["signal"] == "error_rate"]

        if error_alerts:
            act = _calc_activation(1.0, 7.0, 1.0, 1.0) # Maximum urgency
            return Coalition("reflex", error_alerts, act)
        return Coalition("reflex", [], 0.0)
    except Exception:
        return Coalition("reflex", [], 0.0)

# 5. Neural State
def get_neural_state_coalition() -> Coalition:
    import pulse.core.interoception as interoception
    interoception.load_signals()
    if not interoception._signals:
        return Coalition("neural_state", [], 0.0)

    act = _calc_activation(0.8, 2.0, 0.4, 1.0)
    return Coalition("neural_state", [{"type": "system_state", "metrics": interoception._signals}], act)

# 6. Working Memory
def get_working_memory_coalition(agent: str) -> Coalition:
    active = get_active_contexts(agent)
    if not active:
        return Coalition("working_memory", [], 0.0)
        
    act = _calc_activation(0.9, 4.0, 0.7, 1.0)
    return Coalition("working_memory", active, act)

# 7. Governance
def get_governance_coalition() -> Coalition:
    # Always admit if violations exist
    # Simplified mock for Phase 3 integration
    return Coalition("governance", [], 0.0)
