#!/bin/bash

set -euo pipefail

APP_NAME="dingx-substrate-delivery"
ARCH="amd64"
BINARY_NAME="${APP_NAME}-linux-${ARCH}"
BINARY_TARGET="/opt/dingx-gateway/bin/${APP_NAME}-${ARCH}"
SYMLINK_TARGET="/usr/local/bin/${APP_NAME}"
CONFIG_DIR="/etc/dingx-gateway"
BACKUP_ROOT="/home/dingx-gateway/${APP_NAME}-backups"
LATEST_BACKUP_FILE="${BACKUP_ROOT}/latest-backup-path"
SERVICE_NAME="${APP_NAME}.service"
DEFAULT_TAR_PATH="/home/dingx-gateway/${BINARY_NAME}.tar.gz"
DEFAULT_BUNDLE_URL="https://gateway.dingx.net/fuerth/${BINARY_NAME}.tar.gz"

log_message() {
  echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1"
}

run_command() {
  if ! "$@"; then
    log_message "Command failed: $*"
    return 1
  fi
}

require_root() {
  if [ "${EUID}" -ne 0 ]; then
    echo "This script must be run as root." >&2
    exit 1
  fi
}

backup_if_exists() {
  local source_path="$1"
  local destination_path="$2"
  if [ -e "${source_path}" ] || [ -L "${source_path}" ]; then
    mkdir -p "$(dirname "${destination_path}")"
    cp -a "${source_path}" "${destination_path}"
    log_message "Backed up ${source_path} -> ${destination_path}"
  else
    log_message "No existing file to back up: ${source_path}"
  fi
}

require_root
TMP_DIR="$(mktemp -d)"
BUNDLE_SOURCE="${1:-${DEFAULT_BUNDLE_URL}}"
BUNDLE_FILE="${DEFAULT_TAR_PATH}"

cleanup() {
  rm -rf "${TMP_DIR}"
}
trap cleanup EXIT

timestamp_with_fallback() {
  local ts
  ts="$(date '+%Y%m%d-%H%M%S-%N' 2>/dev/null || true)"
  if [ -z "${ts}" ] || [[ "${ts}" == *N ]]; then
    ts="$(date '+%Y%m%d-%H%M%S')"
  fi
  echo "${ts}"
}

TIMESTAMP="$(timestamp_with_fallback)"
BACKUP_DIR="${BACKUP_ROOT}/${TIMESTAMP}"
while [ -e "${BACKUP_DIR}" ]; do
  TIMESTAMP="$(timestamp_with_fallback)"
  BACKUP_DIR="${BACKUP_ROOT}/${TIMESTAMP}"
done

log_message "Using bundle source: ${BUNDLE_SOURCE}"
mkdir -p "$(dirname "${BUNDLE_FILE}")"
if [[ "${BUNDLE_SOURCE}" =~ ^https?:// ]]; then
  if command -v curl >/dev/null 2>&1; then
    curl -fsSL "${BUNDLE_SOURCE}" -o "${BUNDLE_FILE}"
  elif command -v wget >/dev/null 2>&1; then
    wget -qO "${BUNDLE_FILE}" "${BUNDLE_SOURCE}"
  else
    echo "Neither curl nor wget is available for downloading the bundle." >&2
    exit 1
  fi
else
  if [ ! -f "${BUNDLE_SOURCE}" ]; then
    echo "Bundle not found: ${BUNDLE_SOURCE}" >&2
    exit 1
  fi
  if [ "${BUNDLE_SOURCE}" != "${BUNDLE_FILE}" ]; then
    cp -f "${BUNDLE_SOURCE}" "${BUNDLE_FILE}"
  fi
fi

mkdir -p "${BACKUP_DIR}/bin" "${BACKUP_DIR}/etc" "${CONFIG_DIR}" "/opt/dingx-gateway/bin"
backup_if_exists "${BINARY_TARGET}" "${BACKUP_DIR}/bin/$(basename "${BINARY_TARGET}")"
backup_if_exists "${CONFIG_DIR}/ntxcp-substrate-delivery-config.yaml" "${BACKUP_DIR}/etc/ntxcp-substrate-delivery-config.yaml"
backup_if_exists "${CONFIG_DIR}/substrate-delivery-nodes.yaml" "${BACKUP_DIR}/etc/substrate-delivery-nodes.yaml"
backup_if_exists "${SYMLINK_TARGET}" "${BACKUP_DIR}/bin/$(basename "${SYMLINK_TARGET}")"
echo "${BACKUP_DIR}" > "${LATEST_BACKUP_FILE}"
log_message "Backup written to ${BACKUP_DIR}"

tar -xzf "${BUNDLE_FILE}" -C "${TMP_DIR}"

if [ ! -f "${TMP_DIR}/${BINARY_NAME}" ]; then
  echo "Binary missing in bundle: ${BINARY_NAME}" >&2
  exit 1
fi
if [ ! -f "${TMP_DIR}/ntxcp-substrate-delivery-config.yaml" ]; then
  echo "Config missing in bundle: ntxcp-substrate-delivery-config.yaml" >&2
  exit 1
fi
if [ ! -f "${TMP_DIR}/substrate-delivery-nodes.yaml" ]; then
  echo "Config missing in bundle: substrate-delivery-nodes.yaml" >&2
  exit 1
fi

install -m 0755 "${TMP_DIR}/${BINARY_NAME}" "${BINARY_TARGET}"
install -m 0644 "${TMP_DIR}/ntxcp-substrate-delivery-config.yaml" "${CONFIG_DIR}/ntxcp-substrate-delivery-config.yaml"
install -m 0644 "${TMP_DIR}/substrate-delivery-nodes.yaml" "${CONFIG_DIR}/substrate-delivery-nodes.yaml"
ln -sfn "${BINARY_TARGET}" "${SYMLINK_TARGET}"
log_message "Installed binary and configs"

if command -v systemctl >/dev/null 2>&1; then
  run_command systemctl restart "${SERVICE_NAME}" || true
fi

log_message "Install completed successfully."
log_message "Rollback script: /path/to/rollback_fuerth.sh ${BACKUP_DIR}"
