#!/usr/bin/env python3
"""
AI Code Reviewer (AI-on-AI Review)
===================================
Phase 5: 全自動防禦網 - AI 督戰隊

功能:
1. 讀取 git diff (staged changes)
2. 讀取 .awoooi-agent-rules.md 規則
3. 呼叫 Ollama API 進行架構審查
4. 回傳 PASS/FAIL 結果

使用方式:
    python scripts/ai_code_reviewer.py

Exit Codes:
    0 = PASS (允許 commit)
    1 = FAIL (阻止 commit)
"""

import json
import os
import subprocess
import sys
from pathlib import Path

import httpx

# =============================================================================
# Configuration
# =============================================================================

OLLAMA_URL = os.getenv("OLLAMA_GENERATE_URL", "http://192.168.0.111:11434/api/generate")
MODEL = "llama3.2:8b"
PROJECT_ROOT = Path(__file__).parent.parent
RULES_FILE = PROJECT_ROOT / ".awoooi-agent-rules.md"
TIMEOUT = 120  # seconds


# =============================================================================
# Git Operations
# =============================================================================

def get_staged_diff() -> str:
    """取得 staged changes 的 diff"""
    try:
        result = subprocess.run(
            ["git", "diff", "--cached", "--no-color"],
            capture_output=True,
            text=True,
            cwd=PROJECT_ROOT,
        )
        return result.stdout
    except Exception as e:
        print(f"[AI-REVIEWER] Error getting git diff: {e}")
        return ""


def get_staged_files() -> list[str]:
    """取得 staged files 清單"""
    try:
        result = subprocess.run(
            ["git", "diff", "--cached", "--name-only"],
            capture_output=True,
            text=True,
            cwd=PROJECT_ROOT,
        )
        return [f.strip() for f in result.stdout.splitlines() if f.strip()]
    except Exception as e:
        print(f"[AI-REVIEWER] Error getting staged files: {e}")
        return []


# =============================================================================
# Rule Extraction
# =============================================================================

def load_rules() -> str:
    """讀取 AWOOOI 規則檔案 (精簡版)"""
    if not RULES_FILE.exists():
        return "No rules file found."

    content = RULES_FILE.read_text()

    # 萃取關鍵規則 (避免 prompt 過長)
    key_sections = []

    # 萃取禁止事項
    if "## 🚫 絕對禁止事項" in content:
        start = content.find("## 🚫 絕對禁止事項")
        end = content.find("## ✅ 開發準則", start)
        if end > start:
            key_sections.append(content[start:end])

    # 萃取六大鐵律
    if "## 🚨 六大鐵律" in content:
        start = content.find("## 🚨 六大鐵律")
        end = content.find("---", start + 10)
        if end > start:
            key_sections.append(content[start:end])

    # 萃取 i18n 鐵律
    if "## 🌐 國際化 (i18n) 鐵律" in content:
        start = content.find("## 🌐 國際化 (i18n) 鐵律")
        end = content.find("## 📜 API 契約驅動開發", start)
        if end > start:
            key_sections.append(content[start:end])

    return "\n\n".join(key_sections) if key_sections else content[:5000]


# =============================================================================
# Ollama Review
# =============================================================================

