#!/usr/bin/env python3
import argparse
import csv
import sys
from pathlib import Path

HEADERS = [
    "task_id", "task_title", "execution_mode", "complexity", "intake_at",
    "execution_start_at", "review_gate_at", "observation_end_at",
    "preparation_minutes", "cycle_minutes", "rework_rounds",
    "premerge_defects", "postmerge_defects", "defect_frontload_rate",
    "input_tokens", "output_tokens", "cache_tokens", "total_tokens",
    "token_source", "memory_searches", "memory_hit_searches",
    "memory_applied", "memory_useful", "memory_hit_rate", "status",
    "evidence_path", "measurement_notes",
]

NONNEGATIVE = [
    "preparation_minutes", "cycle_minutes", "rework_rounds",
    "premerge_defects", "postmerge_defects", "input_tokens",
    "output_tokens", "cache_tokens", "total_tokens", "memory_searches",
    "memory_hit_searches", "memory_applied", "memory_useful",
]


def is_number(value: str) -> bool:
    try:
        return float(value) >= 0
    except (TypeError, ValueError):
        return False


def validate(path: Path, phase: str) -> list[str]:
    errors: list[str] = []
    with path.open(newline="", encoding="utf-8-sig") as handle:
        reader = csv.DictReader(handle)
        if reader.fieldnames != HEADERS:
            return ["CSV表头不符合task-metrics标准"]
        rows = list(reader)
    if len(rows) != 1:
        return ["每个task-metrics.csv必须且只能有1条任务汇总记录"]
    row = rows[0]
    for field in ["task_id", "task_title", "execution_mode", "complexity", "intake_at", "status", "evidence_path", "measurement_notes"]:
        if not row[field].strip() or row[field] == "pending":
            errors.append(f"{field}未填写")
    if row["execution_mode"] not in {"ruflo", "standard_codex"}:
        errors.append("execution_mode只能是ruflo或standard_codex")
    if row["status"] not in {"baseline", "in_progress", "review_ready", "complete", "observed"}:
        errors.append("status不在允许范围")
    if phase in {"review", "observed"}:
        for field in ["execution_start_at", "review_gate_at"]:
            if not row[field].strip() or row[field] == "pending":
                errors.append(f"Review Gate前必须填写{field}")
        for field in ["preparation_minutes", "cycle_minutes", "rework_rounds", "premerge_defects", "memory_searches", "memory_hit_searches", "memory_applied", "memory_useful"]:
            if not is_number(row[field]):
                errors.append(f"Review Gate前{field}必须为非负数字")
        if not row["token_source"].strip() or row["token_source"] == "pending":
            errors.append("必须填写token_source，无法获取时写unavailable及原因")
        token_values = [row[f] for f in ["input_tokens", "output_tokens", "cache_tokens", "total_tokens"]]
        if not all(is_number(v) for v in token_values) and "unavailable" not in row["token_source"].lower():
            errors.append("Token非数字时token_source必须明确unavailable")
        searches = float(row["memory_searches"] or 0)
        hit_searches = float(row["memory_hit_searches"] or 0)
        if hit_searches > searches:
            errors.append("memory_hit_searches不能大于memory_searches")
        if searches == 0 and row["memory_hit_rate"].lower() not in {"n/a", "na"}:
            errors.append("没有memory搜索时memory_hit_rate必须为n/a")
    if phase == "observed":
        for field in ["observation_end_at", "postmerge_defects", "defect_frontload_rate"]:
            if not row[field].strip() or row[field] == "pending":
                errors.append(f"观察期结束必须填写{field}")
        if row["status"] != "observed":
            errors.append("--phase observed时status必须为observed")
    return errors


def main() -> int:
    parser = argparse.ArgumentParser()
    parser.add_argument("csv_path", type=Path)
    parser.add_argument("--phase", choices=["start", "review", "observed"], default="start")
    args = parser.parse_args()
    if not args.csv_path.is_file():
        print(f"metrics file not found: {args.csv_path}", file=sys.stderr)
        return 2
    errors = validate(args.csv_path, args.phase)
    if errors:
        print("Ruflo task metrics validation failed:", file=sys.stderr)
        for error in errors:
            print(f"- {error}", file=sys.stderr)
        return 1
    print(f"Ruflo task metrics validation passed: phase={args.phase}")
    return 0


if __name__ == "__main__":
    raise SystemExit(main())
