#!/usr/bin/env bash
# =============================================================================
# onx-git-pull — Pull latest commits in an existing checkout
#
# Input:
#   { "username":"onx_xxxx", "path":"/home/<user>/repos/foo", "branch":"main" }
#
# Output:
#   { "path":"...", "branch":"...",
#     "last_commit_sha":"...", "last_commit_message":"...",
#     "last_commit_author":"...", "last_commit_date":"...",
#     "files_changed": N, "ahead":0, "behind":0 }
#
# Exit codes: 0=ok 1=invalid-input 2=preflight-fail 3=execution-fail
# =============================================================================

set -euo pipefail

SCRIPT_DIR="$(dirname "$(readlink -f "$0")")"
source "${SCRIPT_DIR}/_lib/common.sh"

require_cmd jq
require_cmd git

INPUT=$(cat)
onx_require_json "${INPUT}"

USERNAME=$(onx_json_get "${INPUT}" "username")
DEST=$(onx_json_get    "${INPUT}" "path")
BRANCH=$(onx_json_get  "${INPUT}" "branch" "")

onx_validate_username "${USERNAME}"
id "${USERNAME}" &>/dev/null || onx_die 2 "Linux user does not exist: ${USERNAME}"
[[ -n "${DEST}" ]] || onx_die 1 "path is required"
case "${DEST}" in
    "/home/${USERNAME}"|"/home/${USERNAME}/"*) : ;;
    *) onx_die 1 "path must live under /home/${USERNAME}" ;;
esac
[[ "${DEST}" == *..* ]] && onx_die 1 "path may not contain '..'"
[[ -d "${DEST}/.git" ]] || onx_die 2 "not a git repo: ${DEST}"

# Record old HEAD for diff stat
OLD_SHA=$(su -s /bin/bash "${USERNAME}" -c "git -C '${DEST}' rev-parse HEAD 2>/dev/null" || echo "")

if [[ -n "${BRANCH}" ]]; then
    su -s /bin/bash "${USERNAME}" -c \
        "git -C '${DEST}' checkout '${BRANCH}'" >/dev/null 2>&1 || true
fi

su -s /bin/bash "${USERNAME}" -c \
    "git -C '${DEST}' fetch --all --prune && git -C '${DEST}' pull --ff-only" \
    >/dev/null 2>&1 || onx_die 3 "git pull failed in ${DEST}"

NEW_SHA=$(su -s /bin/bash "${USERNAME}" -c "git -C '${DEST}' rev-parse HEAD 2>/dev/null" || echo "")
BR=$(su -s /bin/bash "${USERNAME}" -c "git -C '${DEST}' rev-parse --abbrev-ref HEAD 2>/dev/null" || echo "main")
MSG=$(su -s /bin/bash "${USERNAME}" -c "git -C '${DEST}' log -1 --pretty=%s 2>/dev/null" || echo "")
AUTHOR=$(su -s /bin/bash "${USERNAME}" -c "git -C '${DEST}' log -1 --pretty=%an 2>/dev/null" || echo "")
ISO=$(su -s /bin/bash "${USERNAME}" -c "git -C '${DEST}' log -1 --pretty=%cI 2>/dev/null" || echo "")

FILES_CHANGED=0
if [[ -n "${OLD_SHA}" && -n "${NEW_SHA}" && "${OLD_SHA}" != "${NEW_SHA}" ]]; then
    FILES_CHANGED=$(su -s /bin/bash "${USERNAME}" -c \
        "git -C '${DEST}' diff --name-only ${OLD_SHA} ${NEW_SHA} 2>/dev/null | wc -l" || echo 0)
fi

# Ahead/behind vs upstream
AHEAD_BEHIND=$(su -s /bin/bash "${USERNAME}" -c \
    "git -C '${DEST}' rev-list --left-right --count HEAD...@{upstream} 2>/dev/null" || echo "0	0")
AHEAD=$(echo "${AHEAD_BEHIND}" | awk '{print $1}'); AHEAD=${AHEAD:-0}
BEHIND=$(echo "${AHEAD_BEHIND}" | awk '{print $2}'); BEHIND=${BEHIND:-0}

MSG_J=$(printf '%s' "${MSG}"    | jq -Rs '.')
AUT_J=$(printf '%s' "${AUTHOR}" | jq -Rs '.')
ISO_J=$(printf '%s' "${ISO}"    | jq -Rs '.')

onx_log "git-pull: ${DEST} ${OLD_SHA:0:7}..${NEW_SHA:0:7} changed=${FILES_CHANGED}"

printf '{"path":"%s","branch":"%s","last_commit_sha":"%s","last_commit_message":%s,"last_commit_author":%s,"last_commit_date":%s,"files_changed":%s,"ahead":%s,"behind":%s}\n' \
    "${DEST}" "${BR}" "${NEW_SHA}" "${MSG_J}" "${AUT_J}" "${ISO_J}" "${FILES_CHANGED}" "${AHEAD}" "${BEHIND}"
