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

# Local-to-VPS deploy helper.
# Runs from your laptop: streams deploy_on_vps.sh over SSH and executes it remotely.

REMOTE_USER="${REMOTE_USER:-ubuntu}"
REMOTE_HOST="${REMOTE_HOST:-vps-4d8abcb7.vps.ovh.net}"
SSH_OPTS="${SSH_OPTS:--o StrictHostKeyChecking=no}"
BRANCH="${BRANCH:-main}"
APP_USER="${APP_USER:-myroadtrip}"
APP_DIR="${APP_DIR:-/srv/myroadtrip}"
REPO_DIR="${REPO_DIR:-$APP_DIR/repo}"
WEB_ROOT="${WEB_ROOT:-/srv/www/roadtripper}"
REPO_URL="${REPO_URL:-https://github.com/HectorLayak/RoadTripper.git}"
ENV_FILE="${ENV_FILE:-$APP_DIR/.env.production}"
PNPM_FLAGS="${PNPM_FLAGS:---frozen-lockfile --prefer-offline}"
NODE_OPTIONS="${NODE_OPTIONS:---max-old-space-size=4096}"
SYNC_ENVS="${SYNC_ENVS:-true}"
SSH_PASS="${SSH_PASS:-}"

SSH_WRAP=()
if [[ -n "$SSH_PASS" ]]; then
  if ! command -v sshpass >/dev/null 2>&1; then
    echo "sshpass is required when SSH_PASS is set. Install it (brew install hudochenkov/sshpass/sshpass or apt install sshpass)." >&2
    exit 1
  fi
  SSH_WRAP=(sshpass -p "$SSH_PASS")
  echo "💡 Tip: You are using a password. For better security and convenience, consider setting up SSH keys:"
  echo "  ssh-copy-id $REMOTE_USER@$REMOTE_HOST"
fi

REMOTE_ARGS=()

log() { printf '[%s] %s\n' "$(date +'%F %T')" "$*"; }
die() { printf '[%s] [error] %s\n' "$(date +'%F %T')" "$*" >&2; exit 1; }

usage() {
  cat <<'EOF'
Usage: deploy_from_local.sh [options] [-- <extra args for deploy_on_vps.sh>]
  --host <host>       VPS host (default: vps-4d8abcb7.vps.ovh.net)
  --user <user>       SSH user (default: ubuntu)
  --branch <name>     Git branch to deploy (default: main)
  --app-user <name>   App user on VPS (default: myroadtrip)
  --app-dir <path>    App root on VPS (default: /srv/myroadtrip)
  --repo-dir <path>   Repo path on VPS (default: /srv/myroadtrip/repo)
  --web-root <path>   Web root on VPS (default: /srv/www/roadtripper)
  --env-file <path>   Env file path on VPS (default: /srv/myroadtrip/.env.production)
  --pnpm-flags "<...>" Override pnpm install flags (passed through)
  --skip-web          Skip web build + sync
  --skip-api          Skip API build
  --web-only          Build/sync web only
  --api-only          Build API only
  --skip-install      Skip pnpm install
  --no-restart        Skip service restarts
  --no-pull           Do not git pull
  --no-clone          Do not clone if missing
  --sync-envs         Push local env/serviceAccount/fb dir via sync_envs.sh before deploy (default: on)
  --no-sync-envs      Skip env sync
  --ssh-opts "<opts>" Extra ssh options (quoted)
  -h, --help          Show help
Notes:
  - This script streams scripts/vps/deploy_on_vps.sh to the server; it does not rely on it being present.
  - To pass additional flags to the remote deployer, place them after -- (e.g. -- --pnpm-flags "--prefer-offline").
EOF
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --host) REMOTE_HOST="$2"; shift 2 ;;
    --user) REMOTE_USER="$2"; shift 2 ;;
    --branch) BRANCH="$2"; shift 2 ;;
    --app-user) APP_USER="$2"; shift 2 ;;
    --app-dir) APP_DIR="$2"; shift 2 ;;
    --repo-dir) REPO_DIR="$2"; shift 2 ;;
    --web-root) WEB_ROOT="$2"; shift 2 ;;
    --env-file) ENV_FILE="$2"; shift 2 ;;
    --pnpm-flags) PNPM_FLAGS="$2"; shift 2 ;;
    --skip-web) REMOTE_ARGS+=(--skip-web); shift ;;
    --skip-api) REMOTE_ARGS+=(--skip-api); shift ;;
    --web-only) REMOTE_ARGS+=(--web-only); shift ;;
    --api-only) REMOTE_ARGS+=(--api-only); shift ;;
    --skip-install) REMOTE_ARGS+=(--skip-install); shift ;;
    --no-restart) REMOTE_ARGS+=(--no-restart); shift ;;
    --no-pull) REMOTE_ARGS+=(--no-pull); shift ;;
    --no-clone) REMOTE_ARGS+=(--no-clone); shift ;;
    --sync-envs) SYNC_ENVS=true; shift ;;
    --no-sync-envs) SYNC_ENVS=false; shift ;;
    --sync-code) SYNC_CODE=true; shift ;;
    --ssh-opts) SSH_OPTS="$2"; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    --) shift; REMOTE_ARGS+=("$@"); break ;;
    *) die "unknown argument: $1" ;;
  esac
