#!/usr/bin/env bash
set -euo pipefail

usage() {
  cat <<'EOF'
Usage: codex-review [options]

Options:
  --mode auto|local|branch   Target selection. Default: auto.
  --base REF                 Base ref for branch review. Default: PR base or origin/main.
  --codex-bin PATH           Codex binary. Default: codex.
  --full-access              Run nested Codex review without sandbox/approval prompts.
  --output FILE              Also save output to file.
  --parallel-tests CMD       Run review and test command concurrently.
  --dry-run                  Print selected commands, do not run.
  -h, --help                 Show help.

Modes:
  local   codex review --uncommitted
  branch  codex review --base <base>
  auto    dirty tree -> local, else PR/current branch -> branch
EOF
}

require_option_value() {
  local option=$1
  local value=${2-}

  if [[ -z "$value" || "$value" == --* || "$value" == "-h" ]]; then
    echo "missing value for $option" >&2
    usage >&2
    exit 2
  fi
}

mode=auto
base_ref=
codex_bin=${CODEX_BIN:-codex}
codex_args=()
output=${CODEX_REVIEW_OUTPUT:-}
parallel_tests=
dry_run=false

while [[ $# -gt 0 ]]; do
  case "$1" in
    --mode)
      require_option_value "$1" "${2-}"
      mode=$2
      shift 2
      ;;
    --base)
      require_option_value "$1" "${2-}"
      base_ref=$2
      shift 2
      ;;
    --codex-bin)
      require_option_value "$1" "${2-}"
      codex_bin=$2
      shift 2
      ;;
    --full-access)
      codex_args+=(--dangerously-bypass-approvals-and-sandbox)
      shift
      ;;
    --output)
      require_option_value "$1" "${2-}"
      output=$2
      shift 2
      ;;
    --parallel-tests)
      require_option_value "$1" "${2-}"
      parallel_tests=$2
      shift 2
      ;;
    --dry-run)
      dry_run=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage >&2
      exit 2
      ;;
  esac
done

case "$mode" in
  auto|local|branch) ;;
  *)
    echo "invalid --mode: $mode" >&2
    exit 2
    ;;
esac

nested_level=${CODEX_REVIEW_HELPER_LEVEL:-0}
allow_nested=${CODEX_REVIEW_ALLOW_NESTED:-}
if ! [[ "$nested_level" =~ ^[0-9]+$ ]]; then
  echo "codex-review: invalid CODEX_REVIEW_HELPER_LEVEL=$nested_level" >&2
  exit 2
fi
nested_level_is_nested=false
if [[ "$nested_level" =~ [1-9] ]]; then
  nested_level_is_nested=true
fi
if [[ "$nested_level_is_nested" == true && "$allow_nested" != "1" ]]; then
  echo "codex-review refusal: nested codex-review invocation blocked; set CODEX_REVIEW_ALLOW_NESTED=1 only for intentional debugging" >&2
  exit 78
fi
if [[ "$nested_level_is_nested" != true ]]; then
  export CODEX_REVIEW_HELPER_LEVEL=1
