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

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

Options:
  --mode auto|local|branch|commit
                              Target selection. Default: auto.
  --base REF                 Base ref for branch review. Default: PR base or origin/main.
  --commit REF               Commit ref for commit review. Default: HEAD.
  --codex-bin PATH           Codex binary. Default: codex.
  --full-access              Keep yolo/full-access mode enabled. Default.
  --no-yolo                  Run nested Codex review with normal 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>
  commit  codex review --commit <commit>
  auto    dirty tree -> local, else PR/current branch -> branch
EOF
}

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

while [[ $# -gt 0 ]]; do
  case "$1" in
    --mode)
      mode=${2:-}
      shift 2
      ;;
    --base)
      base_ref=${2:-}
      shift 2
      ;;
    --commit)
      commit_ref=${2:-}
      shift 2
      ;;
    --codex-bin)
      codex_bin=${2:-}
      shift 2
      ;;
    --full-access)
      yolo=1
      shift
      ;;
    --no-yolo)
      yolo=0
      shift
      ;;
    --output)
      output=${2:-}
      shift 2
      ;;
    --parallel-tests)
      parallel_tests=${2:-}
      shift 2
      ;;
    --dry-run)
      dry_run=true
      shift
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      usage >&2
      exit 2
      ;;
  esac
done

case "$yolo" in
  0|false|False|FALSE|no|No|NO|off|Off|OFF) ;;
  *) codex_args+=(--dangerously-bypass-approvals-and-sandbox) ;;
esac

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

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" == commit ]]; then
  review_kind=commit
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[@]}" review --uncommitted)
elif [[ "$review_kind" == commit ]]; then
  review_cmd=("$codex_bin" "${codex_args[@]}" review --commit "$commit_ref")
else
  review_cmd=("$codex_bin" "${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() {
  grep -Eq '\[P[0-3]\]' "$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
