"""voting_aggregator.py — Weighted multi-perspective vote aggregation for LLM direction decisions.

Usage::
    from bridge.voting_aggregator import aggregate_votes
    result = aggregate_votes(votes, weights)
"""

from __future__ import annotations
from typing import Any


def aggregate_votes(
    votes: list[dict[str, Any]],
    weights: dict[str, float] | None = None,
) -> dict[str, Any]:
    """Aggregate multi-perspective votes into a final direction with confidence.

    Args:
        votes: List of {direction, confidence, perspective, reason, ...}
        weights: {perspective: weight} — higher = more influence. None = equal.

    Returns:
        {direction, confidence, reason, _votes: list, _vote_count: int}
    """
    if not votes:
        return {"direction": "NEUTRAL", "confidence": 0.3,
                "reason": "No valid votes", "_votes": [], "_vote_count": 0}
    if len(votes) == 1:
        v = votes[0]
        return {"direction": v["direction"], "confidence": v["confidence"],
                "reason": v.get("reason", "")[:300], "_votes": votes, "_vote_count": 1}

    w = weights or {}
    valid = [v for v in votes if v.get("direction") in ("LONG", "SHORT", "NEUTRAL")]

    # Weighted direction score
    scores = {"LONG": 0.0, "SHORT": 0.0, "NEUTRAL": 0.0}
    total_weight = 0.0
    conf_sum = 0.0

    for v in valid:
        perspective = str(v.get("perspective", "") or "")
        wt = w.get(perspective, 1.0) if perspective else 1.0
        dir_ = v["direction"]
        conf = float(v.get("confidence", 0.5))
        scores[dir_] += wt * conf
        total_weight += wt
        conf_sum += conf * wt

    if total_weight <= 0:
        direction = "NEUTRAL"
        confidence = 0.3
    else:
        sorted_dirs = sorted(scores.items(), key=lambda x: x[1], reverse=True)
        top_dir, top_score = sorted_dirs[0]
        second_score = sorted_dirs[1][1]

        if top_score > second_score * 1.15:
            direction = top_dir
        elif top_score == second_score:
            direction = top_dir
        else:
            direction = top_dir

        confidence = round(top_score / total_weight, 4)
        confidence = max(0.3, min(0.95, confidence))

    # Build reason from all perspectives
    reasons = []
    for v in valid:
        r = str(v.get("reason", "") or "")[:80]
        p = str(v.get("perspective", "?") or "?")
        c = float(v.get("confidence", 0))
        reasons.append(f"[{p}] conf={c:.2f}: {r}")
    final_reason = " | ".join(reasons)

    return {
        "direction": direction,
        "confidence": confidence,
        "reason": final_reason[:500],
        "_votes": valid,
        "_vote_count": len(valid),
    }
