#!/usr/bin/env bash
# ============================================================================
#  Brimoza updater — downloads the latest version, builds it and restarts.
#
#  Run from the project folder (where docker-compose.yml lives):
#      bash scripts/update.sh
#  For SQLite (easy-install):
#      COMPOSE_FILE=compose.sqlite.yml bash scripts/update.sh
#
#  Your .env, state/, logs/ and compose files are PRESERVED — only the
#  application code is updated. The old code is backed up as
#  .brimoza-backup-<version>.tgz.
# ============================================================================
set -euo pipefail

# Script lives in scripts/ -> change to the project root
cd "$(cd "$(dirname "$0")/.." && pwd)"
ROOT="$(pwd)"
VURL="${BRIMOZA_VERSION_URL:-https://brimoza.com/version.json}"

# ---- Release trust anchor (embedded; verifies the NEXT package before it runs) ----
# Public half of the OFFLINE maintainer key (scripts/gen_release_key.sh). The private
# half never leaves the maintainer's machine, so a compromise of brimoza.com cannot
# forge a signed release. Rotate ONLY with a value produced by gen_release_key.sh.
BRIMOZA_RELEASE_PUBKEY="$(cat <<'PUBKEY'
-----BEGIN PUBLIC KEY-----
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA9/1lXxjaEe1FhaHq3VTb
MbAUR2dJqpE1WZpDRfETAbSga+6A6sDlU+hqUhUPDrQUIwxEoab3oq9cde3QMOZk
j6DG8UF0K/pPtyDjooleqwGq28nSQNk3JE7MqTsl6gkwwFcfzEFAlN1U4K7XsVkR
Ub2trvvfSbVKjU8Vb2QfAbYZjVi/K3wTv9MsFnWq3ZeJ0fsXYausl9sZM7IBfijw
eEUoXokoshR4nUUpVKGkedS9Me/yzb/WJeBH05gJN1fTjhsKFV9TDTpqUfwoNiih
XGUBb1Vv9OOOYPTzutNj4XfxKlXKwAwF8ldncXFXrG6LQqizMdLIF/IuRFfpCRxL
5WNkyOiAIKJWBsvRfeKxq7uQMvs+lnrb8dM68J0rKwyAD1KuiOK37VOfkkCIrMaM
psUhPuex30q1pU2oIiGv7dNXrG+bQfCIxi2LaFA6tM/Z4kUU+Hhj4+7LTkVTnD9O
DN9vyXECxScspxCrwadk73+Y0PQus+cOmWmZvoPnoi8rB5MQVjEc1wY4BfSUF6iv
KtXX4+6y//0mwPEEe9GKePs5rAltQTxZQ6ZV2LDobyJxoSNGhrzijoIOCeXv1dz2
c6IiinMreJMezHyBjScHguNEquw77pEwuIkGDWO3hsckL6tcbSROKDLAGWIFIK8M
3xkn/6XEmVFqhqyeIUfRgHMCAwEAAQ==
-----END PUBLIC KEY-----
PUBKEY
)"

# brimoza_verify_release <zip> <ver> <sha256> <download_url> <sig_b64>
# Returns 0 = safe to proceed (verified, or explicitly allowed-unsigned), 1 = abort.
brimoza_verify_release() {
  local zip="$1" ver="$2" sha_exp="$3" url="$4" sig_b64="$5"
  local allow="${BRIMOZA_ALLOW_UNSIGNED:-0}"
  # 1) integrity: downloaded bytes must match the published sha256
  if [ -n "$sha_exp" ]; then
    local got; got="$( { sha256sum "$zip" 2>/dev/null || shasum -a 256 "$zip" 2>/dev/null; } | awk '{print $1}')"
    if [ -z "$got" ]; then
      echo "  [guvenlik] UYARI: sha256 araci yok, butunluk dogrulanamadi." >&2
    elif [ "$got" != "$sha_exp" ]; then
      echo "  [guvenlik] HATA: sha256 UYUSMUYOR (paket bozuk ya da DEGISTIRILMIS) — reddedildi." >&2
      echo "    beklenen: $sha_exp" >&2; echo "    bulunan : $got" >&2; return 1
    fi
  fi
  # 2) authenticity: signature over the canonical manifest, against the embedded key
  case "$BRIMOZA_RELEASE_PUBKEY" in
    *__PASTE_BRIMOZA_RELEASE_PUBLIC_KEY__*|"")
      if [ "$allow" = "1" ]; then echo "  [guvenlik] UYARI: imza anahtari gomulu degil; BRIMOZA_ALLOW_UNSIGNED=1 ile devam." >&2; return 0
      else echo "  [guvenlik] HATA: surum imzasi dogrulanamiyor (anahtar yapilandirilmamis). Devam icin: BRIMOZA_ALLOW_UNSIGNED=1" >&2; return 1; fi ;;
  esac
  if [ -z "$sig_b64" ]; then
    if [ "$allow" = "1" ]; then echo "  [guvenlik] UYARI: version.json imzasiz; BRIMOZA_ALLOW_UNSIGNED=1 ile devam." >&2; return 0
    else echo "  [guvenlik] HATA: version.json imza icermiyor — reddedildi. Devam icin: BRIMOZA_ALLOW_UNSIGNED=1" >&2; return 1; fi
  fi
  command -v openssl >/dev/null 2>&1 || { echo "  [guvenlik] HATA: openssl yok, imza dogrulanamiyor." >&2; return 1; }
  local d; d="$(mktemp -d)"
  printf '%s\n' "brimoza-release-v1" "version=$ver" "sha256=$sha_exp" "download=$url" > "$d/m"
  printf '%s\n' "$BRIMOZA_RELEASE_PUBKEY" > "$d/pub.pem"
  if ! printf '%s' "$sig_b64" | openssl base64 -d -A > "$d/s.bin" 2>/dev/null; then
    rm -rf "$d"; echo "  [guvenlik] HATA: imza cozulemedi (base64)." >&2; return 1
  fi
  if openssl dgst -sha256 -verify "$d/pub.pem" -signature "$d/s.bin" "$d/m" >/dev/null 2>&1; then
    rm -rf "$d"; echo "  [guvenlik] surum imzasi DOGRULANDI (sha256 + RSA)." >&2; return 0
  fi
  rm -rf "$d"; echo "  [guvenlik] HATA: surum imzasi GECERSIZ — paket reddedildi." >&2; return 1
}

