#!/usr/bin/env bash
set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
ROOT_DIR="$SCRIPT_DIR"

# Canonical artifact locations are sourced from the shared contract.
source "$ROOT_DIR/benchmarks/artifact_contract.sh"

MANIFEST="${1:-$ROOT_DIR/benchmarks/benchmark_manifest_core.json}"
RUN_ID="${RUN_ID:-${RUN_DATE:-$(date -u +%Y-%m-%d)}}"
CUSTOM_OUT_DIR="${2:-}"

# Normalize legacy/template placeholder values while preserving explicit run ids.
if [[ "$RUN_ID" == "YYYY-MM-DD" ]]; then
  RUN_ID="$(date -u +%Y-%m-%d)"
fi

# Keep run folder names filesystem-safe (in case callers pass paths).
RUN_ID="${RUN_ID//\//-}"

OUT_DIR="$(artifact_run_dir "$RUN_ID")"
SUMMARY_PATH="$(artifact_summary_path "$RUN_ID")"

if [[ ! -f "$MANIFEST" ]]; then
  echo "Manifest not found: $MANIFEST" >&2
  exit 1
fi

mkdir -p "$ARTIFACT_RUNS_DIR"
mkdir -p "$OUT_DIR"

python3 - "$ROOT_DIR" "$MANIFEST" "$OUT_DIR" "$SUMMARY_PATH" <<'PY'
import json
import subprocess
import sys
import time
from pathlib import Path

root_dir = Path(sys.argv[1]).resolve()
manifest_path = Path(sys.argv[2]).resolve()
out_dir = Path(sys.argv[3]).resolve()
summary_path = Path(sys.argv[4]).resolve()

with manifest_path.open("r", encoding="utf-8") as f:
    manifest = json.load(f)

benchmarks = manifest.get("benchmarks", [])
results = []
passed = 0

for idx, entry in enumerate(benchmarks, start=1):
    bench_id = str(entry.get("id", f"bench_{idx}"))
    name = str(entry.get("name", bench_id))
    command = str(entry.get("command", "")).strip()
    rel_cwd = str(entry.get("workdir", "."))
    timeout_s = float(entry.get("timeout_s", 60))
    cwd = (root_dir / rel_cwd).resolve()

    started = time.time()
    row = {
        "id": bench_id,
        "name": name,
        "status": "failed",
        "pass": 0,
        "runtime_sec": 0.0,
        "metric": {"metric_unavailable": True},
        "command": command,
        "workdir": str(cwd),
        "return_code": None,
        "stdout_log": str((out_dir / f"{bench_id}.stdout.log").resolve()),
        "stderr_log": str((out_dir / f"{bench_id}.stderr.log").resolve()),
    }

    stdout_log = Path(row["stdout_log"])
    stderr_log = Path(row["stderr_log"])

    if not command:
        row["status"] = "invalid"
        row["metric"] = {"error": "missing command"}
        row["runtime_sec"] = 0.0
        results.append(row)
        continue

    try:
        proc = subprocess.run(
            command,
            shell=True,
            cwd=str(cwd),
            capture_output=True,
            text=False,
            timeout=timeout_s,
        )
        runtime = round(time.time() - started, 4)
        stdout_bytes = proc.stdout or b""
        stderr_bytes = proc.stderr or b""

        stdout_log.write_bytes(stdout_bytes)
        stderr_log.write_bytes(stderr_bytes)

        row["return_code"] = proc.returncode
        row["runtime_sec"] = runtime
        row["status"] = "passed" if proc.returncode == 0 else "failed"
        row["pass"] = 1 if proc.returncode == 0 else 0
        row["metric"] = {
            "return_code": proc.returncode,
            "stdout_bytes": len(stdout_bytes),
            "stderr_bytes": len(stderr_bytes),
        }
        if proc.returncode == 0:
            passed += 1
    except subprocess.TimeoutExpired:
        runtime = round(time.time() - started, 4)
        row["status"] = "timed_out"
        row["runtime_sec"] = runtime
        row["metric"] = {"error": "timed_out"}
        stdout_log.write_bytes(b"")
        stderr_log.write_text("Timed out", encoding="utf-8")
    except Exception as exc:
        runtime = round(time.time() - started, 4)
        row["status"] = "error"
        row["runtime_sec"] = runtime
        row["metric"] = {"error": f"{type(exc).__name__}: {exc}"}

    results.append(row)

summary = {
    "generated_at": time.strftime("%Y-%m-%dT%H:%M:%SZ", time.gmtime()),
    "root_dir": str(root_dir),
    "manifest": str(manifest_path),
    "run_id": out_dir.name,
    "summary": {
        "total": len(results),
        "passed": passed,
        "failed": len(results) - passed,
    },
    "benchmarks": results,
}

summary_path.parent.mkdir(parents=True, exist_ok=True)
summary_path.write_text(json.dumps(summary, indent=2), encoding="utf-8")
print(f"Wrote {summary_path}")
PY

if [[ -n "$CUSTOM_OUT_DIR" && "$CUSTOM_OUT_DIR" != "$OUT_DIR" ]]; then
  mkdir -p "$CUSTOM_OUT_DIR"
  cp -a "$OUT_DIR/." "$CUSTOM_OUT_DIR/"
fi

# Normalize schema before pointer publication for downstream consumers.
NORMALIZER="$ROOT_DIR/benchmarks/normalize_benchmark_summary.py"
if [[ -f "$NORMALIZER" ]]; then
  python3 "$NORMALIZER" "$SUMMARY_PATH" --inplace
fi

# Stable pointers for trendability and deterministic discovery.
ln -sfn "$OUT_DIR" "$ARTIFACT_LATEST_LINK"
printf '%s\n' "$OUT_DIR" > "$ARTIFACT_LATEST_RUN_FILE"
cp "$SUMMARY_PATH" "$ARTIFACT_LATEST_SUMMARY"

echo "Benchmark summary: $SUMMARY_PATH"
echo "Latest run: $ARTIFACT_LATEST_LINK"