done

require_cmd() { command -v "$1" >/dev/null 2>&1 || die "missing required command: $1"; }
require_cmd ssh
require_cmd tar

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
# Go to repo root
REPO_ROOT="$(cd "$SCRIPT_DIR/../../" && pwd)"

REMOTE_DEPLOY="$SCRIPT_DIR/deploy_on_vps.sh"
[[ -f "$REMOTE_DEPLOY" ]] || die "missing deploy script at $REMOTE_DEPLOY"

if [[ "${SYNC_CODE:-false}" == "true" ]]; then
  log "Syncing LOCAL CODE to $REMOTE_HOST (bypassing git pull)"
  
  # Create a clean tarball of the repo, excluding heavy/ignored stuff
  CODE_TAR=$(mktemp)
  log "Creating code bundle from $REPO_ROOT..."
  
  # Use tar with excludes
  # We exclude .git, node_modules, dist, .turbo, .env files (handled by sync_envs)
  # Use subshell to cd without affecting script
  (
    cd "$REPO_ROOT"
    tar -czf "$CODE_TAR" \
      --exclude='.git' \
      --exclude='node_modules' \
      --exclude='dist' \
      --exclude='.turbo' \
      --exclude='.DS_Store' \
      --exclude='coverage' \
      --exclude='.env*' \
      --exclude='*.log' \
      .
  )

  REMOTE_CODE_TMP="/tmp/code-bundle-$(date +%s).tgz"
  
  log "Uploading code bundle..."
  if [[ ${#SSH_WRAP[@]} -gt 0 ]]; then
    "${SSH_WRAP[@]}" scp $SSH_OPTS "$CODE_TAR" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_CODE_TMP"
  else
    scp $SSH_OPTS "$CODE_TAR" "$REMOTE_USER@$REMOTE_HOST:$REMOTE_CODE_TMP"
  fi
  
  rm -f "$CODE_TAR"
  
  log "Extracting code on server..."
  # We extract to REPO_DIR and fix permissions
  # We assume REPO_DIR exists or will be created
  ssh $SSH_OPTS "$REMOTE_USER@$REMOTE_HOST" "
    sudo install -d -m 755 -o $APP_USER -g $APP_USER '$REPO_DIR'
    
    # Extract to temp dir first to avoid partial state
    TMP_EXTRACT=\$(mktemp -d)
    tar -xzf '$REMOTE_CODE_TMP' -C \"\$TMP_EXTRACT\"
    
    # Sync content to REPO_DIR using rsync locally on server if available, or just cp
    # We use cp -rT to merge/overwrite
    echo 'Updating repo files...'
    sudo cp -rf \"\$TMP_EXTRACT/.\" '$REPO_DIR/'
    
    # Fix permissions
    sudo chown -R $APP_USER:$APP_USER '$REPO_DIR'
    
    # Cleanup
    rm -rf \"\$TMP_EXTRACT\" '$REMOTE_CODE_TMP'
  "
  
  # Disable git pull in the remote script since we just synced code
  REMOTE_ARGS+=(--no-pull)
fi

if [[ "$SYNC_ENVS" == "true" ]]; then
  log "Syncing env files to $REMOTE_HOST"
  REMOTE_BASE="$APP_DIR" REMOTE_REPO="$REPO_DIR" REMOTE_HOST="$REMOTE_HOST" REMOTE_USER="$REMOTE_USER" SSH_OPTS="$SSH_OPTS" SSH_PASS="$SSH_PASS" \
    "$SCRIPT_DIR/sync_envs.sh"
fi

env_prefix() {
  local pairs=("$@")
  local out=""
  for pair in "${pairs[@]}"; do
    local key="${pair%%=*}"
    local val="${pair#*=}"
    out+=$(printf "%s=%q " "$key" "$val")
  done
  printf "%s" "$out"
}

REMOTE_ENV=(
  "APP_USER=$APP_USER"
  "APP_DIR=$APP_DIR"
  "REPO_DIR=$REPO_DIR"
  "WEB_ROOT=$WEB_ROOT"
  "REPO_URL=$REPO_URL"
  "ENV_FILE=$ENV_FILE"
  "BRANCH=$BRANCH"
  "PNPM_FLAGS=$PNPM_FLAGS"
  "NODE_OPTIONS=$NODE_OPTIONS"
  "API_VIA_DOCKER=true"
)

REMOTE_ARGS_Q=""
if [[ ${#REMOTE_ARGS[@]} -gt 0 ]]; then
  REMOTE_ARGS_Q="$(printf " %q" "${REMOTE_ARGS[@]}")"
fi

CMD="$(env_prefix "${REMOTE_ENV[@]}")bash -s --${REMOTE_ARGS_Q}"

log "Deploying to $REMOTE_USER@$REMOTE_HOST (branch=$BRANCH)"
if [[ ${#SSH_WRAP[@]} -gt 0 ]]; then
  "${SSH_WRAP[@]}" ssh $SSH_OPTS "$REMOTE_USER@$REMOTE_HOST" "$CMD" < "$REMOTE_DEPLOY"
else
  ssh $SSH_OPTS "$REMOTE_USER@$REMOTE_HOST" "$CMD" < "$REMOTE_DEPLOY"
fi
log "✅ Remote deploy finished"