elif (( ${#nested_level} <= 15 )); then
  export CODEX_REVIEW_HELPER_LEVEL=$((10#$nested_level + 1))
else
  export CODEX_REVIEW_HELPER_LEVEL=2
fi
export CODEX_REVIEW_HELPER_PARENT_PID=$$

git rev-parse --show-toplevel >/dev/null

current_branch=$(git branch --show-current 2>/dev/null || true)
dirty=false
if [[ -n "$(git status --porcelain)" ]]; then
  dirty=true
fi

pr_url=
if [[ -z "$base_ref" && "$mode" != local ]] && command -v gh >/dev/null 2>&1; then
  if pr_lines=$(gh pr view --json baseRefName,url --jq '[.baseRefName, .url] | @tsv' 2>/dev/null); then
    base_name=${pr_lines%%$'\t'*}
    pr_url=${pr_lines#*$'\t'}
    if [[ -n "$base_name" ]]; then
      base_ref="origin/$base_name"
    fi
  fi
fi

if [[ -z "$base_ref" ]]; then
  base_ref=origin/main
fi

review_kind=
if [[ "$mode" == local || ( "$mode" == auto && "$dirty" == true ) ]]; then
  review_kind=local
elif [[ "$mode" == branch || ( "$mode" == auto && -n "$current_branch" && "$current_branch" != "main" ) ]]; then
  review_kind=branch
else
  echo "no review target: clean main checkout and no forced mode" >&2
  exit 1
fi

if [[ "$review_kind" == local ]]; then
  review_cmd=("$codex_bin" ${codex_args[@]+"${codex_args[@]}"} review --uncommitted)
else
  review_cmd=("$codex_bin" ${codex_args[@]+"${codex_args[@]}"} review --base "$base_ref")
fi

printf 'codex-review target: %s\n' "$review_kind"
printf 'branch: %s\n' "${current_branch:-detached}"
if [[ -n "$pr_url" ]]; then
  printf 'pr: %s\n' "$pr_url"
fi
printf 'review:'
printf ' %q' "${review_cmd[@]}"
printf '\n'
if [[ -n "$parallel_tests" ]]; then
  printf 'tests: %s\n' "$parallel_tests"
fi
if [[ "$review_kind" == branch ]]; then
  printf 'fetch: git fetch origin --quiet\n'
fi
if [[ -n "$output" ]]; then
  printf 'output: %s\n' "$output"
fi

if [[ "$dry_run" == true ]]; then
  exit 0
fi

if [[ "$review_kind" == branch ]]; then
  git fetch origin --quiet || {
    echo "warning: git fetch origin failed; reviewing with existing refs" >&2
  }
fi

review_output=$output
review_output_is_temp=false
if [[ -z "$review_output" ]]; then
  review_output=$(mktemp)
  review_output_is_temp=true
fi

cleanup() {
  if [[ "${review_output_is_temp:-false}" == true && -n "${review_output:-}" ]]; then
    rm -f "$review_output"
  fi
}
trap cleanup EXIT

run_review() {
  mkdir -p "$(dirname "$review_output")"
  "${review_cmd[@]}" 2>&1 | tee "$review_output"
}

elapsed_since() {
  local started_at=$1
  local finished_at
  finished_at=$(date +%s)
  printf '%s\n' "$((finished_at - started_at))"
}

format_elapsed() {
  local seconds=$1
  if (( seconds < 60 )); then
    printf '%ss\n' "$seconds"
  else
    printf '%sm%ss\n' "$((seconds / 60))" "$((seconds % 60))"
  fi
}

review_output_empty() {
  [[ ! -s "$review_output" ]] || ! grep -q '[^[:space:]]' "$review_output"
}

review_output_has_findings() {
  # Codex CLI transcripts include tool output before the final `codex` section.
  # After the CLI header, prefer the first final-answer marker after the last
  # Codex diagnostic line; if there are no diagnostics, use the last marker.
  # Direct/fake review commands are scanned as a whole.
  awk '
    {
      lines[NR] = $0
      if ($0 ~ /^OpenAI Codex v/) {
        has_codex_header = 1
      }
      if ($0 ~ /^[0-9]{4}-[0-9]{2}-[0-9]{2}T.* (WARN|ERROR) /) {
        last_diagnostic = NR
      }
      if ($0 ~ /\[P[0-3]\]/) {
        any_finding = 1
      }
    }
    END {
      if (has_codex_header) {
        if (last_diagnostic) {
          for (i = last_diagnostic + 1; i <= NR; i++) {
            if (lines[i] == "codex") {
              final_start = i + 1
              break
            }
          }
        } else {
          for (i = 1; i <= NR; i++) {
            if (lines[i] == "codex") {
              final_start = i + 1
            }
          }
        }
        if (final_start) {
          for (i = final_start; i <= NR; i++) {
            if (lines[i] ~ /\[P[0-3]\]/) {
              exit 0
            }
          }
          exit 1
        }
      }
      exit any_finding ? 0 : 1
    }
  ' "$review_output"
}

report_clean_review_or_fail() {
  local elapsed_text
  elapsed_text=$(format_elapsed "${review_elapsed_seconds:-0}")

  if review_output_has_findings; then
    printf 'codex-review complete after %s\n' "$elapsed_text"
    printf 'codex-review findings: accepted/actionable findings reported\n'
    return 1
  fi
  if review_output_empty; then
    printf 'codex-review complete after %s; no output\n' "$elapsed_text"
    return 1
  fi
  printf 'codex-review complete after %s\n' "$elapsed_text"
  printf 'codex-review clean: no accepted/actionable findings reported\n'
}

if [[ -z "$parallel_tests" ]]; then
  review_started_at=$(date +%s)
  set +e
  run_review
  review_status=$?
  review_elapsed_seconds=$(elapsed_since "$review_started_at")
  set -e
  if [[ "$review_status" == 0 ]]; then
    report_clean_review_or_fail
    exit $?
  fi
  exit "$review_status"
fi

review_status_file=$(mktemp)
review_elapsed_file=$(mktemp)
tests_status_file=$(mktemp)

(
  set +e
  review_started_at=$(date +%s)
  run_review
  status=$?
  elapsed=$(elapsed_since "$review_started_at")
  printf '%s\n' "$status" > "$review_status_file"
  printf '%s\n' "$elapsed" > "$review_elapsed_file"
) &
review_pid=$!

(
  set +e
  bash -lc "$parallel_tests"
  status=$?
  printf '%s\n' "$status" > "$tests_status_file"
) &
tests_pid=$!

wait "$review_pid" || true
wait "$tests_pid" || true

review_status=$(cat "$review_status_file")
review_elapsed_seconds=$(cat "$review_elapsed_file")
tests_status=$(cat "$tests_status_file")
rm -f "$review_status_file" "$review_elapsed_file" "$tests_status_file"

printf 'codex-review exit: %s\n' "$review_status"
printf 'tests exit: %s\n' "$tests_status"

if [[ "$review_status" != 0 || "$tests_status" != 0 ]]; then
  exit 1
fi

report_clean_review_or_fail
