#!/usr/bin/env sh
set -eu

APP_NAME="SMS Gateway"
PACKAGE_URL="${SMS_GATEWAY_PACKAGE_URL:-http://image.openvox.cn/sms-gateway/sms-gateway-20260701-deploy.tar.gz}"
INSTALL_DIR="${SMS_GATEWAY_INSTALL_DIR:-/opt/sms-gateway}"
WORK_DIR=""

log() {
  printf '%s\n' "$*"
}

fail() {
  printf 'ERROR: %s\n' "$*" >&2
  exit 1
}

run_as_root() {
  if [ "$(id -u)" -eq 0 ]; then
    "$@"
  elif command -v sudo >/dev/null 2>&1; then
    sudo "$@"
  else
    fail "root privileges are required. Re-run with sudo."
  fi
}

run_root_sh() {
  script="$1"
  if [ "$(id -u)" -eq 0 ]; then
    sh -c "$script"
  elif command -v sudo >/dev/null 2>&1; then
    sudo sh -c "$script"
  else
    fail "root privileges are required. Re-run with sudo."
  fi
}

cleanup() {
  if [ -n "$WORK_DIR" ] && [ -d "$WORK_DIR" ]; then
    run_as_root rm -rf "$WORK_DIR"
  fi
}

trap cleanup EXIT INT TERM

require_package_url() {
  if [ -z "$PACKAGE_URL" ] || [ "$PACKAGE_URL" = "__SMS_GATEWAY_DEPLOY_PACKAGE_URL__" ]; then
    fail "PACKAGE_URL is still a placeholder. Replace __SMS_GATEWAY_DEPLOY_PACKAGE_URL__ or run with SMS_GATEWAY_PACKAGE_URL=https://your-server/sms-gateway-YYYYMMDD-deploy.tar.gz"
  fi
}

load_os_release() {
  if [ ! -r /etc/os-release ]; then
    fail "/etc/os-release is missing; this installer supports Debian 12 and Debian 13 only."
  fi

  # shellcheck disable=SC1091
  . /etc/os-release

  if [ "${ID:-}" != "debian" ]; then
    fail "unsupported OS '${ID:-unknown}'. This installer supports Debian 12 and Debian 13 only."
  fi

  DEBIAN_MAJOR=$(printf '%s' "${VERSION_ID:-}" | cut -d. -f1)
  case "$DEBIAN_MAJOR" in
    12)
      VERSION_CODENAME="${VERSION_CODENAME:-bookworm}"
      ;;
    13)
      VERSION_CODENAME="${VERSION_CODENAME:-trixie}"
      ;;
    *)
      fail "unsupported Debian version '${VERSION_ID:-unknown}'. Supported versions: Debian 12, Debian 13."
      ;;
  esac
}

docker_compose_available() {
  command -v docker >/dev/null 2>&1 && run_as_root docker compose version >/dev/null 2>&1
}

ensure_docker_running() {
  if run_as_root docker info >/dev/null 2>&1; then
    return
  fi

  if command -v systemctl >/dev/null 2>&1; then
    run_as_root systemctl enable --now docker >/dev/null 2>&1 || true
  elif command -v service >/dev/null 2>&1; then
    run_as_root service docker start >/dev/null 2>&1 || true
  fi

  run_as_root docker info >/dev/null 2>&1 || fail "Docker is installed but the Docker daemon is not running."
}

install_docker_if_needed() {
  if docker_compose_available; then
    log "Docker and Docker Compose plugin are already installed."
    ensure_docker_running
    return
  fi

  load_os_release
  log "Installing Docker Engine for Debian ${DEBIAN_MAJOR} (${VERSION_CODENAME})..."

  run_as_root apt-get update
  run_as_root env DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl gnupg tar

  for pkg in docker.io docker-compose docker-doc podman-docker containerd runc; do
    run_as_root apt-get remove -y "$pkg" >/dev/null 2>&1 || true
  done

  run_as_root install -m 0755 -d /etc/apt/keyrings
  run_root_sh "curl -fsSL https://download.docker.com/linux/debian/gpg -o /etc/apt/keyrings/docker.asc"
  run_as_root chmod a+r /etc/apt/keyrings/docker.asc

  ARCH=$(dpkg --print-architecture)
  run_root_sh "cat > /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/debian
Suites: ${VERSION_CODENAME}
Components: stable
Architectures: ${ARCH}
Signed-By: /etc/apt/keyrings/docker.asc
EOF"

  run_as_root apt-get update
  run_as_root env DEBIAN_FRONTEND=noninteractive apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

  ensure_docker_running
  docker_compose_available || fail "Docker Compose plugin was not installed correctly."
}

