#!/usr/bin/env python3
"""
auto_revert.py - probe FAIL 시 자동 revert PR 생성 (task-2367 P1)

사용법:
    python3 scripts/auto_revert.py --task-id task-XXXX --merge-sha <sha> --project-path <path> --reason "..."

동작:
    1. revert/{task_id} 브랜치 생성 (main 기반)
    2. git revert -m 1 <merge_sha> (★ hard reset 절대 사용 금지)
    3. push + gh pr create
    4. audit log에 reverted 기록
    5. 회장에게 즉시 Telegram 알림 (gh CLI 또는 cokacdir 사용)
"""

import argparse
import json
import logging
import os
import subprocess
from datetime import datetime, timezone, timedelta
from pathlib import Path

KST = timezone(timedelta(hours=9))
WORKSPACE = Path(os.environ.get("WORKSPACE_ROOT", "/home/jay/workspace"))
AUDIT_LOG = WORKSPACE / "memory" / "audit" / "auto-merge.log"

logging.basicConfig(level=logging.INFO, format="%(asctime)s [%(levelname)s] %(message)s")
logger = logging.getLogger("auto_revert")


def _append_audit(record: dict) -> None:
    import fcntl
    AUDIT_LOG.parent.mkdir(parents=True, exist_ok=True)
    AUDIT_LOG.touch(exist_ok=True)
    with open(AUDIT_LOG, "r", encoding="utf-8") as f:
        seq = sum(1 for _ in f) + 1
    record.setdefault("timestamp", datetime.now(KST).isoformat())
    record["sequence"] = seq
    with open(AUDIT_LOG, "a", encoding="utf-8") as f:
        fcntl.flock(f.fileno(), fcntl.LOCK_EX)
        try:
            f.write(json.dumps(record, ensure_ascii=False) + "\n")
        finally:
            fcntl.flock(f.fileno(), fcntl.LOCK_UN)


def create_revert_pr(task_id: str, merge_sha: str, project_path: Path, reason: str) -> dict:
    """git revert -m 1 PR 생성. ★ git reset --hard 절대 사용 금지."""
    branch = f"revert/{task_id}"
    project_path = project_path.resolve()
    cwd = ["git", "-C", str(project_path)]

    try:
        # 1. main 동기화
        subprocess.check_call(cwd + ["fetch", "origin", "main"], stderr=subprocess.STDOUT)
        # 2. main 기반 새 브랜치 (이미 있으면 강제 재생성)
        try:
            subprocess.check_call(cwd + ["branch", "-D", branch], stderr=subprocess.DEVNULL)
        except subprocess.CalledProcessError:
            pass
        subprocess.check_call(cwd + ["checkout", "-b", branch, "origin/main"])
        # 3. ★ git revert -m 1 (hard reset 절대 사용 금지)
        subprocess.check_call(cwd + ["revert", "--no-edit", "-m", "1", merge_sha])
        # 4. push
        subprocess.check_call(cwd + ["push", "-u", "origin", branch, "--force-with-lease"])
        # 5. PR 생성 (gh CLI)
        title = f"[REVERT] {task_id} — auto-revert (probe FAIL)"
        body = (
            f"## 자동 Revert PR\n\n"
            f"- task: {task_id}\n"
            f"- 머지 SHA: `{merge_sha}`\n"
            f"- 사유: {reason}\n\n"
            f"★ post_merge_probe.py가 5분 후 검증한 결과 FAIL 감지하여 자동 생성됨.\n"
            f"회장 명시 승인 후 머지하세요."
        )
        try:
            r = subprocess.run(
                ["gh", "pr", "create", "--title", title, "--body", body, "--base", "main", "--head", branch],
                cwd=project_path,
                capture_output=True,
                text=True,
                timeout=60,
            )
            pr_url = r.stdout.strip() if r.returncode == 0 else ""
        except Exception as e:
            pr_url = f"gh pr create 실패: {e}"

        record = {
            "task_id": task_id,
            "merge_sha": merge_sha,
            "tier": "auto-revert",
            "outcome": "reverted",
            "merger": "auto_revert.py",
            "qc_result": "fail",
            "scope_guard": "skipped",
            "diff_files": [],
            "diff_loc": 0,
            "revert": {
                "branch": branch,
                "pr_url": pr_url,
                "reason": reason,
            },
        }
        _append_audit(record)
        return record
    except subprocess.CalledProcessError as e:
        record = {
            "task_id": task_id,
            "merge_sha": merge_sha,
            "tier": "auto-revert",
            "outcome": "revert_failed",
            "merger": "auto_revert.py",
            "qc_result": "fail",
            "scope_guard": "skipped",
            "diff_files": [],
            "diff_loc": 0,
            "revert": {"error": str(e)},
        }
        _append_audit(record)
        return record


if __name__ == "__main__":
    parser = argparse.ArgumentParser()
    parser.add_argument("--task-id", required=True)
    parser.add_argument("--merge-sha", required=True)
    parser.add_argument("--project-path", default=str(WORKSPACE))
    parser.add_argument("--reason", default="health probe FAIL")
    args = parser.parse_args()

    result = create_revert_pr(args.task_id, args.merge_sha, Path(args.project_path), args.reason)
    print(json.dumps(result, ensure_ascii=False, indent=2))
