#!/usr/bin/env bash
# ==============================================================================
# news monorepo - otomatik deploy scripti
# ------------------------------------------------------------------------------
# Akis: git fetch -> degisen proje tespiti -> sadece degisen site(ler)de
#       yarn build -> pm2 restart -> saglik kontrolu. Hata olursa ROLLBACK.
#
# Calisma kullanicisi : ubuntu  (sudo KULLANMAZ; /var/www/html ubuntu'ya ait olmali)
# Tetikleyici         : adnanh/webhook -> webhook-trigger.sh -> bu script
#
# GUVENLIK/GERI DONUS:
#   - .env / node_modules / .next gitignore'da; 'git reset --hard' bunlara DOKUNMAZ.
#   - Build veya saglik kontrolu basarisiz olursa onceki commit'e otomatik donulur.
#   - Ayni anda ikinci bir deploy calismaz (flock).
# ==============================================================================

set -uo pipefail

# ----------------------------- Yapilandirma -----------------------------------
REPO_DIR="/var/www/html"
BRANCH="main"
LOG_DIR="${REPO_DIR}/deploy/logs"
LOCK_FILE="/tmp/news-deploy.lock"

# Klasor -> pm2 process adi (dikkat: isimler klasorle birebir ayni degil)
declare -A APP_NAME=(
  [trsondakika]="trsondakika"
  [borsauzmani]="borsauzmani"
  [ieconomy]="ieconmy"
  [trensonhaber]="trensondakika"
)
# Klasor -> lokal port (saglik kontrolu icin)
declare -A APP_PORT=(
  [trsondakika]="3001"
  [borsauzmani]="3004"
  [ieconomy]="3000"
  [trensonhaber]="3003"
)
# ------------------------------------------------------------------------------

# nvm / node / yarn / pm2 PATH'e alinir (systemd/non-login shell icin sart)
export HOME="${HOME:-/home/ubuntu}"
export NVM_DIR="${HOME}/.nvm"
# shellcheck disable=SC1091
[ -s "${NVM_DIR}/nvm.sh" ] && . "${NVM_DIR}/nvm.sh" >/dev/null 2>&1 || true

mkdir -p "${LOG_DIR}"
TS="$(date +%F_%H-%M-%S)"
LOG_FILE="${LOG_DIR}/deploy_${TS}.log"

log(){ echo "[$(date '+%F %T')] $*" | tee -a "${LOG_FILE}"; }
die(){ log "HATA: $*"; exit 1; }

# --------------------------- Tekil calisma kilidi -----------------------------
exec 9>"${LOCK_FILE}" || die "kilit dosyasi acilamadi"
if ! flock -n 9; then
  echo "[$(date '+%F %T')] Baska bir deploy calisiyor, cikiliyor." | tee -a "${LOG_FILE}"
  exit 0
fi

command -v yarn >/dev/null 2>&1 || die "yarn bulunamadi (PATH/nvm?)"
command -v pm2  >/dev/null 2>&1 || die "pm2 bulunamadi (PATH/nvm?)"
command -v git  >/dev/null 2>&1 || die "git bulunamadi"

cd "${REPO_DIR}" || die "${REPO_DIR} bulunamadi"

log "================ Deploy basladi (${TS}) ================"

PREV_SHA="$(git rev-parse HEAD 2>/dev/null)" || die "git repo degil: ${REPO_DIR}"
log "Mevcut surum : ${PREV_SHA}"

log "git fetch..."
git fetch --prune origin "${BRANCH}" 2>&1 | tee -a "${LOG_FILE}"
NEW_SHA="$(git rev-parse "origin/${BRANCH}" 2>/dev/null)" || die "origin/${BRANCH} okunamadi"
log "Uzak surum   : ${NEW_SHA}"

if [ "${PREV_SHA}" = "${NEW_SHA}" ]; then
  log "Degisiklik yok. Deploy'a gerek yok. Cikiliyor."
  exit 0
fi

CHANGED_FILES="$(git diff --name-only "${PREV_SHA}" "${NEW_SHA}")"
log "Degisen dosyalar:"
echo "${CHANGED_FILES}" | sed 's/^/    /' | tee -a "${LOG_FILE}"

