"""factor_decay.py — Detect profit factor degradation over time.

Phase 2: Compares factor scores across rolling 30-day windows.
Flags factors whose importance has declined >15% (warning) or >30% (critical).

Usage::

    from src.learning.factor_decay import detect_decay
    decay_report = detect_decay(current_factors, previous_factors)
"""

from __future__ import annotations

import json
import time as _time
from pathlib import Path
from typing import Any

import config_manager


def _decay_state_path() -> Path:
    d = config_manager.get_data_dir() / "learning"
    d.mkdir(parents=True, exist_ok=True)
    return d / "factor_decay_state.json"


def _load_previous() -> dict[str, Any]:
    sp = _decay_state_path()
    if sp.exists():
        try:
            return json.loads(sp.read_text(encoding="utf-8"))
        except Exception:
            pass
    return {}


def _save_current(factors: list[dict[str, Any]]) -> None:
    try:
        snapshot = {
            "ts": _time.strftime("%Y-%m-%dT%H:%M:%S", _time.gmtime()),
            "factors": {f["feature"]: f["importance_score"] for f in factors},
        }
        _decay_state_path().write_text(json.dumps(snapshot, indent=2), encoding="utf-8")
    except Exception:
        pass


def detect_decay(current_factors: list[dict[str, Any]]) -> dict[str, Any]:
    """Compare current factor scores against previous snapshot to detect decay.

    Returns:
        {"decaying": [{feature, prev_score, curr_score, change_pct, level}],
         "improving": [...],
         "report_md": str}
    """
    prev = _load_previous()
    prev_factors = prev.get("factors", {}) if isinstance(prev, dict) else {}
    prev_ts = prev.get("ts", "never")

    decaying: list[dict[str, Any]] = []
    improving: list[dict[str, Any]] = []

    for f in current_factors:
        feature = f["feature"]
        curr = f["importance_score"]
        prev_score = prev_factors.get(feature, curr)

        if prev_score > 0 and curr > 0:
            change_pct = round((curr - prev_score) / prev_score * 100, 1)
        else:
            change_pct = 0.0

        if change_pct <= -30:
            level = "critical"
        elif change_pct <= -15:
            level = "warning"
        elif change_pct >= 30:
            level = "improving"
        else:
            level = "stable"

        f["trend"] = level
        f["change_pct"] = change_pct

        if level in ("critical", "warning"):
            decaying.append({
                "feature": feature, "prev_score": prev_score, "curr_score": curr,
                "change_pct": change_pct, "level": level,
            })
        elif level == "improving":
            improving.append({
                "feature": feature, "prev_score": prev_score, "curr_score": curr,
                "change_pct": change_pct,
            })

    _save_current(current_factors)

    # Generate markdown report
    lines = [
        "---",
        f"updated: {_time.strftime('%Y-%m-%dT%H:%M:%S')}",
        f"previous_snapshot: {prev_ts}",
        "tags: [factors, decay]",
        "---",
        "",
        "# Factor Decay Report",
        "",
    ]

    if decaying:
        lines.append("## Decaying Factors")
        lines.append("")
        for d in decaying:
            icon = "🔴" if d["level"] == "critical" else "🟡"
            lines.append(
                f"- {icon} **{d['feature']}**: {d['prev_score']:.1f} → "
                f"{d['curr_score']:.1f} ({d['change_pct']:+.1f}%)"
            )
        lines.append("")

    if improving:
        lines.append("## Improving Factors")
        lines.append("")
        for d in improving:
            lines.append(
                f"- 🟢 **{d['feature']}**: {d['prev_score']:.1f} → "
                f"{d['curr_score']:.1f} ({d['change_pct']:+.1f}%)"
            )
        lines.append("")

    if not decaying and not improving:
        lines.append("No significant changes detected since last snapshot.")
        lines.append("")

    report_md = "\n".join(lines)

    # Save report to knowledge base
    try:
        from src.learning.knowledge_writer import _ensure_subdir
        d = _ensure_subdir("factors")
        (d / "DECAY.md").write_text(report_md, encoding="utf-8")
    except Exception:
        pass

    return {
        "decaying": decaying,
        "improving": improving,
        "report_md": report_md,
    }
