#!/usr/bin/env python3
"""Shared utilities for skill-builder scripts."""

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


def load_json(path):
    """Load and parse a JSON file. Exit with error if not found or invalid."""
    path = Path(path)
    if not path.exists():
        print(f"Error: {path} not found", file=sys.stderr)
        sys.exit(1)
    try:
        with open(path, "r") as f:
            return json.load(f)
    except json.JSONDecodeError as e:
        print(f"Error: Invalid JSON in {path}: {e}", file=sys.stderr)
        sys.exit(1)


def save_json(path, data, indent=2):
    """Save data as formatted JSON."""
    path = Path(path)
    path.parent.mkdir(parents=True, exist_ok=True)
    with open(path, "w") as f:
        json.dump(data, f, indent=indent)
    print(f"Saved: {path}")


def find_workspace(skill_dir):
    """Find or create the workspace directory for a skill."""
    skill_dir = Path(skill_dir)
    slug = skill_dir.name
    workspace = skill_dir.parent.parent.parent / f"{slug}-workspace"
    return workspace


def find_latest_iteration(workspace):
    """Find the highest iteration number in a workspace."""
    workspace = Path(workspace)
    if not workspace.exists():
        return 0
    iterations = [
        int(d.name.split("-")[1])
        for d in workspace.iterdir()
        if d.is_dir() and d.name.startswith("iteration-")
    ]
    return max(iterations) if iterations else 0


def next_iteration_dir(workspace):
    """Get the path for the next iteration directory."""
    workspace = Path(workspace)
    n = find_latest_iteration(workspace) + 1
    return workspace / f"iteration-{n}"


def collect_grading_files(iteration_dir):
    """Collect all grading.json files from an iteration directory."""
    iteration_dir = Path(iteration_dir)
    results = []
    for eval_dir in sorted(iteration_dir.iterdir()):
        if not eval_dir.is_dir() or not eval_dir.name.startswith("eval-"):
            continue
        for config in ["with_skill", "without_skill"]:
            grading_path = eval_dir / config / "grading.json"
            if grading_path.exists():
                results.append(load_json(grading_path))
    return results


def collect_timing_files(iteration_dir):
    """Collect all timing.json files from an iteration directory."""
    iteration_dir = Path(iteration_dir)
    results = []
    for eval_dir in sorted(iteration_dir.iterdir()):
        if not eval_dir.is_dir() or not eval_dir.name.startswith("eval-"):
            continue
        for config in ["with_skill", "without_skill"]:
            timing_path = eval_dir / config / "timing.json"
            if timing_path.exists():
                results.append(load_json(timing_path))
    return results


def now_iso():
    """Return current time as ISO 8601 string."""
    return datetime.now(timezone.utc).isoformat()


def mean(values):
    """Calculate mean of a list of numbers."""
    if not values:
        return 0
    return sum(values) / len(values)


def stddev(values):
    """Calculate population standard deviation."""
    if len(values) < 2:
        return 0
    m = mean(values)
    variance = sum((x - m) ** 2 for x in values) / len(values)
    return variance ** 0.5


def format_percent(value):
    """Format a float as a percentage string."""
    return f"{value * 100:.1f}%"


def format_duration(ms):
    """Format milliseconds as a human-readable duration."""
    if ms < 1000:
        return f"{ms}ms"
    elif ms < 60000:
        return f"{ms / 1000:.1f}s"
    else:
        return f"{ms / 60000:.1f}m"
