"""AI Chief Investment Officer briefing (docs/DASHBOARD_SPEC.md sections 1, 3, 15).

Composes the morning executive summary from existing, evidence-based services
— deterministic and auditable (no LLM required, so the briefing can never
hallucinate a number it can't source).

Includes the Trade Readiness Score: a 0-100 composite per approved signal so
the trader sees ranked opportunities instead of raw lists.
"""
from datetime import datetime, timedelta

from sqlalchemy.orm import Session

from .. import models
from ..agents.regime import REGIME_SYMBOL, RegimeAgent
from ..config import settings
from .market_data import get_provider
from .reporting import portfolio_summary

READINESS_WEIGHTS = {
    "setup": 0.25,        # technical/swing setup quality
    "confidence": 0.25,   # AI ensemble confidence
    "probability": 0.20,  # calibrated win probability
    "risk_reward": 0.10,
    "volatility": 0.10,
    "options": 0.10,      # chain quality (neutral 60 for stock swings)
}


def _pnl_since(db: Session, since: datetime) -> float:
    rows = (
        db.query(models.PaperTrade)
        .filter(models.PaperTrade.status == "closed", models.PaperTrade.closed_at >= since)
        .all()
    )
    return round(sum(t.pnl for t in rows), 2)


def _recent_win_rate(db: Session, days: int = 30) -> float | None:
    since = datetime.utcnow() - timedelta(days=days)
    rows = (
        db.query(models.PaperTrade)
        .filter(models.PaperTrade.status == "closed", models.PaperTrade.closed_at >= since)
        .all()
    )
    if not rows:
        return None
    return round(sum(1 for t in rows if t.pnl > 0) / len(rows) * 100, 1)


def trading_mode(regime: str, high_vol: bool, risk_utilization: float,
                 win_rate_30d: float | None) -> tuple[str, list[str]]:
    """Recommended trading mode with explicit reasoning."""
    reasons = []
    defensive = False
    if regime in ("chop", "bear", "unknown"):
        defensive = True
        reasons.append(f"market regime is {regime.upper()}")
    if high_vol:
        defensive = True
        reasons.append("index volatility is elevated")
    if risk_utilization > 70:
        defensive = True
        reasons.append(f"risk budget {risk_utilization:.0f}% used")
    if win_rate_30d is not None and win_rate_30d < 45:
        defensive = True
        reasons.append(f"30-day win rate {win_rate_30d}% below par")

    if defensive:
        return "Defensive", reasons

    aggressive = (regime == "bull" and not high_vol and risk_utilization < 40
                  and (win_rate_30d is None or win_rate_30d >= 60))
    if aggressive:
        reasons.append("bull regime, normal volatility, risk budget available")
        if win_rate_30d is not None:
            reasons.append(f"30-day win rate {win_rate_30d}%")
        return "Aggressive", reasons

    reasons.append("conditions are acceptable but not uniformly favorable")
    return "Moderate", reasons


def readiness_score(signal: models.Signal, regime: str) -> dict:
    """Trade Readiness Score 0-100 with a transparent breakdown."""
    scores = signal.scores or {}
    setup = scores.get("swing") or scores.get("technical") or 50.0
    parts = {
        "setup": float(setup),
        "confidence": float(signal.confidence),
        "probability": float(signal.probability),
        "risk_reward": min(100.0, signal.risk_reward / 3.0 * 100),
        "volatility": float(scores.get("volatility", 60.0)),
        "options": float(scores.get("options", 60.0)),
    }
    base = sum(parts[k] * w for k, w in READINESS_WEIGHTS.items())

    bullish = signal.direction in ("CALL", "BUY")
    aligned = (regime == "bull" and bullish) or (regime == "bear" and not bullish)
    adjustment = 5.0 if aligned else -5.0 if regime == "chop" else 0.0
    total = round(max(0.0, min(100.0, base + adjustment)), 1)

    return {"total": total, "breakdown": {k: round(v, 1) for k, v in parts.items()},
            "regime_alignment": round(adjustment, 1)}


def build_briefing(db: Session) -> dict:
    provider = get_provider()
    regime_res = RegimeAgent().run({"history": provider.get_history(REGIME_SYMBOL, 90)})
    regime = regime_res.data["regime"]
    high_vol = regime_res.data["high_volatility"]

    portfolio = portfolio_summary(db)
    now = datetime.utcnow()
    day_start = datetime(now.year, now.month, now.day)
    pnl_today = _pnl_since(db, day_start)
    pnl_week = _pnl_since(db, now - timedelta(days=7))
    pnl_month = _pnl_since(db, now - timedelta(days=30))
    win_rate_30d = _recent_win_rate(db, 30)

    mode, mode_reasons = trading_mode(regime, high_vol,
                                      portfolio["risk_utilization_pct"], win_rate_30d)

    # Today's approved signals ranked by readiness
    approved = (
        db.query(models.Signal)
        .filter(models.Signal.status == "approved", models.Signal.created_at >= day_start)
        .all()
    )
    ranked = []
    for s in approved:
        r = readiness_score(s, regime)
        ranked.append({
            "id": s.id, "symbol": s.symbol, "direction": s.direction,
            "signal_type": s.signal_type or "options",
            "entry": s.entry, "stop_loss": s.stop_loss, "target1": s.target1,
            "probability": s.probability, "confidence": s.confidence,
            "readiness": r["total"], "readiness_breakdown": r["breakdown"],
            "regime_alignment": r["regime_alignment"],
        })
    ranked.sort(key=lambda x: x["readiness"], reverse=True)
    top = ranked[:5]

    # Narrative — every number sourced from the structures above
    lines = [
        f"Market regime: {regime.upper()}"
        + (" with ELEVATED volatility — position sizing is halved." if high_vol else "."),
        f"Recommended mode: {mode} ({'; '.join(mode_reasons)}).",
        f"Account ${portfolio['account_equity']:,.0f} — today ${pnl_today:+,.0f}, "
        f"7d ${pnl_week:+,.0f}, 30d ${pnl_month:+,.0f}"
        + (f", 30-day win rate {win_rate_30d}%." if win_rate_30d is not None
           else " (no closed trades in 30d yet)."),
        f"Risk budget: {portfolio['risk_utilization_pct']:.0f}% used "
        f"(${portfolio['open_risk_usd']:,.0f} of ${portfolio['max_daily_risk_usd']:,.0f}).",
    ]
    if top:
        best = top[0]
        lines.append(
            f"Highest-readiness setup: {best['symbol']} {best['direction']} "
            f"(readiness {best['readiness']}, est. probability {best['probability']:.0f}%). "
            f"{len([r for r in ranked if r['readiness'] >= 70])} of {len(ranked)} "
            "of today's approved signals score 70+."
        )
    else:
        lines.append("No approved signals yet today — run a scan or wait for the next auto-scan.")
    lines.append("Paper trading research only — not financial advice.")

    return {
        "generated_at": now.isoformat(),
        "regime": regime,
        "high_volatility": high_vol,
        "trading_mode": mode,
        "mode_reasons": mode_reasons,
        "portfolio": {
            **portfolio,
            "pnl_today": pnl_today,
            "pnl_week": pnl_week,
            "pnl_month": pnl_month,
            "win_rate_30d": win_rate_30d,
        },
        "top_opportunities": top,
        "signals_today": len(ranked),
        "briefing": lines,
    }
