"""
Trajectory mining for text evolution.

Filters decrypted trajectory records for skill-related signals
(high tool count, low reward, skill_manage calls) and optionally
seeds eval task stubs from failure patterns.

v1 is intentionally minimal: most value comes from hand-authored
eval tasks. Mining provides signal for *which* skill to optimize.
"""
from __future__ import annotations

import os
from typing import Any


def _log(msg: str, level: str = "WARNING") -> None:
    try:
        from tools._logging import _debug_log
        _debug_log(f"[evolution/skill_mining] {msg}", level)
    except Exception:
        pass


def mine_optimization_targets(
    since_iso: str | None = None,
    min_tool_count: int = 5,
    max_results: int = 10,
) -> list[dict]:
    """Return skill names that are candidates for optimization.

    Heuristics (v1):
    - Trajectories with skill_manage patch/create calls → skill was actively modified
    - High tool-call count → complex workflow, possibly improvable
    - Low heuristic reward → agent struggled

    Returns list of {"skill_name": str, "reason": str, "score": float}.
    """
    try:
        from evolution.trajectory_logger import load_trajectory_records
        from evolution.rewards import compute_reward
    except ImportError as exc:
        _log(f"Cannot import trajectory/rewards: {exc}", "ERROR")
        return []

    records = load_trajectory_records(since_iso=since_iso)
    if not records:
        return []

    skill_signals: dict[str, list[float]] = {}

    for rec in records:
        messages = rec.get("messages", [])
        tool_calls = rec.get("tool_calls", [])
        reward = compute_reward(rec)

        mentioned_skills: set[str] = set()
        tool_count = len(tool_calls)

        for tc in tool_calls:
            name = tc.get("name", "") if isinstance(tc, dict) else ""
            args = tc.get("arguments", {}) if isinstance(tc, dict) else {}
            if isinstance(args, str):
                try:
                    import json
                    args = json.loads(args)
                except Exception:
                    args = {}

            if name == "skill_manage" and isinstance(args, dict):
                sn = args.get("skill_name", "")
                if sn:
                    mentioned_skills.add(sn)

            if name == "skill_view" and isinstance(args, dict):
                sn = args.get("skill_name", "")
                if sn:
                    mentioned_skills.add(sn)

        # Score: low reward + high tool count = good optimization candidate
        if mentioned_skills and (reward < 0.5 or tool_count >= min_tool_count):
            optimization_score = (1.0 - reward) * 0.6 + min(tool_count / 20.0, 1.0) * 0.4
            for sn in mentioned_skills:
                skill_signals.setdefault(sn, []).append(optimization_score)

    # Aggregate: mean signal per skill
    results = []
    for skill_name, scores in skill_signals.items():
        avg = sum(scores) / len(scores)
        reasons = []
        if avg > 0.5:
            reasons.append("low reward trajectories")
        if len(scores) > 1:
            reasons.append(f"appeared in {len(scores)} trajectories")
        results.append({
            "skill_name": skill_name,
            "reason": "; ".join(reasons) if reasons else "skill activity detected",
            "score": round(avg, 3),
        })

    results.sort(key=lambda x: x["score"], reverse=True)
    return results[:max_results]

