"""AI Probability Scoring Agent — combines all agent outputs into a final
confidence score (0-100) and an estimated probability of success (0-100).

The ensemble is weighted: technical conviction and options quality dominate;
volatility and sentiment refine. Agreement between agents boosts confidence;
disagreement penalizes it. Probability is a calibrated, conservative mapping
of confidence (never promises certainty)."""
from .base import Agent, AgentResult

# Decision-layer weights (Platform Expansion v2 Module 3). News is an input
# to the ensemble — an adjustment, never an override of technicals.
WEIGHTS = {"technical": 0.35, "options": 0.20, "volatility": 0.15,
           "sentiment": 0.10, "news": 0.20}


class ProbabilityAgent(Agent):
    name = "probability"

    def run(self, context: dict) -> AgentResult:
        results: dict[str, AgentResult] = context["agent_results"]
        direction = results["technical"].direction or "CALL"

        weighted = sum(results[k].score * w for k, w in WEIGHTS.items() if k in results)

        # Agreement adjustment
        agree = disagree = 0
        for k in ("sentiment", "options", "news"):
            d = results.get(k).direction if k in results else None
            if d == direction:
                agree += 1
            elif d is not None:
                disagree += 1
        confidence = weighted + agree * 4 - disagree * 8
        confidence = round(max(0.0, min(98.0, confidence)), 1)

        # Conservative probability mapping: 50 conf → ~48%, 90 conf → ~68%
        probability = round(max(5.0, min(90.0, 23 + confidence * 0.5)), 1)

        # Learning loop: blend toward empirical win rates from closed paper
        # trades once enough history exists (see services/learning.py).
        calibration_note = None
        calibration = context.get("calibration")
        if calibration and calibration.get("active"):
            from ..services.learning import adjust_probability

            raw = probability
            probability = adjust_probability(probability, calibration)
            if probability != raw:
                calibration_note = (
                    f"Calibrated from paper-trade history: {raw}% → {probability}% "
                    f"({calibration['samples']} closed trades)"
                )

        notes = [
            f"Weighted ensemble score {weighted:.1f} "
            f"(technical {results['technical'].score}, options {results.get('options').score if 'options' in results else 'n/a'}, "
            f"volatility {results.get('volatility').score if 'volatility' in results else 'n/a'}, "
            f"sentiment {results.get('sentiment').score if 'sentiment' in results else 'n/a'})",
        ]
        if agree:
            notes.append(f"{agree} agent(s) confirm the {direction} bias")
        if disagree:
            notes.append(f"{disagree} agent(s) disagree with the {direction} bias — confidence reduced")
        if calibration_note:
            notes.append(calibration_note)

        return AgentResult(agent=self.name, score=confidence, direction=direction,
                           data={"confidence": confidence, "probability": probability},
                           notes=notes)
