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

APP_DIR="${NARVO_ROOT:-/var/www/html/narvo}"
PKG="${1:-}"
LOCK="/var/lock/narvo-offline-update.lock"
BACKUP_BASE="/var/backups/narvo-offline"
TMP=""
STARTED=0
BACKUP=""
DB_DUMP=""
APP_TAR=""
DB_HOST=""
DB_NAME=""
DB_USER=""
DB_PASS=""

die(){ echo "HATA: $*" >&2; exit 1; }
cleanup(){ [[ -n "${TMP:-}" && -d "${TMP:-}" ]] && rm -rf "$TMP"; }
trap cleanup EXIT

rollback(){
  local rc=$?
  if [[ "$STARTED" -eq 1 && -n "$BACKUP" ]]; then
    echo "Güncelleme başarısız. Geri dönüş başlatılıyor..." >&2
    if [[ -f "$APP_TAR" ]]; then
      rm -rf "$APP_DIR"
      mkdir -p "$(dirname "$APP_DIR")"
      tar -xzf "$APP_TAR" -C "$(dirname "$APP_DIR")" || true
    fi
    if [[ -f "$DB_DUMP" ]]; then
      MYSQL_PWD="$DB_PASS" mysql -h "$DB_HOST" -u "$DB_USER" "$DB_NAME" < "$DB_DUMP" || true
    fi
    systemctl reload apache2 >/dev/null 2>&1 || true
  fi
  exit "$rc"
}
trap rollback ERR

[[ "$EUID" -eq 0 ]] || die "root yetkisi gerekli."
[[ -n "$PKG" ]] || die "Kullanım: sudo narvo-offline-update /path/NARVO-OFFLINE-UPDATE.zip"
[[ -f "$PKG" ]] || die "Paket bulunamadı: $PKG"
[[ -d "$APP_DIR" ]] || die "NARVO bulunamadı: $APP_DIR"
[[ -f "$APP_DIR/config/database.php" ]] || die "DB config bulunamadı."
command -v php >/dev/null || die "PHP CLI bulunamadı."
command -v unzip >/dev/null || die "unzip bulunamadı."
command -v rsync >/dev/null || die "rsync bulunamadı."

exec 9>"$LOCK"
flock -n 9 || die "Başka bir NARVO güncellemesi çalışıyor."

# Offline license must be active; updater itself never checks the internet.
php -r '
require $argv[1]."/config/database.php";
require $argv[1]."/includes/license.php";
$pdo=db();
if(!mon_license_is_offline($pdo)){fwrite(STDERR,"Bu komut yalnızca Enterprise Offline mod içindir.\n");exit(2);}
$e=mon_license_entitlement($pdo);
if(($e["status"]??"")!=="licensed"){fwrite(STDERR,"Enterprise Offline lisans geçerli değil: ".($e["message"]??"")."\n");exit(3);}
' "$APP_DIR"

TMP="$(mktemp -d)"
unzip -q "$PKG" -d "$TMP"

MAN="$TMP/update-manifest.json"
SIG="$TMP/update-manifest.sig"
PAYLOAD="$TMP/NARVO-PAYLOAD.zip"
[[ -f "$MAN" && -f "$SIG" && -f "$PAYLOAD" ]] || die "Offline update paketi eksik/geçersiz."

# Verify manifest signature against the same pinned NARVO vendor key used by the license.
php -r '
require $argv[1]."/config/database.php";
require $argv[1]."/includes/license.php";
$trust=mon_license_trusted_key();
if(empty($trust["pem"])){fwrite(STDERR,"Vendor public key trust bulunamadı.\n");exit(2);}
$manifest=file_get_contents($argv[2]);
$sig=base64_decode(trim(file_get_contents($argv[3])),true);
if($manifest===false||$sig===false){fwrite(STDERR,"Manifest/imza okunamadı.\n");exit(3);}
$key=openssl_pkey_get_public($trust["pem"]);
if(!$key||openssl_verify($manifest,$sig,$key,OPENSSL_ALGO_SHA256)!==1){
    fwrite(STDERR,"Offline update RSA imzası geçersiz.\n");exit(4);
}
' "$APP_DIR" "$MAN" "$SIG"

