"""
gemini_review_check.py — Gemini PR 리뷰 교차검증 verifier

보고서의 "Gemini PR 리뷰" 섹션과 실제 GitHub PR 코멘트의 severity를 교차검증한다.
보고서에 "High 0건"이라 되어 있는데 실제 Gemini 코멘트에 HIGH가 있으면 FAIL.
"""

import json
import os
import re
import subprocess

MEMORY_BASE = os.environ.get("WORKSPACE_ROOT", "/home/jay/workspace") + "/memory"
REPORTS_DIR = os.path.join(MEMORY_BASE, "reports")

# Gemini 마크다운 이미지 severity 패턴
_HIGH_IMG_RE = re.compile(r"!\[(security-critical|critical|high)\]", re.IGNORECASE)
_MEDIUM_IMG_RE = re.compile(r"!\[(medium)\]", re.IGNORECASE)


def _extract_pr_number(report_content: str) -> str | None:
    """보고서에서 PR 번호를 추출한다."""
    # 패턴: PR #123, pr_number: 123, /pulls/123 등
    patterns = [
        r"PR\s*#(\d+)",
        r"pr_number[\"']?\s*[:=]\s*[\"']?(\d+)",
        r"/pulls?/(\d+)",
        r"#(\d+)\s+worktree\s+finish",
    ]
    for p in patterns:
        m = re.search(p, report_content, re.IGNORECASE)
        if m:
            return m.group(1)
    return None


def _extract_repo_info(report_content: str) -> tuple[str, str] | None:
    """보고서에서 owner/repo를 추출한다."""
    m = re.search(r"github\.com/([^/\s]+)/([^/\s#]+)", report_content)
    if m:
        return m.group(1), m.group(2).rstrip("/")
    return None


def _parse_gemini_severity_from_body(body: str) -> str:
    """Gemini 코멘트 body에서 severity를 파싱한다."""
    body_lower = body.lower()
    if (
        "severity: high" in body_lower
        or "severity: critical" in body_lower
        or "🔴" in body
        or "HIGH" in body
        or "CRITICAL" in body
        or _HIGH_IMG_RE.search(body)
        or "high-priority.svg" in body_lower
        or "critical.svg" in body_lower
    ):
        return "high"
    if (
        "severity: medium" in body_lower
        or "⚠️" in body
        or "MEDIUM" in body
        or "WARNING" in body
        or _MEDIUM_IMG_RE.search(body)
        or "medium-priority.svg" in body_lower
    ):
        return "medium"
    return "low"


def _fetch_pr_gemini_comments(owner: str, repo: str, pr_number: str) -> list[dict]:
    """GitHub API로 PR의 Gemini 코멘트를 조회한다."""
    try:
        result = subprocess.run(
            ["gh", "api", f"repos/{owner}/{repo}/pulls/{pr_number}/comments"],
            capture_output=True, text=True, timeout=30,
        )
        if result.returncode != 0:
            return []
        comments = json.loads(result.stdout)
    except (subprocess.TimeoutExpired, json.JSONDecodeError, Exception):
        return []

    gemini_comments = []
    for c in comments:
        user = c.get("user", {}).get("login", "")
        if "gemini" not in user.lower():
            continue
        body = c.get("body", "")
        gemini_comments.append({
            "severity": _parse_gemini_severity_from_body(body),
            "path": c.get("path", ""),
            "body_preview": body[:200],
        })
    return gemini_comments


def _extract_report_high_count(report_content: str) -> int | None:
    """보고서에서 Gemini 리뷰의 High 건수를 추출한다."""
    # 패턴: "High 0건", "high_severity_count: 0", "HIGH: 0"
    patterns = [
        r"High\s+(\d+)\s*건",
        r"high_severity_count[\"']?\s*[:=]\s*(\d+)",
        r"HIGH\s*[:=]\s*(\d+)",
    ]
    for p in patterns:
        m = re.search(p, report_content, re.IGNORECASE)
        if m:
            return int(m.group(1))
    return None


def run(task_id: str, **kwargs) -> dict:
    """
    QC verifier 인터페이스.
    보고서의 Gemini 리뷰 결과와 실제 PR 코멘트를 교차검증한다.

    Returns:
        {"status": "PASS"|"FAIL"|"SKIP", "details": [...]}
    """
    report_path = os.path.join(REPORTS_DIR, f"{task_id}.md")
    if not os.path.exists(report_path):
        return {"status": "SKIP", "details": ["보고서 파일 없음"]}

    with open(report_path, encoding="utf-8") as f:
        report_content = f.read()

    # Gemini 관련 섹션이 없으면 SKIP
    if "gemini" not in report_content.lower() and "Gemini" not in report_content:
        return {"status": "SKIP", "details": ["보고서에 Gemini 관련 내용 없음"]}

    pr_number = _extract_pr_number(report_content)
    if not pr_number:
        return {"status": "SKIP", "details": ["보고서에서 PR 번호 추출 실패"]}

    repo_info = _extract_repo_info(report_content)
    if not repo_info:
        return {"status": "SKIP", "details": ["보고서에서 repo 정보 추출 실패"]}

    owner, repo = repo_info

    # 보고서의 High 건수 추출
    report_high = _extract_report_high_count(report_content)

    # 실제 PR 코멘트 조회
    gemini_comments = _fetch_pr_gemini_comments(owner, repo, pr_number)
    if not gemini_comments:
        return {"status": "SKIP", "details": [f"PR #{pr_number}에서 Gemini 코멘트를 조회하지 못함"]}

    actual_high = sum(1 for c in gemini_comments if c["severity"] == "high")
    actual_medium = sum(1 for c in gemini_comments if c["severity"] == "medium")

    details = [
        f"PR #{pr_number}: Gemini 코멘트 {len(gemini_comments)}건 (High {actual_high}, Medium {actual_medium})",
    ]

    # 교차검증: 보고서 vs 실제
    if report_high is not None and report_high != actual_high:
        details.append(
            f"불일치: 보고서 High={report_high}건, 실제 High={actual_high}건"
        )
        return {"status": "FAIL", "details": details}

    # 보고서에 High 건수 명시 없어도 실제 HIGH가 있으면 경고
    if report_high is None and actual_high > 0:
        details.append(
            f"경고: 보고서에 High 건수 미명시, 실제 High={actual_high}건 발견"
        )
        return {"status": "FAIL", "details": details}

    details.append("교차검증 통과")
    return {"status": "PASS", "details": details}