# ----------------------------- Kodu guncelle ----------------------------------
# .env / node_modules / .next gitignore'da oldugu icin bunlara dokunulmaz.
log "Kod guncelleniyor: git reset --hard ${NEW_SHA}"
git reset --hard "${NEW_SHA}" 2>&1 | tee -a "${LOG_FILE}" || die "git reset basarisiz"

# ----------------------------- Site build fonksiyonu --------------------------
build_and_restart(){
  local folder="$1"
  local name="${APP_NAME[$folder]}"
  local port="${APP_PORT[$folder]}"
  local dir="${REPO_DIR}/${folder}/site"

  log "--- ${folder} (pm2:${name} port:${port}) ---"
  cd "${dir}" || { log "!!! ${dir} yok"; return 1; }

  chmod +x node_modules/.bin/next 2>/dev/null || true

  if echo "${CHANGED_FILES}" | grep -qE "^${folder}/site/(package\.json|yarn\.lock)$"; then
    log "${folder}: bagimlilik degismis -> yarn install"
    yarn install --frozen-lockfile 2>&1 | tee -a "${LOG_FILE}" || { log "!!! ${folder}: yarn install basarisiz"; return 1; }
  fi

  rm -rf .next
  log "${folder}: yarn build..."
  if ! yarn build 2>&1 | tee -a "${LOG_FILE}"; then
    log "!!! ${folder}: BUILD BASARISIZ"
    return 1
  fi

  log "${folder}: pm2 restart ${name}"
  pm2 restart "${name}" --update-env 2>&1 | tee -a "${LOG_FILE}" || { log "!!! ${folder}: pm2 restart basarisiz"; return 1; }

  # saglik kontrolu (boot suresi icin birkac deneme)
  local ok=0 i
  for i in 1 2 3 4 5 6 7 8; do
    sleep 3
    if curl -fsS -m 10 "http://127.0.0.1:${port}/" >/dev/null 2>&1; then ok=1; break; fi
  done
  if [ "${ok}" = 1 ]; then
    log "${folder}: saglik kontrolu OK (port ${port})"
    return 0
  fi
  log "!!! ${folder}: saglik kontrolu BASARISIZ (port ${port})"
  return 1
}

# --------------- Hangi site(ler) degisti? Sadece onlari build et ---------------
CHANGED_TOP="$(echo "${CHANGED_FILES}" | awk -F/ 'NF>1{print $1}' | sort -u)"
TARGETS=()
for folder in "${!APP_NAME[@]}"; do
  if echo "${CHANGED_TOP}" | grep -qx "${folder}" && echo "${CHANGED_FILES}" | grep -qE "^${folder}/site/"; then
    TARGETS+=("${folder}")
  fi
done

if [ "${#TARGETS[@]}" -eq 0 ]; then
  log "site/ altinda degisiklik yok (muhtemelen api/admin/deploy degisti). pm2 restart gerekmiyor."
  pm2 save 2>&1 | tee -a "${LOG_FILE}" || true
  log "================ Deploy tamam (build gerekmedi): ${NEW_SHA} ================"
  exit 0
fi

log "Build edilecek site(ler): ${TARGETS[*]}"

FAILED=0
for folder in "${TARGETS[@]}"; do
  build_and_restart "${folder}" || { FAILED=1; break; }
done

# ------------------------------- Rollback -------------------------------------
if [ "${FAILED}" = 1 ]; then
  log "!!!!!! Deploy BASARISIZ. ROLLBACK baslatiliyor -> ${PREV_SHA}"
  cd "${REPO_DIR}" || die "rollback: ${REPO_DIR} yok"
  git reset --hard "${PREV_SHA}" 2>&1 | tee -a "${LOG_FILE}"
  for folder in "${TARGETS[@]}"; do
    ( cd "${REPO_DIR}/${folder}/site" \
        && rm -rf .next \
        && yarn build \
        && pm2 restart "${APP_NAME[$folder]}" --update-env ) 2>&1 | tee -a "${LOG_FILE}" || log "!!! ${folder}: rollback build sorunlu, MANUEL kontrol gerekli"
  done
  log "ROLLBACK tamamlandi. Onceki surum (${PREV_SHA}) geri yuklendi."
  exit 1
fi

pm2 save 2>&1 | tee -a "${LOG_FILE}" || true
log "================ Deploy BASARILI: ${NEW_SHA} ================"
exit 0