download_and_extract_package() {
  CALLER_DIR=$(pwd -P)
  WORK_DIR=$(mktemp -d "${CALLER_DIR}/.sms-gateway-install.XXXXXX")
  PACKAGE_FILE="${WORK_DIR}/sms-gateway-deploy.tar.gz"
  EXTRACT_DIR="${WORK_DIR}/extract"
  SHA256_FILE="${WORK_DIR}/sms-gateway-deploy.tar.gz.sha256"

  mkdir -p "$EXTRACT_DIR"

  log "Downloading ${APP_NAME} deploy package..."
  curl -fL --retry 5 --retry-delay 2 --retry-all-errors --connect-timeout 20 "$PACKAGE_URL" -o "$PACKAGE_FILE"

  log "Checking downloaded package..."
  if ! tar -tzf "$PACKAGE_FILE" >/dev/null 2>&1; then
    fail "downloaded package is incomplete or corrupted. Delete ${PACKAGE_FILE} and retry."
  fi

  SHA256_URL="${SMS_GATEWAY_SHA256_URL:-${PACKAGE_URL}.sha256}"
  if curl -fL --retry 2 --connect-timeout 10 "$SHA256_URL" -o "$SHA256_FILE" >/dev/null 2>&1; then
    log "Verifying package checksum..."
    EXPECTED_SHA256=$(awk '{ print $1; exit }' "$SHA256_FILE")
    if [ -z "$EXPECTED_SHA256" ]; then
      fail "checksum file is empty: ${SHA256_URL}"
    fi
    (
      cd "$WORK_DIR"
      printf '%s  sms-gateway-deploy.tar.gz\n' "$EXPECTED_SHA256" | sha256sum -c -
    )
  else
    log "Checksum file not found; gzip/tar integrity check passed."
  fi

  REQUIRED_KB=700000
  AVAILABLE_KB=$(df -Pk "$CALLER_DIR" | awk 'NR==2 { print $4 }')
  if [ "${AVAILABLE_KB:-0}" -lt "$REQUIRED_KB" ]; then
    fail "not enough free space in ${CALLER_DIR}. Need at least 700 MB free for download and extraction."
  fi

  tar -xzf "$PACKAGE_FILE" -C "$EXTRACT_DIR"

  if [ ! -x "${EXTRACT_DIR}/sms-gateway/release/install.sh" ]; then
    fail "invalid deploy package: release/install.sh is missing or not executable."
  fi

  INSTALL_PARENT=$(dirname "$INSTALL_DIR")
  run_as_root mkdir -p "$INSTALL_PARENT"

  if [ -d "$INSTALL_DIR" ]; then
    log "Updating existing installation at ${INSTALL_DIR}..."
    run_as_root cp -a "${EXTRACT_DIR}/sms-gateway/." "$INSTALL_DIR/"
  else
    log "Installing to ${INSTALL_DIR}..."
    if mv "${EXTRACT_DIR}/sms-gateway" "$INSTALL_DIR" 2>/dev/null; then
      :
    else
      run_as_root cp -a "${EXTRACT_DIR}/sms-gateway" "$INSTALL_DIR"
    fi
  fi

  run_as_root chmod +x "${INSTALL_DIR}/release/install.sh"
}

run_application_installer() {
  log "Starting ${APP_NAME}..."
  (
    cd "$INSTALL_DIR"
    run_as_root sh ./release/install.sh
  )
}

read_env_value() {
  key="$1"
  default_value="$2"
  env_file="${INSTALL_DIR}/.env"

  if [ -r "$env_file" ]; then
    value=$(grep -E "^${key}=" "$env_file" | tail -n 1 | cut -d= -f2- || true)
    if [ -n "$value" ]; then
      printf '%s' "$value" | sed "s/^['\"]//;s/['\"]$//"
      return
    fi
  fi

  printf '%s' "$default_value"
}

detect_host_ip() {
  if command -v ip >/dev/null 2>&1; then
    ip -4 route get 1.1.1.1 2>/dev/null | awk '{ for (i=1; i<=NF; i++) if ($i == "src") { print $(i+1); exit } }'
    return
  fi

  if command -v hostname >/dev/null 2>&1; then
    hostname -I 2>/dev/null | awk '{ print $1 }'
    return
  fi
}

print_summary() {
  FRONTEND_PORT=$(read_env_value FRONTEND_PORT 4674)
  ADMIN_USER=$(read_env_value SUPERADMIN_USERNAME sysadmin)
  ADMIN_PASS=$(read_env_value SUPERADMIN_PASSWORD "Password!")
  HOST_IP=$(detect_host_ip || true)
  HOST_IP="${HOST_IP:-<server-ip>}"

  cat <<EOF

${APP_NAME} deployment completed.

Access URL:
  http://${HOST_IP}:${FRONTEND_PORT}

Default login:
  Username: ${ADMIN_USER}
  Password: ${ADMIN_PASS}

Install directory:
  ${INSTALL_DIR}

Useful commands:
  cd ${INSTALL_DIR}
  docker compose ps
  docker logs -f smsgateway-backend

EOF
}

main() {
  require_package_url
  install_docker_if_needed
  download_and_extract_package
  run_application_installer
  print_summary
}

main "$@"
