#!/bin/bash
# MapSystem - node uzerinde calisan dagitim scripti.
#
# Bu dosya sunucuda /usr/local/sbin/mapsystem-deploy olarak, ROOT'a ait ve yalnizca root
# tarafindan YAZILABILIR durur. Dagitim kullanicisi bunu sudo ile parolasiz calistirabilir
# ama ICERIGINI DEGISTIREMEZ.
#
# Tasarim gerekcesi: dagitim kullanicisina "NOPASSWD: ALL" vermek, dagitim anahtarini fiilen
# root anahtarina cevirir. Anahtar sizarsa saldirgan makinenin tamamini alir. Burada verilen
# tek yetki "MapSystem'i guncelle"dir; script sabit yollarla calisir, disaridan komut almaz.
#
# Kullanim (dagitim kullanicisi olarak):
#   sudo /usr/local/sbin/mapsystem-deploy /tmp/ms-new.tgz
#   sudo /usr/local/sbin/mapsystem-deploy --restart
#   sudo /usr/local/sbin/mapsystem-deploy --status

set -euo pipefail

INSTALL_DIR="/opt/mapsystem"
SERVICE="mapsystem"

usage() {
    cat <<'EOF'
kullanim:
  mapsystem-deploy <paket.tgz>        yeni surumu kur
  mapsystem-deploy --restart          servisi yeniden baslat
  mapsystem-deploy --status           servis durumu
  mapsystem-deploy --logs             son kayitlar

  mapsystem-deploy --retire on|off    bu node'u emekliye ayir / geri al
  mapsystem-deploy --remove <id|adres>   bir node'u kumeden cikar
  mapsystem-deploy --unremove <id|adres> cikarma islemini geri al
  mapsystem-deploy --cluster          mevcut kume ayarlarini goster
  mapsystem-deploy --anahtar          kume katilim anahtarini ve node ekleme komutunu goster
EOF
    exit 2
}
[[ $# -ge 1 ]] || usage

CONFIG="$INSTALL_DIR/appsettings.Production.json"

# Yapilandirma dosyasi 0600 ve servis kullanicisina ait; dagitim kullanicisi onu duzenleyemez ve
# duzenleyebilmesi de dogru olmaz (icinde baglanti dizeleri var). Node cikarma ayarlari bu yuzden
# buradan, DAR bir arayuzle degistirilir: yalnizca uc alana dokunulur, dosyanin geri kalanina degil.
edit_config() {   # $1 = python ifadesi (cfg sozlugu uzerinde calisir)
    [[ -f "$CONFIG" ]] || { echo "HATA: $CONFIG yok" >&2; exit 1; }
    local owner; owner="$(stat -c '%U:%G' "$CONFIG")"
    local mode;  mode="$(stat -c '%a' "$CONFIG")"
    cp -a "$CONFIG" "$CONFIG.yedek-$(date +%Y%m%d-%H%M%S)"
    python3 - "$CONFIG" "$1" <<'PY'
import json, sys
path, expr = sys.argv[1], sys.argv[2]
doc = json.load(open(path, encoding='utf-8'))
cfg = doc.setdefault('MapSystem', {}).setdefault('Cluster', {})
exec(expr)
json.dump(doc, open(path, 'w', encoding='utf-8'), ensure_ascii=False, indent=2)
PY
    chown "$owner" "$CONFIG"; chmod "$mode" "$CONFIG"
    echo "  -> yapilandirma guncellendi"
}

case "$1" in
  --status) systemctl status "$SERVICE" --no-pager -l | head -20; exit 0 ;;
  --logs)   journalctl -u "$SERVICE" -n 60 --no-pager; exit 0 ;;
  --restart) systemctl restart "$SERVICE"; sleep 2; systemctl is-active "$SERVICE"; exit 0 ;;

  --anahtar|--join-token)
    # Kumenin katilim anahtarini ve yeni node icin hazir komutu yazdirir.
    python3 - "$CONFIG" <<'PY'
import json, sys
cfg = json.load(open(sys.argv[1], encoding='utf-8')).get('MapSystem', {})
tok = cfg.get('Cluster', {}).get('JoinToken', '')
addr = cfg.get('Orchestrator', {}).get('NodeAddress', '') or 'http://<bu-sunucunun-adresi>'
if not tok:
    print('Bu node bir kume katilim anahtari tasimiyor.')
    print('Kume kurmak icin ilk node: curl -fsSL https://mapsystem.com.tr/indir/kur.sh | sudo bash -s -- --kume')
    sys.exit(1)
print('Katilim anahtari:', tok)
print()
print('Yeni node eklemek icin o makinede:')
print('  curl -fsSL https://mapsystem.com.tr/indir/node-ekle.sh | sudo bash -s -- \\')
print('       --kume %s --anahtar %s' % (addr, tok))
PY
    exit $? ;;

  --cluster)
    python3 -c "
