#!/usr/bin/env bash
# loop-review：查询 PR 上「最新一轮 AI review 审查的 commit_id」。
# 供 SKILL.md 轮询/判断流程调用，把易错的 jq 转义逻辑收敛到独立脚本，便于测试与维护。
#
# 用法：
#   bash check-review.sh <REPO> <PR>   # 输出最新 review 审查的 commit_id（完整 SHA），无 review 输出空
#
# 依赖：
#   - gh CLI（已登录且有权限读该仓库）
#   - jq >= 1.6：capture（1.5+）、try/catch（1.6+）、-s slurp；本地旧版 jq 会语法报错
#   - 说明：GitHub GET /pulls/{n}/reviews 返回按创建时间升序，但显式 sort_by(.submitted_at) 取最后一条最稳。

set -euo pipefail

REPO="${1:?用法: bash check-review.sh <REPO> <PR>}"
PR="${2:?用法: bash check-review.sh <REPO> <PR>}"

# $REPO / $PR 直接拼入 URL 路径与 jq filter 字符串，必须先校验格式：
#   - $REPO 形如 owner/name，仅含字母数字、点、下划线、中划线
#   - $PR 必须是纯数字
# 避免传参含特殊字符时破坏 jq 语法或让请求打到意外路径。
[[ "$REPO" =~ ^[a-zA-Z0-9._-]+/[a-zA-Z0-9._-]+$ ]] || { echo "错误: REPO 格式非法（应为 owner/repo，收到: ${REPO}）" >&2; exit 1; }
[[ "$PR" =~ ^[0-9]+$ ]] || { echo "错误: PR 必须是纯数字（收到: ${PR}）" >&2; exit 1; }

# jq 版本校验：下方 filter 用了 try/catch（jq 1.6+ 语法），Ubuntu 20.04 默认 jq 1.5 会直接语法报错，
# 且报错信息晦涩难定位。启动时主动检测版本，给明确提示而不是等 jq 报错。
if ! command -v jq >/dev/null 2>&1; then
  echo "错误: 未找到 jq（脚本依赖 jq >= 1.6，请先安装）" >&2
  exit 1
fi
# jq --version 保证单行输出（如 jq-1.6），grep -oE 最多匹配一行，head -1 冗余，直接省略
JQ_VERSION="$(jq --version 2>/dev/null | grep -oE '[0-9]+(\.[0-9]+)+')"
if [ -z "$JQ_VERSION" ]; then
  echo "错误: 无法从 jq --version 解析出版本号（输出: $(jq --version 2>&1)），脚本依赖 jq >= 1.6" >&2
  exit 1
fi
# 版本比较：拆分主/次版本号后直接做整数比较（review 建议，替代反直觉的 awk exit 语义）。
# 直白逻辑：主版本 >1，或主版本==1 且次版本>=6 → 满足要求，不进入报错分支。
JQ_MAJOR="${JQ_VERSION%%.*}"
JQ_MINOR_REMAINDER="${JQ_VERSION#*.}"
JQ_MINOR="${JQ_MINOR_REMAINDER%%.*}"
if [ "$JQ_MAJOR" -lt 1 ] || { [ "$JQ_MAJOR" -eq 1 ] && [ "$JQ_MINOR" -lt 6 ]; }; then
  echo "错误: jq 版本过低（当前 ${JQ_VERSION}，需要 >= 1.6）：try/catch 语法不可用" >&2
  exit 1
fi

# ⚠️ 分页处理：gh api --paginate 不带 --jq，把每页原始 JSON 输出（多页 = 多个数组流），
#    再管道给 jq -s（slurp）合并成单一数组后统一筛选排序。
#    --paginate --jq 会「每页独立执行 jq」，review 超过一页时输出多行 commit_id，调用方误判。
# ⚠️ jq filter 用单引号包裹（无 shell 变量插值），内部反引号/双引号无需 shell 转义，避免转义脆弱性。
# `-r` raw 输出：去掉 JSON 字符串引号，调用方 `[ "$LATEST" = "$CUR" ]` 才能比较成功。
# `(add // [])`：gh api 完全无输出（如 PR 不存在/无任何 review）时，slurp 的输入为空流，
#    add 得 null，后续 select 会报「Cannot iterate over null」；// [] 让空输入变空数组。
# `select($cid | type == "string" and length == 40)`：只保留完整 40 位 SHA 的 review。
#    优先用 commit_id 字段（GitHub API 保证完整），fallback 解析 body「审查 commit」时可能拿到短 SHA，
#    短 SHA 与调用方 git rev-parse HEAD（完整 40 位）比较永远不匹配 → 空等；这里过滤掉非 40 位值，
#    宁可判定「未审查」也不误判「已审查」。
gh api "repos/$REPO/pulls/$PR/reviews?per_page=100" --paginate | jq -rs '
  (add // []) | [.[] | select(.user.login == "github-actions[bot]" and .submitted_at != null) |
   (.commit_id // (try (.body | capture("审查 commit: `(?<h>[0-9a-f]+)`") | .h) catch null)) as $cid |
   select($cid | type == "string" and length == 40) |
   {commit_id: $cid, submitted_at}] |
  sort_by(.submitted_at) | .[-1].commit_id // empty
'