mapfile -t META < <(php -r '
$j=json_decode(file_get_contents($argv[1]),true);
if(!is_array($j)||($j["product"]??"")!=="NARVO"){exit(2);}
echo ($j["build"]??""),PHP_EOL;
echo ($j["payload_sha256"]??""),PHP_EOL;
echo ($j["product_version"]??""),PHP_EOL;
' "$MAN")
BUILD="${META[0]:-}"
EXPECTED="${META[1]:-}"
VERSION="${META[2]:-}"
[[ "$BUILD" =~ ^[0-9]+$ ]] || die "Build geçersiz."
[[ "$EXPECTED" =~ ^[a-fA-F0-9]{64}$ ]] || die "SHA256 geçersiz."
ACTUAL="$(sha256sum "$PAYLOAD" | awk '{print $1}')"
[[ "${ACTUAL,,}" == "${EXPECTED,,}" ]] || die "Payload SHA256 doğrulaması başarısız."

PAYDIR="$TMP/payload"
mkdir -p "$PAYDIR"
unzip -q "$PAYLOAD" -d "$PAYDIR"
[[ -d "$PAYDIR/narvo" ]] || die "Payload içinde narvo/ yok."

# PHP lint before touching the live installation.
while IFS= read -r -d '' f; do
  php -l "$f" >/dev/null || die "PHP syntax hatası: $f"
done < <(find "$PAYDIR/narvo" -type f -name '*.php' -print0)

mapfile -t DBINFO < <(php -r '
require $argv[1];
echo DB_HOST,PHP_EOL;echo DB_NAME,PHP_EOL;echo DB_USER,PHP_EOL;echo base64_encode(DB_PASS),PHP_EOL;
' "$APP_DIR/config/database.php")
DB_HOST="${DBINFO[0]}"; DB_NAME="${DBINFO[1]}"; DB_USER="${DBINFO[2]}"
DB_PASS="$(printf '%s' "${DBINFO[3]}" | base64 -d)"

STAMP="$(date +%Y%m%d-%H%M%S)"
BACKUP="$BACKUP_BASE/$STAMP"
mkdir -p "$BACKUP"; chmod 700 "$BACKUP"
DB_DUMP="$BACKUP/database.sql"
APP_TAR="$BACKUP/narvo-files.tar.gz"

MYSQL_PWD="$DB_PASS" mysqldump -h "$DB_HOST" -u "$DB_USER" --single-transaction --quick --routines --triggers "$DB_NAME" > "$DB_DUMP"
tar -czf "$APP_TAR" -C "$(dirname "$APP_DIR")" "$(basename "$APP_DIR")"
STARTED=1

rsync -a --delete \
  --exclude='config/database.php' \
  --exclude='config/license_trust.php' \
  --exclude='config/*.lic' \
  --exclude='config/*.pem' \
  --exclude='config/*.key' \
  --exclude='.env' \
  --exclude='assets/vendor-content/***' \
  --exclude='storage/***' \
  --exclude='uploads/***' \
  --exclude='logs/***' \
  --exclude='KURULUM.php' \
  "$PAYDIR/narvo/" "$APP_DIR/"

rm -f "$APP_DIR/KURULUM.php" "$APP_DIR/config/install-bootstrap.php"

php -r '
define("NARVO_INSTALL_CONTEXT",true);
require $argv[1]."/config/database.php";
require $argv[1]."/includes/schema_runner.php";
if(!$ok){fwrite(STDERR,implode(PHP_EOL,$messages).PHP_EOL);exit(1);}
' "$APP_DIR"

chown -R root:www-data "$APP_DIR"
find "$APP_DIR" -type d -exec chmod 755 {} \;
find "$APP_DIR" -type f -exec chmod 644 {} \;
chown root:www-data "$APP_DIR/config"; chmod 775 "$APP_DIR/config"
chown root:www-data "$APP_DIR/config/database.php"; chmod 640 "$APP_DIR/config/database.php"
[[ -f "$APP_DIR/config/license_trust.php" ]] && { chown www-data:www-data "$APP_DIR/config/license_trust.php"; chmod 640 "$APP_DIR/config/license_trust.php"; }
[[ -f "$APP_DIR/config/narvo-enterprise.lic" ]] && { chown www-data:www-data "$APP_DIR/config/narvo-enterprise.lic"; chmod 640 "$APP_DIR/config/narvo-enterprise.lic"; }

printf '%s\n' "$BUILD" > "$APP_DIR/.narvo-build"
chown root:www-data "$APP_DIR/.narvo-build"; chmod 644 "$APP_DIR/.narvo-build"

if [[ -x "$APP_DIR/tools/install_linux_runtime.sh" ]]; then
  "$APP_DIR/tools/install_linux_runtime.sh" "$APP_DIR" >/dev/null
fi

apache2ctl configtest >/dev/null
systemctl reload apache2

php -r '
require $argv[1]."/config/database.php";
require $argv[1]."/includes/license.php";
$pdo=db(); db()->query("SELECT 1")->fetchColumn();
$e=mon_license_entitlement($pdo);
if(($e["status"]??"")!=="licensed"){fwrite(STDERR,"Offline lisans health check başarısız.\n");exit(2);}
echo "OK\n";
' "$APP_DIR"

STARTED=0
trap - ERR

echo
echo "============================================"
echo " NARVO OFFLINE GÜNCELLEME TAMAMLANDI"
echo "============================================"
echo "Sürüm : $VERSION"
echo "Build : $BUILD"
echo "Yedek : $BACKUP"
echo "Dış ağ isteği: YOK"
