"""Phase 6D: Collective Decision Making — multi-agent agreement protocol."""
import json
import uuid
from datetime import datetime, timezone
from pathlib import Path
from pulse.core.paths import get_state_dir
from pulse.core import event_bus

DECISIONS_FILE = get_state_dir() / "pending_decisions.json"


def _load_decisions() -> dict:
    if not DECISIONS_FILE.exists():
        return {"decisions": []}
    try:
        return json.loads(DECISIONS_FILE.read_text(encoding="utf-8"))
    except Exception:
        return {"decisions": []}


def _save_decisions(data: dict):
    DECISIONS_FILE.parent.mkdir(parents=True, exist_ok=True)
    DECISIONS_FILE.write_text(json.dumps(data, indent=2), encoding="utf-8")


def open_decision(title: str, description: str, decision_type: str = "architecture") -> str:
    """Post a decision for multi-agent voting. Returns decision ID."""
    decision = {
        "id": f"decision_{uuid.uuid4().hex[:8]}",
        "title": title,
        "description": description,
        "decision_type": decision_type,
        "created_at": datetime.now(timezone.utc).isoformat(),
        "status": "open",
        "positions": [],
        "synthesis": None,
    }
    data = _load_decisions()
    data["decisions"].append(decision)
    _save_decisions(data)
    event_bus.publish("decision.opened", "collective_decision", {"id": decision["id"], "title": title})
    return decision["id"]


def submit_position(decision_id: str, agent: str, position: str, reasoning: str, confidence: float) -> bool:
    """Agent submits a position on an open decision."""
    data = _load_decisions()
    for d in data["decisions"]:
        if d["id"] == decision_id and d["status"] == "open":
            # Prevent duplicate votes
            if any(p["agent"] == agent for p in d["positions"]):
                return False
            d["positions"].append({
                "agent": agent, "position": position,
                "reasoning": reasoning, "confidence": max(0.0, min(1.0, confidence)),
            })
            _save_decisions(data)
            return True
    return False


def synthesize(decision_id: str) -> dict:
    """
    Synthesize positions into consensus.
    >70% weighted agreement -> consensus
    <30% -> opposite majority
    else -> contested (escalate)
    """
    data = _load_decisions()
    for d in data["decisions"]:
        if d["id"] != decision_id:
            continue
        if d["status"] != "open" or len(d["positions"]) < 2:
            return {"status": d["status"]}

        # Group by position, weight by confidence
        position_scores = {}
        total_confidence = 0
        for p in d["positions"]:
            pos = p["position"]
            conf = p["confidence"]
            position_scores[pos] = position_scores.get(pos, 0) + conf
            total_confidence += conf

        if total_confidence == 0:
            d["status"] = "contested"
            d["synthesis"] = {"consensus_position": "split", "weighted_confidence": 0}
            _save_decisions(data)
            return {"status": "contested"}

        # Find majority
        best_pos = max(position_scores, key=position_scores.get)
        best_weight = position_scores[best_pos] / total_confidence

        if best_weight > 0.7:
            consensus = best_pos
            status = "synthesized"
        elif best_weight < 0.3:
            consensus = best_pos
            status = "contested"
        else:
            consensus = "split"
            status = "contested"

        d["status"] = status
        d["synthesis"] = {
            "consensus_position": consensus,
            "weighted_confidence": round(best_weight, 3),
            "synthesis_timestamp": datetime.now(timezone.utc).isoformat(),
        }
        _save_decisions(data)
        event_bus.publish("decision.synthesized", "collective_decision", {
            "id": decision_id, "consensus": consensus, "confidence": best_weight,
        })
        return {"status": status, "consensus": consensus, "confidence": best_weight}

    return {"status": "not_found"}


def get_open_decisions() -> list:
    """Return decisions needing agent input (for boot briefing)."""
    data = _load_decisions()
    return [d for d in data["decisions"] if d["status"] == "open"]