for c in python3 curl docker; do
  command -v "$c" >/dev/null || { echo "[update] HATA: '$c' gerekli ama bulunamadı."; exit 1; }
done

echo "[update] sürüm bilgisi alınıyor: $VURL"
META="$(curl -fsSL "$VURL")"
VER="$(printf '%s' "$META" | python3 -c 'import sys,json;print(json.load(sys.stdin)["version"])')"
URL="$(printf '%s' "$META" | python3 -c 'import sys,json;print(json.load(sys.stdin)["download"])')"
SHA="$(printf '%s' "$META" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("sha256") or "")')"
SIG="$(printf '%s' "$META" | python3 -c 'import sys,json;print(json.load(sys.stdin).get("sig") or "")')"
CURR="$(cat VERSION 2>/dev/null || echo '?')"
echo "[update] yüklü: v$CURR  ->  en son: v$VER"
if [ "$VER" = "$CURR" ]; then
  echo "[update] Zaten güncelsin (v$CURR). Çıkılıyor."; exit 0
fi
case "$URL" in
  https://*) ;;
  *) echo "[update] HATA: indirme URL'si https değil — reddedildi: $URL"; exit 1 ;;
esac

TMP="$(mktemp -d)"; trap 'rm -rf "$TMP" /tmp/brimoza-update.zip' EXIT
echo "[update] indiriliyor: $URL"
curl -fsSL "$URL" -o /tmp/brimoza-update.zip
echo "[update] paket doğrulanıyor (sha256 + imza)..."
brimoza_verify_release /tmp/brimoza-update.zip "$VER" "$SHA" "$URL" "$SIG" \
  || { echo "[update] İPTAL: paket doğrulanamadı, hiçbir şey değiştirilmedi."; exit 1; }
python3 -c 'import zipfile,sys;zipfile.ZipFile("/tmp/brimoza-update.zip").extractall(sys.argv[1])' "$TMP"
SRC="$(find "$TMP" -maxdepth 1 -type d -name 'brimoza-*' | head -1)"
[ -d "$SRC" ] || { echo "[update] HATA: zip içeriği beklenmedik."; exit 1; }

echo "[update] mevcut kod yedekleniyor -> .brimoza-backup-$CURR.tgz"
tar czf ".brimoza-backup-$CURR.tgz" coinbot webapp scripts Dockerfile VERSION 2>/dev/null || true

echo "[update] kod güncelleniyor (.env / state / logs / compose dosyaların KORUNUR)..."
for item in coinbot webapp Dockerfile requirements.txt config.yaml config.testnet-soak.yaml \
            VERSION CHANGELOG.md README.md SETUP.md LICENSE; do
  [ -e "$SRC/$item" ] || continue
  rm -rf "$ROOT/$item"; cp -r "$SRC/$item" "$ROOT/$item"
done
# scripts/: prevent the running update.sh from overwriting itself -> drop the new version as update.sh.new
if [ -d "$SRC/scripts" ]; then
  for s in "$SRC"/scripts/*; do
    bn="$(basename "$s")"
    if [ "$bn" = "update.sh" ]; then cp "$s" "$ROOT/scripts/update.sh.new" 2>/dev/null || true
    else rm -rf "$ROOT/scripts/$bn"; cp -r "$s" "$ROOT/scripts/$bn"; fi
  done
fi

echo "[update] yeniden derleniyor + başlatılıyor (docker compose up -d --build)..."
docker compose up -d --build

echo "[update] TAMAM — Brimoza v$VER çalışıyor."
echo "[update] Yedek: .brimoza-backup-$CURR.tgz"
[ -f "$ROOT/scripts/update.sh.new" ] && echo "[update] Not: güncelleyici de değişmiş olabilir -> 'mv scripts/update.sh.new scripts/update.sh'"
