"""'Die and come back stronger': detect failure, run an autopsy on the trade journal, and spawn the next version.

Evolution is at the PARAMETER / RULE level, and every child must be backtested before it trades.
The AI never rewrites live trading code on its own: that is how accounts get blown up.
"""
import copy
from .metrics import summarize


def check_failure(cfg, trades, drawdown_pct):
    f = cfg["failure"]
    if drawdown_pct >= f["max_drawdown_pct"]:
        return f"drawdown {drawdown_pct:.1f}% reached the limit of {f['max_drawdown_pct']}%"
    s = summarize(trades)
    if s["trades"] >= f["min_trades_before_profit_check"] and s["profit_factor"] < f["min_profit_factor"]:
        return f"profit factor {s['profit_factor']} after {s['trades']} trades (needs {f['min_profit_factor']}+)"
    return None


def _wr(ts):
    return sum(1 for t in ts if t["pnl"] > 0) / len(ts) if ts else None


def autopsy(trades, params):
    """Returns (findings, new_params). Always changes at least one thing."""
    cl = [t for t in trades if t["status"] == "closed"]
    new, notes = copy.deepcopy(params), []
    if len(cl) < 10:
        notes.append("Very few trades, so this autopsy is weak evidence. Applying a conservative tightening.")

    lo = [t for t in cl if t["confidence"] < 100]
    hi = [t for t in cl if t["confidence"] >= 100]
    if params["min_confidence"] < 100 and len(lo) >= 5 and _wr(lo) < 0.40 and (not hi or _wr(hi) > _wr(lo) + 0.10):
        new["min_confidence"] = 100
        notes.append(f"Trades below 100% confidence won only {_wr(lo):.0%}. Now requiring all 5 factors.")

    weak = [t for t in cl if t["factors"].get("adx", 99) < 20]
    if len(weak) >= 5 and _wr(weak) < 0.40:
        target = 25 if params.get("min_adx", 0) >= 20 else 20
        if target > params.get("min_adx", 0):
            new["min_adx"] = target
            notes.append(f"Trades in weak-trend markets (ADX<20) won only {_wr(weak):.0%}. Now requiring ADX>={target}.")

    losses = [t for t in cl if t["pnl"] <= 0]
    fast = [t for t in losses if t["exit_reason"] == "SL" and (t["bars_held"] or 0) <= 3]
    if losses and len(fast) / len(losses) >= 0.5 and params["atr_stop_mult"] < 4:
        new["atr_stop_mult"] = round(params["atr_stop_mult"] + 0.5, 2)
        notes.append(f"{len(fast)}/{len(losses)} losses were stopped out within 3 candles. Widening the stop to {new['atr_stop_mult']} x ATR.")

    for side, other in (("BUY", "SELL"), ("SELL", "BUY")):
        a = [t for t in cl if t["side"] == side]
        b = [t for t in cl if t["side"] == other]
        if len(a) >= 8 and _wr(a) < 0.35 and b and _wr(b) >= 0.50 and side in params["sides"]:
            new["sides"] = [s for s in params["sides"] if s != side]
            notes.append(f"{side} trades won only {_wr(a):.0%} vs {_wr(b):.0%} for {other}. Switching {side} off.")

    if not params.get("mtf_confirm", True):
        new["mtf_confirm"] = True
        notes.append("Turning higher-timeframe confirmation back on.")

    if new == params:
        new["supertrend_mult"] = round(params["supertrend_mult"] + 0.5, 2)
        new["min_confidence"] = max(params["min_confidence"], 80)
        notes.append("No clear pattern found. Making the trend filter less jumpy (Supertrend multiplier +0.5).")
    return notes, new
