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

REPO_ROOT="${ZHCTPROMPT_REPO_ROOT:-/opt/zhct/zhctprompt}"
AUTH_ENV="${ZHCTPROMPT_AUTH_ENV:-/opt/zhct/local/yunxiao.env}"
BRANCH="${ZHCTPROMPT_SYNC_BRANCH:-master}"
LOCK_FILE="${ZHCTPROMPT_SYNC_LOCK_FILE:-/run/lock/zhctprompt-sync.lock}"
ASKPASS="$REPO_ROOT/deploy/digital-employee/codeup-askpass.sh"

log() {
  printf '[%s] %s\n' "$(date '+%Y-%m-%d %H:%M:%S %z')" "$*"
}

fail() {
  log "ERROR: $*" >&2
  exit 1
}

[[ -d "$REPO_ROOT/.git" ]] || fail "not a Git repository: $REPO_ROOT"
[[ -x "$ASKPASS" ]] || fail "missing executable askpass helper: $ASKPASS"
command -v flock >/dev/null || fail "flock is not installed"

if [[ -r "$AUTH_ENV" ]]; then
  # shellcheck disable=SC1090
  source "$AUTH_ENV"
fi
if [[ -n "${YUNXIAO_GIT_USERNAME:-}" && -n "${YUNXIAO_GIT_TOKEN:-}" ]]; then
  export GIT_ASKPASS="$ASKPASS"
fi
export GIT_TERMINAL_PROMPT=0

exec 9>"$LOCK_FILE"
flock -n 9 || fail "another sync process is running"

cd "$REPO_ROOT"
[[ "$(git branch --show-current)" == "$BRANCH" ]] || fail "expected branch $BRANCH"
[[ ! -e .git/MERGE_HEAD && ! -d .git/rebase-merge && ! -d .git/rebase-apply ]] \
  || fail "repository has an unfinished merge or rebase"
git config user.name >/dev/null || fail "Git user.name is not configured"
git config user.email >/dev/null || fail "Git user.email is not configured"

blocked_path_regex='(^|/)(config/local|\.env($|\.)|[^/]*credentials[^/]*|[^/]*secret[^/]*)'
changed_paths="$(git status --porcelain=v1 --untracked-files=all | cut -c4-)"
if [[ -n "$changed_paths" ]] && grep -Eiq "$blocked_path_regex" <<<"$changed_paths"; then
  fail "refusing to commit a credential-like path"
fi

if [[ -n "$changed_paths" ]]; then
  git add -A
  if ! git diff --cached --quiet; then
    git diff --cached --check
    git commit -m "chore: persist cloud knowledge $(date '+%Y-%m-%d %H:%M')"
    log "committed local knowledge changes"
  fi
fi

git fetch --prune origin "$BRANCH"
remote_ref="origin/$BRANCH"

if git diff --quiet HEAD "$remote_ref"; then
  log "already up to date"
elif git merge-base --is-ancestor HEAD "$remote_ref"; then
  git merge --ff-only "$remote_ref"
  log "fast-forwarded to $remote_ref"
elif git merge-base --is-ancestor "$remote_ref" HEAD; then
  log "local branch is ahead of $remote_ref; no remote update to merge"
else
  if git merge --no-edit "$remote_ref"; then
    git diff --check
    log "merged remote changes without rewriting history"
  else
    git merge --abort || true
    fail "remote merge conflicted; repository restored to its pre-merge state"
  fi
fi

log "sync complete at $(git rev-parse --short HEAD)"

if [[ "${ZHCTPROJECT_SYNC_ENABLED:-1}" == "1" ]]; then
  log "pulling clean zhctproject repositories without committing local changes"
  "$REPO_ROOT/control/scripts/sync-zhctproject-repos.sh"
fi

log "all scheduled repository synchronization completed"
