#!/usr/bin/env python3
# Copyright (c) 2026 PULSE Contributors. Proprietary. All rights reserved.
# See LICENSE file for details.
"""
Benchmark Tracker: Lifecycle management with exponential decay (V43.12)

Manages benchmarks from creation through achievement/failure to archival.
Decay formula: salience(t) = e^(-t/100). Archive when salience < 0.1 (~230 days).

Usage:
    python .claude/automation/benchmark_tracker.py --list
    python .claude/automation/benchmark_tracker.py --create "description" --criteria "success criteria"
    python .claude/automation/benchmark_tracker.py --achieve BM-001
    python .claude/automation/benchmark_tracker.py --fail BM-001 --reason "why"
    python .claude/automation/benchmark_tracker.py --decay
    python .claude/automation/benchmark_tracker.py --archive
Dependencies: Python stdlib only (Law 4)
"""

import json
import math
import sys
from datetime import datetime, timezone
from pathlib import Path

# Add Utilities to path for brain_utils

from pulse.core.brain_utils import (load_config, load_json_dict, save_json,
                         BENCHMARKS_FILE)


def load_benchmarks() -> dict:
    """Load benchmarks file."""
    data = load_json_dict(BENCHMARKS_FILE)
    if not data:
        data = {
            "version": "1.0", "schema": "V43.12",
            "last_updated": datetime.now(timezone.utc).isoformat(),
            "counters": {"total": 0, "active": 0, "achieved": 0,
                         "failed": 0, "archived": 0},
            "benchmarks": [], "archived": []
        }
    return data


def save_benchmarks(data: dict):
    """Save benchmarks with updated timestamp."""
    data["last_updated"] = datetime.now(timezone.utc).isoformat()
    save_json(BENCHMARKS_FILE, data)


def compute_salience(created_date: str) -> float:
    """Compute salience: e^(-days/100)."""
    config = load_config()
    decay_const = config.get("decay", {}).get("benchmark_decay_constant", 100)
    try:
        ts = str(created_date).replace("Z", "+00:00")
        if "T" in ts:
            d = datetime.fromisoformat(ts)
        else:
            d = datetime.fromisoformat(ts).replace(tzinfo=timezone.utc)
        days = max(0, (datetime.now(timezone.utc) - d).days)
    except (ValueError, TypeError):
        days = 0
    return round(math.exp(-days / decay_const), 4)


def next_id(data: dict) -> str:
    """Generate next benchmark ID."""
    total = data.get("counters", {}).get("total", 0) + 1
    return f"BM-{total:03d}"


def update_counters(data: dict):
    """Recompute counters from current state."""
    benchmarks = data.get("benchmarks", [])
    data["counters"] = {
        "total": len(benchmarks) + len(data.get("archived", [])),
        "active": sum(1 for b in benchmarks if b.get("status") == "active"),
        "achieved": sum(1 for b in benchmarks if b.get("status") == "achieved"),
        "failed": sum(1 for b in benchmarks if b.get("status") == "failed"),
        "archived": len(data.get("archived", []))
    }


# Lifecycle operations extracted to benchmark_tracker_ops.py for Law 7 compliance.
# CLI entry: benchmark_tracker_main.py