#!/usr/bin/env python3
"""
Day9: Plan-Execute-Validate 루프 데모
- HF Agents Course/smolagents의 planning 개념을 실무형으로 축약한 재현용 스크립트
- 모델 호출 없이도 selfcheck/eval이 가능하도록 규칙 기반으로 구성
"""

from __future__ import annotations
import argparse
import json
from dataclasses import dataclass
from pathlib import Path
from typing import Dict, List, Any


@dataclass
class TaskInput:
    request: str
    risk_level: str  # low|medium|high
    has_pii: int     # 0|1
    deadline_hours: int


def make_plan(t: TaskInput) -> List[str]:
    steps = [
        "요청 의도 요약",
        "리스크/개인정보 확인",
        "초안 작성",
        "검증 체크리스트 적용",
    ]
    if t.risk_level == "high" or t.has_pii == 1:
        steps.insert(2, "민감정보 마스킹")
    if t.deadline_hours <= 4:
        steps.append("긴급 라벨 부여")
    steps.append("최종 결과 포맷팅")
    return steps


def validate_output(t: TaskInput, plan: List[str], draft: str) -> Dict[str, Any]:
    checks = {
        "has_summary": "요약" in draft,
        "has_checklist": "체크리스트" in draft,
        "pii_masked": (t.has_pii == 0) or ("[REDACTED]" in draft),
        "high_risk_gate": (t.risk_level != "high") or ("검토자 승인 필요" in draft),
    }
    ok = all(checks.values())
    return {"ok": ok, "checks": checks}


def execute_task(t: TaskInput) -> Dict[str, Any]:
    plan = make_plan(t)

    summary = f"요약: 요청='{t.request[:40]}'"
    checklist = "체크리스트: 범위/사실/리스크/기한 확인"

    pii_line = ""
    if t.has_pii == 1:
        pii_line = "민감정보: [REDACTED] 처리 완료"

    gate_line = ""
    if t.risk_level == "high":
        gate_line = "승인: 검토자 승인 필요"

    urgency = ""
    if t.deadline_hours <= 4:
        urgency = "우선순위: 긴급"

    draft_lines = [summary, checklist, pii_line, gate_line, urgency]
    draft = "\n".join([x for x in draft_lines if x])

    validation = validate_output(t, plan, draft)

    return {
        "plan": plan,
        "draft": draft,
        "validation": validation,
        "final": {
            "status": "PASS" if validation["ok"] else "REVIEW",
            "request": t.request,
            "risk_level": t.risk_level,
            "deadline_hours": t.deadline_hours,
        },
    }


def run_selfcheck() -> Dict[str, Any]:
    t = TaskInput(
        request="고객 CS 요약 보고서 작성",
        risk_level="high",
        has_pii=1,
        deadline_hours=2,
    )
    result = execute_task(t)
    ok = (
        "민감정보 마스킹" in result["plan"]
        and result["validation"]["ok"] is True
        and result["final"]["status"] == "PASS"
    )
    return {"selfcheck_ok": ok, "result": result}


def run_eval(path: Path) -> Dict[str, Any]:
    data = json.loads(path.read_text(encoding="utf-8"))
    rows = data.get("tasks", [])
    passed = 0
    outputs = []

    for row in rows:
        t = TaskInput(**row["input"])
        res = execute_task(t)
        expect = row.get("expect", {})

        conds = []
        if "status" in expect:
            conds.append(res["final"]["status"] == expect["status"])
        if "needs_masking" in expect:
            conds.append(("[REDACTED]" in res["draft"]) == expect["needs_masking"])

        row_pass = all(conds) if conds else res["validation"]["ok"]
        passed += 1 if row_pass else 0

        outputs.append({
            "id": row.get("id"),
            "pass": row_pass,
            "final": res["final"],
            "checks": res["validation"]["checks"],
        })

    total = len(rows)
    score = (passed / total) if total else 0.0
    return {"pass": score >= 0.66, "score": round(score, 2), "total": total, "passed": passed, "rows": outputs}


def main():
    ap = argparse.ArgumentParser()
    ap.add_argument("--mode", choices=["selfcheck", "single", "eval"], required=True)
    ap.add_argument("--request", default="")
    ap.add_argument("--risk", choices=["low", "medium", "high"], default="medium")
    ap.add_argument("--pii", type=int, choices=[0, 1], default=0)
    ap.add_argument("--deadline", type=int, default=24)
    ap.add_argument("--input", default="")
    args = ap.parse_args()

    if args.mode == "selfcheck":
        print(json.dumps(run_selfcheck(), ensure_ascii=False, indent=2))
        return

    if args.mode == "single":
        t = TaskInput(
            request=args.request or "주간 운영보고 초안 작성",
            risk_level=args.risk,
            has_pii=args.pii,
            deadline_hours=args.deadline,
        )
        print(json.dumps(execute_task(t), ensure_ascii=False, indent=2))
        return

    if args.mode == "eval":
        if not args.input:
            raise SystemExit("--input 경로를 지정하세요.")
        print(json.dumps(run_eval(Path(args.input)), ensure_ascii=False, indent=2))


if __name__ == "__main__":
    main()
