#!/bin/bash
# codex-code-review.sh - Run an AI-powered code quality review using Codex CLI
# Usage: codex-code-review.sh [OPTIONS]
#
# Runs codex exec in read-only sandbox mode with a structured code review prompt.
# Outputs findings as JSON and optionally posts them to a PR.

set -e

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/common.sh"

# Defaults
PR_NUMBER=""
BASE_BRANCH="main"
COMMIT_SHA=""
OUTPUT_FILE=""
POST_TO_PR=false
UNCOMMITTED=false
REVIEW_MODE=""

show_help() {
    cat <<'EOF'
Usage: codex-code-review.sh [OPTIONS]

Run an AI-powered code quality review using OpenAI Codex CLI.

Options:
  -n, --pr <number>       PR number (auto-enables posting findings to PR)
  -b, --base <branch>     Base branch to diff against (default: main)
  -c, --commit <sha>      Review a specific commit
  -o, --output <path>     Write JSON results to file
  --post-to-pr            Post findings as PR comment (requires -n)
  --uncommitted           Review uncommitted changes (staged + unstaged + untracked)
  -h, --help              Show this help

Examples:
  # Review uncommitted changes
  codex-code-review.sh --uncommitted

  # Review a PR and post findings as a comment
  codex-code-review.sh -n 42

  # Review changes against main, save JSON
  codex-code-review.sh -b main -o review.json

  # Review a specific commit
  codex-code-review.sh -c abc123f
EOF
    exit 0
}

# Parse arguments
while [[ $# -gt 0 ]]; do
    case $1 in
        -n|--pr)
            PR_NUMBER="$2"
            POST_TO_PR=true
            REVIEW_MODE="pr"
            shift 2
            ;;
        -b|--base)
            BASE_BRANCH="$2"
            REVIEW_MODE="base"
            shift 2
            ;;
        -c|--commit)
            COMMIT_SHA="$2"
            REVIEW_MODE="commit"
            shift 2
            ;;
        -o|--output)
            OUTPUT_FILE="$2"
            shift 2
            ;;
        --post-to-pr)
            POST_TO_PR=true
            shift
            ;;
        --uncommitted)
            UNCOMMITTED=true
            REVIEW_MODE="uncommitted"
            shift
            ;;
        -h|--help)
            show_help
            ;;
        *)
            echo "Unknown option: $1" >&2
            echo "Run with --help for usage" >&2
            exit 1
            ;;
    esac
done

# Validate
if [[ -z "$REVIEW_MODE" ]]; then
    echo "Error: Specify a review mode: --uncommitted, --base <branch>, --commit <sha>, or --pr <number>" >&2
    exit 1
fi

if [[ "$POST_TO_PR" == true && -z "$PR_NUMBER" ]]; then
    echo "Error: --post-to-pr requires -n <pr_number>" >&2
    exit 1
fi

check_codex
check_jq

# Verify we're in a git repo
if ! git rev-parse --is-inside-work-tree &>/dev/null; then
    echo "Error: Not inside a git repository" >&2
    exit 1
fi

# Get the diff context
echo "Gathering diff context..." >&2
case "$REVIEW_MODE" in
    uncommitted) DIFF_CONTEXT=$(build_diff_context "uncommitted" "") ;;
    base)        DIFF_CONTEXT=$(build_diff_context "base" "$BASE_BRANCH") ;;
    commit)      DIFF_CONTEXT=$(build_diff_context "commit" "$COMMIT_SHA") ;;
    pr)          DIFF_CONTEXT=$(build_diff_context "pr" "$PR_NUMBER") ;;
esac

if [[ -z "$DIFF_CONTEXT" ]]; then
    echo "No changes found to review." >&2
    exit 0
fi

# Build the review prompt
REVIEW_PROMPT=$(cat <<'PROMPT'
You are an expert code reviewer. Review the following code changes thoroughly.

Focus on issues that are ACTIONABLE and IMPORTANT. Do not flag trivial style issues.

## Review Checklist

### Correctness
- Code does what it claims to do
- Edge cases are handled
- Error conditions are managed properly
- No obvious bugs or logic errors

### Code Quality
- Functions are focused and reasonably sized
- No unnecessary complexity
- DRY - no significant duplication
- Clear naming for variables and functions
- No dead code or commented-out code

### Testing
- Tests exist for new functionality
- Tests cover happy path AND error cases
- No flaky tests introduced

### Performance
- No obvious N+1 queries
- No blocking operations in hot paths
- Resource cleanup (connections, file handles)

### Dependencies
- No deprecated packages
- No unnecessary new dependencies

### Documentation
- Complex logic has explanatory comments
- Public APIs are documented

## Severity Guide
- **blocker**: Must fix before merge (bugs, correctness issues, missing error handling)
- **should-fix**: Important but not blocking (code quality, minor issues)
- **suggestion**: Optional improvements (nice-to-haves)

Only report findings you are confident about (confidence > 0.7).
If the code looks good, say so — don't manufacture issues.

PROMPT
)

# Set up temp files for output and diff
TEMP_OUTPUT=$(mktemp /tmp/codex-review-XXXXXX.json)
TEMP_DIFF=$(mktemp /tmp/codex-diff-XXXXXX.txt)
trap 'rm -f "$TEMP_OUTPUT" "$TEMP_DIFF"' EXIT

SCHEMA_FILE="$SCRIPT_DIR/schemas/code-review-schema.json"

# Write diff to temp file
echo "$DIFF_CONTEXT" > "$TEMP_DIFF"

echo "Running Codex code review..." >&2
echo "  Diff size: $(wc -l < "$TEMP_DIFF") lines" >&2

# Build full prompt with diff reference
FULL_PROMPT="${REVIEW_PROMPT}

Here are the code changes to review:

\`\`\`diff
$(cat "$TEMP_DIFF")
\`\`\`"

# Run codex exec with prompt from stdin to avoid arg length limits
echo "$FULL_PROMPT" | codex exec \
    --sandbox read-only \
    --output-schema "$SCHEMA_FILE" \
    -o "$TEMP_OUTPUT" \
    - 2>&1 | while IFS= read -r line; do
    echo "  [codex] $line" >&2
done

# Check output was produced
if [[ ! -s "$TEMP_OUTPUT" ]]; then
    echo "Error: Codex produced no output" >&2
    exit 1
fi

# Validate JSON
if ! jq empty "$TEMP_OUTPUT" 2>/dev/null; then
    echo "Error: Codex output is not valid JSON" >&2
    cat "$TEMP_OUTPUT" >&2
    exit 1
fi

# Save output if requested
if [[ -n "$OUTPUT_FILE" ]]; then
    cp "$TEMP_OUTPUT" "$OUTPUT_FILE"
    echo "Results saved to: $OUTPUT_FILE" >&2
fi

# Post to PR if requested
if [[ "$POST_TO_PR" == true && -n "$PR_NUMBER" ]]; then
    echo "Posting findings to PR #$PR_NUMBER..." >&2
    post_to_pr "$PR_NUMBER" "$TEMP_OUTPUT" "code"
    echo "Posted review to PR #$PR_NUMBER" >&2
fi

# Always print results to stdout
print_results "$TEMP_OUTPUT" "code"
