#!/bin/bash
# common.sh - Shared utilities for Codex review scripts
# Source this file from review scripts: source "$(dirname "${BASH_SOURCE[0]}")/common.sh"

set -e

CODEX_SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
GIT_SCRIPT_DIR="$CODEX_SCRIPT_DIR/../git"

# Source platform detection
source "$GIT_SCRIPT_DIR/detect-platform.sh"

# Check codex is installed
check_codex() {
    if ! command -v codex &>/dev/null; then
        echo "Error: codex CLI not found. Install with: npm i -g @openai/codex" >&2
        exit 1
    fi
}

# Check jq is installed (needed for JSON processing)
check_jq() {
    if ! command -v jq &>/dev/null; then
        echo "Error: jq not found. Install with your package manager." >&2
        exit 1
    fi
}

# Build the codex exec command args for the review mode
# Arguments: $1=mode (--uncommitted|--base|--commit), $2=value (branch/sha)
build_diff_context() {
    local mode="$1"
    local value="$2"
    local diff_text=""

    case "$mode" in
        uncommitted)
            diff_text=$(git diff HEAD 2>/dev/null; git diff --cached 2>/dev/null; git ls-files --others --exclude-standard 2>/dev/null | while read -r f; do echo "=== NEW FILE: $f ==="; cat "$f" 2>/dev/null; done)
            ;;
        base)
            diff_text=$(git diff "${value}...HEAD" 2>/dev/null)
            ;;
        commit)
            diff_text=$(git show "$value" 2>/dev/null)
            ;;
        pr)
            # For PRs, we need to fetch the PR diff
            detect_platform
            if [[ "$PLATFORM" == "github" ]]; then
                diff_text=$(gh pr diff "$value" 2>/dev/null)
            elif [[ "$PLATFORM" == "gitea" ]]; then
                # tea doesn't have a direct pr diff command, use git
                local pr_base
                pr_base=$(tea pr list --fields index,base --output simple 2>/dev/null | grep "^${value}" | awk '{print $2}')
                if [[ -n "$pr_base" ]]; then
                    diff_text=$(git diff "${pr_base}...HEAD" 2>/dev/null)
                else
                    # Fallback: fetch PR info via API
                    local repo_info
                    repo_info=$(get_repo_info)
                    local remote_url
                    remote_url=$(git remote get-url origin 2>/dev/null)
                    local host
                    host=$(echo "$remote_url" | sed -E 's|.*://([^/]+).*|\1|; s|.*@([^:]+).*|\1|')
                    diff_text=$(curl -s "https://${host}/api/v1/repos/${repo_info}/pulls/${value}" \
                        -H "Authorization: token $(tea login list --output simple 2>/dev/null | head -1 | awk '{print $2}')" \
                        2>/dev/null | jq -r '.diff_url // empty')
                    if [[ -n "$diff_text" && "$diff_text" != "null" ]]; then
                        diff_text=$(curl -s "$diff_text" 2>/dev/null)
                    else
                        diff_text=$(git diff "main...HEAD" 2>/dev/null)
                    fi
                fi
            fi
            ;;
    esac

    echo "$diff_text"
}

# Format JSON findings as markdown for PR comments
# Arguments: $1=json_file, $2=review_type (code|security)
format_findings_as_markdown() {
    local json_file="$1"
    local review_type="$2"

    if [[ ! -f "$json_file" ]]; then
        echo "Error: JSON file not found: $json_file" >&2
        return 1
    fi

    local summary verdict confidence
    summary=$(jq -r '.summary' "$json_file")
    confidence=$(jq -r '.confidence' "$json_file")

    if [[ "$review_type" == "code" ]]; then
        verdict=$(jq -r '.verdict' "$json_file")
        local blockers should_fix suggestions files_reviewed
        blockers=$(jq -r '.stats.blockers' "$json_file")
        should_fix=$(jq -r '.stats.should_fix' "$json_file")
        suggestions=$(jq -r '.stats.suggestions' "$json_file")
        files_reviewed=$(jq -r '.stats.files_reviewed' "$json_file")

        cat <<EOF
## Codex Code Review

**Verdict:** ${verdict} | **Confidence:** ${confidence} | **Files reviewed:** ${files_reviewed}
**Findings:** ${blockers} blockers, ${should_fix} should-fix, ${suggestions} suggestions

### Summary
${summary}

EOF
    else
        local risk_level critical high medium low files_reviewed
        risk_level=$(jq -r '.risk_level' "$json_file")
        critical=$(jq -r '.stats.critical' "$json_file")
        high=$(jq -r '.stats.high' "$json_file")
        medium=$(jq -r '.stats.medium' "$json_file")
        low=$(jq -r '.stats.low' "$json_file")
        files_reviewed=$(jq -r '.stats.files_reviewed' "$json_file")

        cat <<EOF
## Codex Security Review

**Risk Level:** ${risk_level} | **Confidence:** ${confidence} | **Files reviewed:** ${files_reviewed}
**Findings:** ${critical} critical, ${high} high, ${medium} medium, ${low} low

### Summary
${summary}

EOF
    fi

    # Output findings
    local finding_count
    finding_count=$(jq '.findings | length' "$json_file")

    if [[ "$finding_count" -gt 0 ]]; then
        echo "### Findings"
        echo ""

        jq -r '.findings[] | "#### [\(.severity | ascii_upcase)] \(.title)\n- **File:** `\(.file)`\(if .line_start then " (L\(.line_start)\(if .line_end and .line_end != .line_start then "-L\(.line_end)" else "" end))" else "" end)\n- \(.description)\(if .suggestion then "\n- **Suggestion:** \(.suggestion)" else "" end)\(if .cwe_id then "\n- **CWE:** \(.cwe_id)" else "" end)\(if .owasp_category then "\n- **OWASP:** \(.owasp_category)" else "" end)\(if .remediation then "\n- **Remediation:** \(.remediation)" else "" end)\n"' "$json_file"
    else
        echo "*No issues found.*"
    fi

    echo "---"
    echo "*Reviewed by Codex ($(codex --version 2>/dev/null || echo "unknown"))*"
}

# Post review findings to a PR
# Arguments: $1=pr_number, $2=json_file, $3=review_type (code|security)
post_to_pr() {
    local pr_number="$1"
    local json_file="$2"
    local review_type="$3"

    local markdown
    markdown=$(format_findings_as_markdown "$json_file" "$review_type")

    detect_platform

    # Determine review action based on findings
    local action="comment"
    if [[ "$review_type" == "code" ]]; then
        local verdict
        verdict=$(jq -r '.verdict' "$json_file")
        action="$verdict"
    else
        local risk_level
        risk_level=$(jq -r '.risk_level' "$json_file")
        case "$risk_level" in
            critical|high) action="request-changes" ;;
            medium) action="comment" ;;
            low|none) action="comment" ;;
        esac
    fi

    # Post the review
    "$GIT_SCRIPT_DIR/pr-review.sh" -n "$pr_number" -a "$action" -c "$markdown"
}

# Print review results to stdout
# Arguments: $1=json_file, $2=review_type (code|security)
print_results() {
    local json_file="$1"
    local review_type="$2"

    format_findings_as_markdown "$json_file" "$review_type"
}
