"""
training_candidate_value — evaluate whether current training candidate
parameters are worth manual review by a human operator.

Consumed by /api/training_status and /api/governance_brief to show
the candidate value score in the UI.
"""

import time
from typing import Any, Dict


def evaluate_training_candidate_value(
    *,
    quality_snapshot: Dict[str, Any] = None,
    bootstrap_mode: bool = False,
) -> Dict[str, Any]:
    """Evaluate the value of the current training candidate parameters.

    Args:
        quality_snapshot: Output from training_quality_snapshot.
            Expected keys: ready_for_training, closure_coverage_pct,
            usable_trade_count, critical_anomalies, natural_closed_ratio_pct.
        bootstrap_mode: If True, relax requirements for systems with zero
            completed trades (avoids deadlock where promotion requires trades
            but trades require promotion).

    Returns:
        Dict with:
            - ready_for_manual_review: bool   (should UI show review button)
            - candidate_score: float          (0.0–1.0, higher = more valuable)
            - review_priority: str            (low / medium / high)
            - reasons: list[str]              (why this score)
            - generated_at: str               (ISO timestamp)
    """
    qs = quality_snapshot if isinstance(quality_snapshot, dict) else {}

    ready = bool(qs.get("ready_for_training", False))
    coverage = float(qs.get("closure_coverage_pct", 0.0))
    usable = int(qs.get("usable_trade_count", 0))
    anomalies = int(qs.get("critical_anomalies", 0))
    natural_ratio = float(qs.get("natural_closed_ratio_pct", 0.0))

    reasons = []
    score = 0.0

    if bootstrap_mode:
        reasons.append("Bootstrap mode: trade-history requirements waived")
        ready = True

    # Factor 1: readiness (0–30 points)
    if ready:
        score += 30
        reasons.append("Training quality gate passed")
    else:
        reasons.append("Training quality gate not ready")

    # Factor 2: trade count (0–25 points)
    if bootstrap_mode:
        score += 18
        reasons.append("Bootstrap: trade count requirement waived")
    elif usable >= 50:
        score += 25
        reasons.append(f"Strong trade sample ({usable} closed trades)")
    elif usable >= 20:
        score += 18
        reasons.append(f"Adequate trade sample ({usable} closed trades)")
    elif usable >= 10:
        score += 10
        reasons.append(f"Minimal trade sample ({usable} closed trades)")
    else:
        reasons.append(f"Insufficient trades ({usable} < 10)")

    # Factor 3: closure coverage (0–20 points)
    if bootstrap_mode:
        score += 14
        reasons.append("Bootstrap: closure coverage requirement waived")
    elif coverage >= 60:
        score += 20
        reasons.append(f"High closure coverage ({coverage}%)")
    elif coverage >= 40:
        score += 14
        reasons.append(f"Moderate closure coverage ({coverage}%)")
    elif coverage >= 20:
        score += 8
        reasons.append(f"Low closure coverage ({coverage}%)")
    else:
        reasons.append(f"Very low closure coverage ({coverage}%)")

    # Factor 4: data quality (0–15 points)
    if anomalies == 0:
        score += 15
        reasons.append("No critical anomalies detected")
    elif anomalies == 1:
        score += 7
        reasons.append(f"{anomalies} critical anomaly — review advised")
    else:
        reasons.append(f"{anomalies} critical anomalies — data quality poor")

    # Factor 5: natural-closed ratio (0–10 points)
    if bootstrap_mode:
        score += 5
        reasons.append("Bootstrap: natural-closed ratio requirement waived")
    elif natural_ratio >= 70:
        score += 10
        reasons.append(f"High natural-closed ratio ({natural_ratio}%)")
    elif natural_ratio >= 40:
        score += 5
        reasons.append(f"Adequate natural-closed ratio ({natural_ratio}%)")
    else:
        reasons.append(f"Low natural-closed ratio ({natural_ratio}%) — many recovered trades")

    # Normalize to 0–1
    score_normalized = round(score / 100.0, 2)

    # Priority
    if score_normalized >= 0.7:
        priority = "high"
    elif score_normalized >= 0.4:
        priority = "medium"
    else:
        priority = "low"

    ready_for_review = score_normalized >= 0.3

    return {
        "ready_for_manual_review": ready_for_review,
        "candidate_score": score_normalized,
        "review_priority": priority,
        "reasons": reasons,
        "generated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
        "score_breakdown": {
            "readiness": 30 if ready else 0,
            "trade_count": min(25, max(0, (usable / 50) * 25)),
            "closure_coverage": min(20, max(0, (coverage / 60) * 20)),
            "data_quality": min(15, max(0, 15 - anomalies * 7)),
            "natural_ratio": min(10, max(0, (natural_ratio / 70) * 10)),
        },
    }
