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

PACKAGE_URL=""
DOMAIN=""
STAGING_DOMAIN=""
ADMIN_EMAIL=""
ADMIN_NAME="ZT Deploy Administrator"
ACME_EMAIL=""
NONINTERACTIVE=0
INSTALL_DIR="/opt/ztdeploy"

usage() {
cat <<'TXT'
ZT Deploy one-command raw-server bootstrap

Required:
  --package-url URL
  --domain DOMAIN
  --admin-email EMAIL

Optional:
  --staging-domain DOMAIN
  --admin-name NAME
  --acme-email EMAIL
  --non-interactive
  --install-dir PATH      default /opt/ztdeploy

The bootstrap expects a checksum at: <package-url>.sha256
TXT
}

while [[ $# -gt 0 ]]; do
  case "$1" in
    --package-url) PACKAGE_URL="$2"; shift 2 ;;
    --domain) DOMAIN="$2"; shift 2 ;;
    --staging-domain) STAGING_DOMAIN="$2"; shift 2 ;;
    --admin-email) ADMIN_EMAIL="$2"; shift 2 ;;
    --admin-name) ADMIN_NAME="$2"; shift 2 ;;
    --acme-email) ACME_EMAIL="$2"; shift 2 ;;
    --non-interactive) NONINTERACTIVE=1; shift ;;
    --install-dir) INSTALL_DIR="$2"; shift 2 ;;
    -h|--help) usage; exit 0 ;;
    *) echo "Unknown argument: $1" >&2; usage; exit 1 ;;
  esac
done

[[ $EUID -eq 0 ]] || { echo "Run as root or with sudo." >&2; exit 1; }
[[ -n "$PACKAGE_URL" && -n "$DOMAIN" && -n "$ADMIN_EMAIL" ]] || { usage; exit 1; }
[[ -n "$STAGING_DOMAIN" ]] || STAGING_DOMAIN="apps.${DOMAIN#*.}"
[[ -n "$ACME_EMAIL" ]] || ACME_EMAIL="$ADMIN_EMAIL"

log(){ printf '\n\033[1;36m[ZT Deploy]\033[0m %s\n' "$*"; }
fail(){ echo "ERROR: $*" >&2; exit 1; }

install_base_tools() {
  if command -v apt-get >/dev/null 2>&1; then
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y ca-certificates curl unzip openssl gnupg
  elif command -v dnf >/dev/null 2>&1; then
    dnf -y install ca-certificates curl unzip openssl dnf-plugins-core
  elif command -v yum >/dev/null 2>&1; then
    yum -y install ca-certificates curl unzip openssl yum-utils
  else
    fail "Unsupported package manager. Supported: apt, dnf/yum."
  fi
}

install_docker() {
  command -v docker >/dev/null 2>&1 && docker compose version >/dev/null 2>&1 && return 0
  . /etc/os-release
  log "Installing Docker Engine from Docker's package repository for ${ID} ${VERSION_ID}..."

  if command -v apt-get >/dev/null 2>&1; then
    case "$ID" in
      ubuntu|debian) ;;
      *) fail "Automatic Docker install supports Ubuntu/Debian on apt systems. Install Docker manually, then rerun." ;;
    esac
    install -m 0755 -d /etc/apt/keyrings
    curl -fsSL "https://download.docker.com/linux/${ID}/gpg" -o /etc/apt/keyrings/docker.asc
    chmod a+r /etc/apt/keyrings/docker.asc
    codename="${UBUNTU_CODENAME:-${VERSION_CODENAME:-}}"
    [[ -n "$codename" ]] || fail "Unable to determine distribution codename."
    arch="$(dpkg --print-architecture)"
    cat > /etc/apt/sources.list.d/docker.sources <<APT
Types: deb
URIs: https://download.docker.com/linux/${ID}
Suites: ${codename}
Components: stable
Architectures: ${arch}
Signed-By: /etc/apt/keyrings/docker.asc
APT
    apt-get update
    DEBIAN_FRONTEND=noninteractive apt-get install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  else
    case "$ID" in
      centos|rhel|rocky|almalinux) ;;
      *) fail "Automatic Docker install supports RHEL-compatible dnf/yum systems. Install Docker manually, then rerun." ;;
    esac
    mgr=dnf; command -v dnf >/dev/null 2>&1 || mgr=yum
    $mgr config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
    $mgr -y install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
  fi

  systemctl enable --now docker
  docker version >/dev/null
  docker compose version >/dev/null
}

check_ports() {
  if command -v ss >/dev/null 2>&1; then
    if ss -lntH | awk '{print $4}' | grep -Eq '(^|:)(80|443)$'; then
      echo "Ports 80/443 are already in use:" >&2
      ss -lntp | grep -E ':(80|443)\b' >&2 || true
      fail "ZT Deploy raw-server package expects exclusive access to ports 80/443."
    fi
  fi
}

install_base_tools
install_docker
check_ports

TMP="$(mktemp -d)"
trap 'rm -rf "$TMP"' EXIT
ZIP="$TMP/package.zip"
SUM="$TMP/package.sha256"

log "Downloading release package..."
curl -fL --retry 3 --connect-timeout 15 "$PACKAGE_URL" -o "$ZIP"
curl -fL --retry 3 --connect-timeout 15 "${PACKAGE_URL}.sha256" -o "$SUM"
expected="$(awk 'NR==1{print $1}' "$SUM")"
actual="$(sha256sum "$ZIP" | awk '{print $1}')"
[[ "$expected" == "$actual" ]] || fail "Package checksum mismatch."
log "Checksum verified: ${actual}"

mkdir -p "$(dirname "$INSTALL_DIR")"
if [[ -d "$INSTALL_DIR" && -n "$(find "$INSTALL_DIR" -mindepth 1 -maxdepth 1 -print -quit 2>/dev/null)" ]]; then
  backup="${INSTALL_DIR}.backup-$(date +%Y%m%d-%H%M%S)"
  log "Existing install detected; backing it up to $backup"
  cp -a "$INSTALL_DIR" "$backup"
fi
rm -rf "$INSTALL_DIR"
mkdir -p "$INSTALL_DIR" "$TMP/extract"
unzip -q "$ZIP" -d "$TMP/extract"
source_dir="$(find "$TMP/extract" -mindepth 1 -maxdepth 1 -type d | head -1)"
[[ -n "$source_dir" ]] || fail "Invalid release archive."
cp -a "$source_dir/." "$INSTALL_DIR/"
cd "$INSTALL_DIR"

args=(--domain "$DOMAIN" --staging-domain "$STAGING_DOMAIN" --admin-email "$ADMIN_EMAIL" --admin-name "$ADMIN_NAME" --acme-email "$ACME_EMAIL")
[[ "$NONINTERACTIVE" -eq 1 ]] && args+=(--non-interactive)

log "Starting ZT Deploy installation..."
./install.sh "${args[@]}"