import json,sys
c=json.load(open('$CONFIG',encoding='utf-8')).get('MapSystem',{}).get('Cluster',{})
print('Retiring    :', c.get('Retiring', False))
print('RemovedNodes:', c.get('RemovedNodes', []))
print('Peers       :', c.get('Peers', []))"
    exit 0 ;;

  --retire)
    [[ "${2:-}" == "on" || "${2:-}" == "off" ]] || usage
    val=$([[ "$2" == "on" ]] && echo True || echo False)
    edit_config "cfg['Retiring'] = $val"
    systemctl restart "$SERVICE"; sleep 3
    systemctl is-active --quiet "$SERVICE" && echo "TAMAM: emeklilik = $2" || { echo "HATA: servis baslamadi" >&2; exit 1; }
    exit 0 ;;

  --remove|--unremove)
    [[ -n "${2:-}" ]] || usage
    if [[ "$1" == "--remove" ]]; then
        # Peers'tan da dusurulur: biri adresi unutturur, digeri node geri donerse engeller.
        edit_config "
lst = cfg.setdefault('RemovedNodes', [])
if '$2' not in lst: lst.append('$2')
cfg['Peers'] = [p for p in cfg.get('Peers', []) if p.rstrip('/').lower() != '$2'.rstrip('/').lower()]"
    else
        edit_config "cfg['RemovedNodes'] = [x for x in cfg.get('RemovedNodes', []) if x != '$2']"
    fi
    systemctl restart "$SERVICE"; sleep 3
    systemctl is-active --quiet "$SERVICE" && echo "TAMAM: $1 $2" || { echo "HATA: servis baslamadi" >&2; exit 1; }
    exit 0 ;;
esac

[[ $# -eq 1 ]] || usage

PKG="$1"

# Paket yolu kisitli: dagitim kullanicisi rastgele bir dosyayi /opt/mapsystem uzerine
# acamasin diye yalnizca /tmp altindaki .tgz dosyalari kabul edilir.
case "$PKG" in
  /tmp/*.tgz) ;;
  *) echo "HATA: paket /tmp altinda ve .tgz olmali: $PKG" >&2; exit 1 ;;
esac
[[ -f "$PKG" ]] || { echo "HATA: paket yok: $PKG" >&2; exit 1; }

# Servisin hangi kullanici ile calistigini systemd'den ogren; sabit yazmak, kurulumda
# farkli bir kullanici secilmis olsaydi izinleri sessizce bozardi.
SVC_USER="$(systemctl show -p User --value "$SERVICE" 2>/dev/null || true)"
[[ -n "$SVC_USER" ]] || SVC_USER="mapsystem"

STAMP="$(date +%Y%m%d-%H%M%S)"
STAGE="$(mktemp -d /tmp/ms-stage-XXXXXX)"
trap 'rm -rf "$STAGE"' EXIT

echo "[1/5] paket aciliyor"
tar xzf "$PKG" -C "$STAGE"

# Paketin gercekten bir MapSystem yayini oldugunu dogrula. Bu kontrol olmadan bozuk bir
# paket, calisan kurulumu silip yerine hicbir sey koymayabilirdi.
[[ -f "$STAGE/MapSystem.Host.dll" ]] || { echo "HATA: pakette MapSystem.Host.dll yok; dagitim iptal." >&2; exit 1; }

echo "[2/5] servis durduruluyor"
systemctl stop "$SERVICE" || true

# Veri ve yapilandirma KORUNUR: data-directory katalogu ve anahtar halkasini, appsettings ise
# node'a ozel ayarlari (adres, node kimligi) tutar. Bunlarin uzerine yazmak kurulumu bitirir.
echo "[3/5] ikili dosyalar guncelleniyor (veri ve ayarlar korunuyor)"
mkdir -p "$INSTALL_DIR"
find "$STAGE" -maxdepth 1 -mindepth 1 \
     ! -name 'appsettings.Production.json' \
     ! -name 'data-directory' \
     -exec cp -a {} "$INSTALL_DIR"/ \;

chown -R "$SVC_USER":"$SVC_USER" "$INSTALL_DIR"

echo "[4/5] servis baslatiliyor"
systemctl start "$SERVICE"
sleep 3

echo "[5/5] dogrulama"
if systemctl is-active --quiet "$SERVICE"; then
    echo "TAMAM: $SERVICE calisiyor ($STAMP)"
else
    echo "HATA: servis baslamadi. Son kayitlar:" >&2
    journalctl -u "$SERVICE" -n 30 --no-pager >&2
    exit 1
fi
