"""Adversarial AI code review — sends PR diff to OpenAI-compatible endpoint.

Stdlib-only. Works with vLLM, Ollama, LM Studio, or OpenAI/DeepSeek cloud.
Disabled by default; activated via GitHub Actions variable.
"""

from __future__ import annotations

import argparse
import json
import os
import ssl
import sys
import urllib.error
import urllib.request

MAX_DIFF_CHARS = 30_000
TIMEOUT_SECONDS = 120
TEMPERATURE = 0.2

SYSTEM_PROMPT = """\
You are an adversarial code reviewer. You did NOT write this code.
Your job is to find problems the author missed.

Orxaq is a causal intelligence OS for credit risk. It uses directed acyclic
graphs, structural causal models, and Bayesian inference for credit risk
analysis.

Review the diff for issues in these categories:
- security: injection, hardcoded secrets, auth bypass, unsafe deserialization
- correctness: logic errors, off-by-one, race conditions, unhandled edge cases
- performance: O(n^2) where O(n) suffices, unnecessary allocations, missing caching
- style: naming, dead code, overly complex conditionals, missing type hints
- causal_reasoning: invalid d-separation, wrong causal roles, confusing correlation
  with causation, missing confounders, incorrect intervention semantics

Respond ONLY with valid JSON in this exact format:
{
  "summary": "1-2 sentence assessment",
  "risk_level": "low|medium|high|critical",
  "findings": [
    {
      "category": "security|correctness|performance|style|causal_reasoning",
      "severity": "info|warning|error|critical",
      "file": "path.py",
      "line": 42,
      "title": "Short title",
      "detail": "What is wrong",
      "suggestion": "How to fix it"
    }
  ],
  "approval": "approve|request_changes|comment"
}

If the diff is clean with no issues, return an empty findings array and
approval "approve". Do not invent problems that do not exist.
"""


def review_diff(diff_text: str) -> dict:
    """Send diff to OpenAI-compatible endpoint and return structured review."""
    api_base = os.environ.get("REVIEW_API_BASE", "http://localhost:8000/v1")
    api_key = os.environ.get("REVIEW_API_KEY", "not-needed")
    model = os.environ.get("REVIEW_MODEL", "deepseek-coder")

    # Truncate oversized diffs to fit context windows
    if len(diff_text) > MAX_DIFF_CHARS:
        diff_text = diff_text[:MAX_DIFF_CHARS] + "\n\n[... diff truncated ...]"

    payload = json.dumps(
        {
            "model": model,
            "temperature": TEMPERATURE,
            "messages": [
                {"role": "system", "content": SYSTEM_PROMPT},
                {"role": "user", "content": f"Review this PR diff:\n\n```diff\n{diff_text}\n```"},
            ],
        }
    ).encode()

    url = f"{api_base.rstrip('/')}/chat/completions"
    req = urllib.request.Request(
        url,
        data=payload,
        headers={
            "Content-Type": "application/json",
            "Authorization": f"Bearer {api_key}",
        },
        method="POST",
    )

    ctx = ssl.create_default_context()

    try:
        with urllib.request.urlopen(req, timeout=TIMEOUT_SECONDS, context=ctx) as resp:
            body = json.loads(resp.read().decode())
    except (urllib.error.URLError, TimeoutError, OSError) as exc:
        return {
            "summary": f"Adversarial review unavailable: {exc}",
            "risk_level": "unknown",
            "findings": [],
            "approval": "comment",
        }

    content = body["choices"][0]["message"]["content"]

    # Strip markdown fences if the model wraps JSON in ```json ... ```
    content = content.strip()
    if content.startswith("```"):
        first_newline = content.index("\n")
        content = content[first_newline + 1 :]
        if content.endswith("```"):
            content = content[:-3]
        content = content.strip()

    try:
        return json.loads(content)
    except json.JSONDecodeError:
        return {
            "summary": "Review model returned non-JSON response.",
            "risk_level": "unknown",
            "findings": [],
            "approval": "comment",
            "_raw_response": content[:500],
        }


def main() -> None:
    parser = argparse.ArgumentParser(description="Adversarial AI code review")
    parser.add_argument("--diff", required=True, help="Path to diff file")
    parser.add_argument("--output", required=True, help="Path to write review JSON")
    args = parser.parse_args()

    with open(args.diff) as f:
        diff_text = f.read()

    if not diff_text.strip():
        print("Empty diff — skipping review.")
        result = {
            "summary": "No Python changes to review.",
            "risk_level": "low",
            "findings": [],
            "approval": "approve",
        }
    else:
        print(f"Reviewing {len(diff_text)} chars of diff...")
        result = review_diff(diff_text)

    with open(args.output, "w") as f:
        json.dump(result, f, indent=2)

    print(f"Review written to {args.output}")
    print(f"Risk level: {result.get('risk_level', 'unknown')}")
    print(f"Findings: {len(result.get('findings', []))}")
    print(f"Recommendation: {result.get('approval', 'unknown')}")

    # Exit non-zero only on critical risk to block the pipeline
    if result.get("risk_level") == "critical":
        print("CRITICAL risk detected — failing pipeline.")
        sys.exit(1)


if __name__ == "__main__":
    main()