def call_ollama_review(diff: str, rules: str, files: list[str]) -> dict:
    """呼叫 Ollama 進行代碼審查"""
    prompt = f"""You are AWOOOI's AI Code Reviewer. Analyze the following git diff and check for violations.

## RULES TO ENFORCE:
{rules}

## FILES CHANGED:
{', '.join(files[:20])}

## GIT DIFF:
```diff
{diff[:8000]}
```

## YOUR TASK:
1. Check for hardcoded secrets (API keys, passwords, tokens)
2. Check for hardcoded Chinese/English strings in UI components (should use next-intl)
3. Check for imports from forbidden paths (../../../wooo-aiops/)
4. Check for architecture violations (mixing layers, etc.)
5. Check for potential security issues

## RESPONSE FORMAT (JSON only):
{{
  "verdict": "PASS" or "FAIL",
  "issues": [
    {{"severity": "critical|warning", "file": "path", "line": "N/A", "message": "description"}}
  ],
  "summary": "One sentence summary"
}}

Respond with ONLY the JSON, no markdown, no explanation.
"""

    try:
        response = httpx.post(
            OLLAMA_URL,
            json={
                "model": MODEL,
                "prompt": prompt,
                "stream": False,
                "options": {
                    "temperature": 0.1,
                    "num_predict": 1000,
                },
            },
            timeout=TIMEOUT,
        )
        response.raise_for_status()
        result = response.json()
        response_text = result.get("response", "")

        # 嘗試解析 JSON
        # 清理可能的 markdown 包裹
        cleaned = response_text.strip()
        if cleaned.startswith("```json"):
            cleaned = cleaned[7:]
        if cleaned.startswith("```"):
            cleaned = cleaned[3:]
        if cleaned.endswith("```"):
            cleaned = cleaned[:-3]
        cleaned = cleaned.strip()

        return json.loads(cleaned)

    except httpx.TimeoutException:
        print("[AI-REVIEWER] Ollama timeout - allowing commit (fail-open)")
        return {"verdict": "PASS", "issues": [], "summary": "Review skipped (timeout)"}
    except httpx.ConnectError:
        print("[AI-REVIEWER] Cannot connect to Ollama - allowing commit (fail-open)")
        return {"verdict": "PASS", "issues": [], "summary": "Review skipped (no connection)"}
    except json.JSONDecodeError as e:
        print(f"[AI-REVIEWER] JSON parse error: {e}")
        print(f"[AI-REVIEWER] Raw response: {response_text[:500]}")
        return {"verdict": "PASS", "issues": [], "summary": "Review skipped (parse error)"}
    except Exception as e:
        print(f"[AI-REVIEWER] Error: {e}")
        return {"verdict": "PASS", "issues": [], "summary": f"Review skipped ({type(e).__name__})"}


# =============================================================================
# Main
# =============================================================================

def main() -> int:
    """主程式"""
    print("\n" + "=" * 60)
    print("🤖 AWOOOI AI Code Reviewer (AI-on-AI)")
    print("=" * 60)

    # 取得 staged changes
    files = get_staged_files()
    if not files:
        print("[AI-REVIEWER] No staged changes. Skipping review.")
        return 0

    print(f"[AI-REVIEWER] Reviewing {len(files)} staged file(s)...")
    for f in files[:10]:
        print(f"  - {f}")
    if len(files) > 10:
        print(f"  ... and {len(files) - 10} more")

    diff = get_staged_diff()
    if not diff:
        print("[AI-REVIEWER] Empty diff. Skipping review.")
        return 0

    # 載入規則
    rules = load_rules()

    # 呼叫 Ollama
    print(f"[AI-REVIEWER] Calling Ollama ({MODEL})...")
    result = call_ollama_review(diff, rules, files)

    # 輸出結果
    verdict = result.get("verdict", "PASS")
    issues = result.get("issues", [])
    summary = result.get("summary", "")

    print("\n" + "-" * 60)
    print(f"Summary: {summary}")
    print("-" * 60)

    if issues:
        print("\n📋 Issues Found:")
        for issue in issues:
            severity = issue.get("severity", "warning")
            file = issue.get("file", "N/A")
            msg = issue.get("message", "")
            icon = "🔴" if severity == "critical" else "🟡"
            print(f"  {icon} [{severity.upper()}] {file}: {msg}")

    print("\n" + "=" * 60)
    if verdict == "PASS":
        print("✅ VERDICT: PASS - Commit allowed")
        print("=" * 60 + "\n")
        return 0
    else:
        print("❌ VERDICT: FAIL - Commit blocked")
        print("=" * 60 + "\n")
        print("Fix the issues above and try again.")
        return 1


if __name__ == "__main__":
    sys.exit(main())
