#!/usr/bin/env bash
# git-sync — add/commit/pull --rebase/push.
#   git-sync                  alle Repos aus permissions.additionalDirectories
#   git-sync <dir> [message]  ein einzelnes Repo
# Safe: rebaset auf den Remote, kein Merge, kein force-push; Konflikte werden
# gemeldet (Rebase abgebrochen), nicht automatisch aufgelöst.
set -uo pipefail

ok()   { printf '\033[1;32m✓ %s\033[0m\n' "$*"; }   # green
note() { printf '\033[1;36m· %s\033[0m\n' "$*"; }   # cyan
warn() { printf '\033[1;33m⚠ %s\033[0m\n' "$*"; }   # yellow

sync_one() {
  local dir=$1 msg=${2:-} label branch ahead behind
  case "$dir" in "~") dir="$HOME" ;; "~/"*) dir="$HOME/${dir#"~/"}" ;; esac
  label=$(basename "$dir")

  if ! git -C "$dir" rev-parse --is-inside-work-tree >/dev/null 2>&1; then
    warn "$label: kein Git-Repo — übersprungen."; return 0
  fi
  branch=$(git -C "$dir" rev-parse --abbrev-ref HEAD)

  # add/commit
  if [ -n "$(git -C "$dir" status --porcelain)" ]; then
    git -C "$dir" add -A
    [ -z "$msg" ] && msg="git-sync: $(date '+%Y-%m-%d %H:%M')"
    if git -C "$dir" commit --quiet -m "$msg"; then
      note "$label: committed — $msg"
    else
      warn "$label: commit fehlgeschlagen."; return 0
    fi
  else
    note "$label: keine Änderungen."
  fi

  # pull --rebase, dann push
  if ! git -C "$dir" remote get-url origin >/dev/null 2>&1; then
    note "$label: kein origin-Remote — push übersprungen."; return 0
  fi

  if git -C "$dir" rev-parse --abbrev-ref --symbolic-full-name '@{u}' >/dev/null 2>&1; then
    git -C "$dir" fetch --quiet 2>/dev/null || true
    behind=$(git -C "$dir" rev-list --count 'HEAD..@{u}' 2>/dev/null || echo 0)
    if [ "$behind" -gt 0 ]; then
      if git -C "$dir" pull --rebase --quiet 2>/dev/null; then
        note "$label: $behind Commit(s) per Rebase integriert."
      else
        git -C "$dir" rebase --abort >/dev/null 2>&1 || true
        warn "$label: Pull/Rebase-Konflikt — bitte manuell lösen. Push übersprungen."; return 0
      fi
    fi
    ahead=$(git -C "$dir" rev-list --count '@{u}..HEAD' 2>/dev/null || echo 0)
    if [ "$ahead" -eq 0 ]; then
      note "$label: nichts zu pushen."
    elif git -C "$dir" push --quiet 2>/dev/null; then
      ok "$label: $ahead Commit(s) gepusht ($branch)."
    else
      warn "$label: push abgelehnt — Remote voraus. Manuell prüfen."
    fi
  else
    if git -C "$dir" push --quiet -u origin "$branch" 2>/dev/null; then
      ok "$label: Upstream gesetzt und gepusht ($branch)."
    else
      warn "$label: kein Upstream, push fehlgeschlagen — einmal manuell pushen."
    fi
  fi
}

# --- dispatch --------------------------------------------------------------
if [ $# -ge 1 ]; then
  sync_one "$1" "${2:-}"
  exit 0
fi

# ohne Argument: das aktuelle Projekt (cwd) selbst + seine eigenen additionalDirectories
dirs=$( { echo "$PWD"
          for f in .claude/settings.json .claude/settings.local.json; do
            [ -f "$f" ] && jq -r '.permissions.additionalDirectories[]?' "$f" 2>/dev/null
          done; } | sort -u)
while IFS= read -r d; do
  [ -n "$d" ] && sync_one "$d"
done <<< "$dirs"
