#!/usr/bin/env bash
# Minimal rsync stand-in for Windows Git Bash (tar-over-ssh).
# Supports the flags used by server-dev/sync-submodules-rsync.sh:
#   rsync -az [--delete] [--exclude PATTERN ...] SRC/ HOST:DEST/
set -euo pipefail

DELETE=false
EXCLUDES=()
ARGS=()

while (($#)); do
  case "$1" in
    -az|-a|-z|-v|-q|-P|--progress) shift ;;
    --delete) DELETE=true; shift ;;
    --exclude)
      EXCLUDES+=("$2"); shift 2 ;;
    --exclude=*)
      EXCLUDES+=("${1#--exclude=}"); shift ;;
    -*)
      # ignore unknown short/long flags used by callers
      shift ;;
    *)
      ARGS+=("$1"); shift ;;
  esac
done

if ((${#ARGS[@]} < 2)); then
  echo "rsync-shim: need SRC and DEST" >&2
  exit 1
fi

SRC="${ARGS[0]}"
DEST="${ARGS[1]}"

# Git Bash /d/foo → Windows D:/foo (OpenSSH scp 용)
to_win_path() {
  local p="$1"
  if [[ "${p}" =~ ^/([a-zA-Z])/(.*)$ ]]; then
    local drive rest
    drive="$(echo "${BASH_REMATCH[1]}" | tr 'a-z' 'A-Z')"
    rest="${BASH_REMATCH[2]}"
    echo "${drive}:/${rest}"
  else
    echo "${p}"
  fi
}

copy_file_remote() {
  local src_file="$1"
  local dest="$2"
  local win_src
  win_src="$(to_win_path "${src_file}")"
  if [[ -f "${win_src}" || -f "${src_file}" ]]; then
    local local_src="${src_file}"
    [[ -f "${win_src}" ]] && local_src="${win_src}"
    scp -o BatchMode=yes -q "${local_src}" "${dest}" && return 0
  fi
  # fallback: tar stream single file
  local base dir
  base="$(basename "${src_file}")"
  dir="$(cd "$(dirname "${src_file}")" && pwd)"
  local host="${dest%%:*}"
  local remote="${dest#*:}"
  local remote_dir remote_base
  if [[ "${remote}" == */ ]]; then
    remote_dir="${remote%/}"
    remote_base="${base}"
  else
    remote_dir="$(dirname "${remote}")"
    remote_base="$(basename "${remote}")"
  fi
  ssh -o BatchMode=yes "${host}" "mkdir -p '${remote_dir}'"
  tar -C "${dir}" -cf - "${base}" \
    | ssh -o BatchMode=yes "${host}" "tar -C '${remote_dir}' -xf - && if [[ '${remote_base}' != '${base}' ]]; then mv '${remote_dir}/${base}' '${remote_dir}/${remote_base}'; fi"
}

# file → file copy (overlay yml etc.)
if [[ -f "${SRC}" && "${DEST}" == *:* ]]; then
  copy_file_remote "${SRC}" "${DEST}"
  exit 0
fi

# normalize trailing slash semantics like rsync SRC/
SRC_DIR="${SRC%/}"
if [[ ! -d "${SRC_DIR}" ]]; then
  # allow copying a single file into a remote dir
  if [[ -f "${SRC_DIR}" ]]; then
    copy_file_remote "${SRC_DIR}" "${DEST}"
    exit 0
  fi
  echo "rsync-shim: source not found: ${SRC}" >&2
  exit 1
fi

if [[ "${DEST}" != *:* ]]; then
  echo "rsync-shim: only remote DEST (host:path) supported" >&2
  exit 1
fi

HOST="${DEST%%:*}"
REMOTE_PATH="${DEST#*:}"
REMOTE_PATH="${REMOTE_PATH%/}"

TAR_EXCLUDES=()
for pat in "${EXCLUDES[@]}"; do
  # tar 의 --exclude 는 'node_modules/' 처럼 슬래시로 끝나면 디렉터리에 매칭되지 않는다.
  # (rsync 문법 그대로 넘기면 node_modules 가 통째로 전송돼 메모리 부족으로 죽는다)
  TAR_EXCLUDES+=(--exclude "${pat%/}")
done

ssh -o BatchMode=yes "${HOST}" "mkdir -p '${REMOTE_PATH}'"

if $DELETE; then
  # wipe remote dir contents then unpack (approx --delete)
  # 서버 public-* 등이 root/docker 소유일 수 있어 실패해도 이어서 덮어쓴다
  ssh -o BatchMode=yes "${HOST}" \
    "chmod -R u+w '${REMOTE_PATH}' 2>/dev/null || true; \
     find '${REMOTE_PATH}' -mindepth 1 -maxdepth 1 -exec rm -rf {} + 2>/dev/null || true" \
    || true
fi

# shellcheck disable=SC2086
tar -C "${SRC_DIR}" "${TAR_EXCLUDES[@]}" -cf - . \
  | ssh -o BatchMode=yes "${HOST}" "tar -C '${REMOTE_PATH}' -xf -"

echo "rsync-shim: synced ${SRC_DIR}/ -> ${HOST}:${REMOTE_PATH}/"
