#!/usr/bin/env bash

set -euo pipefail

ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
SSH_KEY_DEFAULT="${HOME}/.ssh/vps_ovh_cd035e9a_ed25519"
SSH_USER_DEFAULT="ubuntu"
SSH_HOST_DEFAULT="142.44.210.180"

usage() {
  cat <<'EOF'
Usage:
  ./scripts/deploy-vps.sh <prod|preprod> [--skip-check] [--skip-build]

Examples:
  ./scripts/deploy-vps.sh preprod
  ./scripts/deploy-vps.sh prod

Behavior:
  - synchronise les sources utiles vers le VPS
  - exécute le check TypeScript local (sauf --skip-check)
  - exécute le build local (sauf --skip-build)
  - reconstruit et redémarre l'application distante
  - utilise explicitement le bon fichier d'environnement par cible
EOF
}

if [[ "${1:-}" == "-h" || "${1:-}" == "--help" ]]; then
  usage
  exit 0
fi

TARGET="${1:-}"
if [[ -z "${TARGET}" ]]; then
  usage
  exit 1
fi
shift || true

RUN_CHECK=1
RUN_BUILD=1
USE_MAINTENANCE_FLAG="${USE_MAINTENANCE_FLAG:-0}"

while [[ $# -gt 0 ]]; do
  case "$1" in
    --skip-check)
      RUN_CHECK=0
      ;;
    --skip-build)
      RUN_BUILD=0
      ;;
    -h|--help)
      usage
      exit 0
      ;;
    *)
      echo "Option inconnue: $1" >&2
      usage
      exit 1
      ;;
  esac
  shift
done

case "${TARGET}" in
  prod)
    REMOTE_DIR="/home/${SSH_USER_DEFAULT}/portail-associations"
    REMOTE_DEPLOY_CMD='cd /home/ubuntu/portail-associations && docker compose --env-file .env up -d --build app'
    POST_CHECK_URL='https://www.portail-association973.com'
    ;;
  preprod)
    REMOTE_DIR="/home/${SSH_USER_DEFAULT}/portail-associations-preprod"
    REMOTE_DEPLOY_CMD='cd /home/ubuntu/portail-associations-preprod/deployments/preprod && docker compose --env-file .env up -d --build app'
    POST_CHECK_URL='https://preprod.portail-association973.com'
    ;;
  *)
    echo "Cible invalide: ${TARGET}" >&2
    usage
    exit 1
    ;;
esac

SSH_KEY="${SSH_KEY:-${SSH_KEY_DEFAULT}}"
SSH_USER="${SSH_USER:-${SSH_USER_DEFAULT}}"
SSH_HOST="${SSH_HOST:-${SSH_HOST_DEFAULT}}"
SSH_TARGET="${SSH_USER}@${SSH_HOST}"
SSH_CMD=(ssh -i "${SSH_KEY}" -o BatchMode=yes -o ConnectTimeout=10 "${SSH_TARGET}")
RSYNC_SSH="ssh -i ${SSH_KEY} -o BatchMode=yes -o ConnectTimeout=10"
POST_CHECK_HEALTH_URL="${POST_CHECK_URL}/health/ready"

SYNC_ITEMS=(
  "${ROOT_DIR}/client"
  "${ROOT_DIR}/server"
  "${ROOT_DIR}/shared"
  "${ROOT_DIR}/drizzle"
  "${ROOT_DIR}/docs"
  "${ROOT_DIR}/deployments"
  "${ROOT_DIR}/scripts"
  "${ROOT_DIR}/patches"
  "${ROOT_DIR}/package.json"
  "${ROOT_DIR}/pnpm-lock.yaml"
  "${ROOT_DIR}/Dockerfile"
  "${ROOT_DIR}/docker-compose.yml"
  "${ROOT_DIR}/vite.config.ts"
  "${ROOT_DIR}/tsconfig.json"
  "${ROOT_DIR}/components.json"
  "${ROOT_DIR}/drizzle.config.ts"
  "${ROOT_DIR}/MAIL_PROVIDERS.md"
)

echo "==> Vérification SSH (${SSH_TARGET})"
"${SSH_CMD[@]}" 'echo SSH_OK >/dev/null'

remote_maintenance() {
  local mode="$1"
  "${SSH_CMD[@]}" "cd ${REMOTE_DIR} && MAINTENANCE_FLAG_PATH=${REMOTE_DIR}/uploads/system/maintenance.flag ./scripts/maintenance-flag.sh ${mode}"
}

wait_for_http_200() {
  local url="$1"
  local label="$2"
  local max_attempts="${3:-20}"
  local delay_seconds="${4:-3}"
  local attempt=1
  while [[ "${attempt}" -le "${max_attempts}" ]]; do
    local code
    code="$(curl -k -s -o /dev/null -w "%{http_code}" -m 20 "${url}" || true)"
    echo "   - ${label} tentative ${attempt}/${max_attempts} -> ${code}"
    if [[ "${code}" == "200" ]]; then
      return 0
    fi
    sleep "${delay_seconds}"
    attempt=$((attempt + 1))
  done
  return 1
}

if [[ "${RUN_CHECK}" -eq 1 ]]; then
  echo "==> TypeScript check local"
  (cd "${ROOT_DIR}" && corepack pnpm check)
fi

if [[ "${RUN_BUILD}" -eq 1 ]]; then
  echo "==> Build local"
  (cd "${ROOT_DIR}" && corepack pnpm build)
fi

echo "==> Synchronisation des sources vers ${REMOTE_DIR}"
rsync -az --delete \
  --exclude '.git/' \
  --exclude 'node_modules/' \
  --exclude 'dist/' \
  --exclude 'uploads/' \
  --exclude '.env' \
  -e "${RSYNC_SSH}" \
  "${SYNC_ITEMS[@]}" \
  "${SSH_TARGET}:${REMOTE_DIR}/"

if [[ "${USE_MAINTENANCE_FLAG}" == "1" ]]; then
  echo "==> Activation du mode maintenance"
  remote_maintenance on
fi

echo "==> Déploiement ${TARGET}"
"${SSH_CMD[@]}" "${REMOTE_DEPLOY_CMD}"

echo "==> Attente de disponibilité applicative (${POST_CHECK_HEALTH_URL})"
wait_for_http_200 "${POST_CHECK_HEALTH_URL}" "health" 25 3

if [[ "${USE_MAINTENANCE_FLAG}" == "1" ]]; then
  echo "==> Désactivation du mode maintenance"
  remote_maintenance off
fi

echo "==> Contrôle HTTP ${POST_CHECK_URL}"
wait_for_http_200 "${POST_CHECK_URL}" "home" 10 2
curl -I -k -m 20 "${POST_CHECK_HEALTH_URL}"

echo "==> Déploiement ${TARGET} terminé"
