#!/usr/bin/env bash

set -euo pipefail

MXC_REPO_HOST="${MXC_REPO_HOST:-repo.mxcentral.net}"
MXC_CHANNEL="${MXC_CHANNEL:-stable}"
KEYRING_PATH="/usr/share/keyrings/mxcentral-archive-keyring.gpg"
SOURCES_PATH="/etc/apt/sources.list.d/mxcentral.sources"
ENV_FILE_PATH="/etc/mxcentral/mxcentral.env"
MXC_DATA_DIR="${MXC_DATA_DIR:-/var/lib/mxcentral}"
MXC_PRIMARY_HOST="${MXC_PRIMARY_HOST:-}"
MXC_APP_HOST="${MXC_APP_HOST:-}"
MXC_API_HOST="${MXC_API_HOST:-}"
MXC_DOCS_HOST="${MXC_DOCS_HOST:-}"
MXC_DB_HOST="${MXC_DB_HOST:-127.0.0.1}"
MXC_DB_PORT="${MXC_DB_PORT:-3306}"
MXC_DB_NAME="${MXC_DB_NAME:-mxcentral}"
MXC_DB_USER="${MXC_DB_USER:-mxcentral}"
MXC_SOGO_DB_NAME="${MXC_SOGO_DB_NAME:-sogo}"
MXC_SOGO_DB_USER="${MXC_SOGO_DB_USER:-sogo}"

usage() {
  cat <<'EOF'
usage: install.sh [options]

Bootstraps MXCentral APT trust and source configuration, runs apt-get update,
and writes a starter /etc/mxcentral/mxcentral.env before package installation.

Examples:
  wget -qO - https://repo.mxcentral.net/install.sh | sudo bash
  wget -qO - https://repo.mxcentral.net/install.sh | sudo bash -s -- --channel testing
EOF
}

log() {
  printf '[mxcentral-install] %s\n' "$*"
}

die() {
  printf '[mxcentral-install] ERROR: %s\n' "$*" >&2
  exit 1
}

require_root() {
  [ "${EUID}" -eq 0 ] || die "run as root; for example: wget -qO - https://${MXC_REPO_HOST}/install.sh | sudo bash"
}

fetch_to_file() {
  local url="$1"
  local output_path="$2"

  if command -v curl > /dev/null 2>&1; then
    curl -fsSL "${url}" -o "${output_path}"
    return 0
  fi

  if command -v wget > /dev/null 2>&1; then
    wget -qO "${output_path}" "${url}"
    return 0
  fi

  die "curl or wget is required to fetch ${url}"
}

write_env_file() {
  local target="$1"
  local host_fqdn
  local host_short
  local tmp

  host_fqdn="$(hostname -f 2>/dev/null || true)"
  host_short="$(hostname 2>/dev/null || true)"

  if [ -z "${MXC_PRIMARY_HOST}" ]; then
    MXC_PRIMARY_HOST="${host_fqdn:-${host_short:-mxcentral.local}}"
  fi

  if [ -z "${MXC_APP_HOST}" ]; then
    MXC_APP_HOST="${MXC_PRIMARY_HOST}"
  fi

  if [ -z "${MXC_API_HOST}" ]; then
    MXC_API_HOST="${MXC_PRIMARY_HOST}"
  fi

  if [ -z "${MXC_DOCS_HOST}" ]; then
    MXC_DOCS_HOST="${MXC_PRIMARY_HOST}"
  fi

  mkdir -p "$(dirname "${target}")"
  tmp="$(mktemp "$(dirname "${target}")/.mxcentral.env.XXXXXX")"
  cat > "${tmp}" <<EOF
MXC_CHANNEL=${MXC_CHANNEL}
MXC_DATA_DIR=${MXC_DATA_DIR}
MXC_PRIMARY_HOST=${MXC_PRIMARY_HOST}
MXC_APP_HOST=${MXC_APP_HOST}
MXC_API_HOST=${MXC_API_HOST}
MXC_REPO_HOST=${MXC_REPO_HOST}
MXC_DOCS_HOST=${MXC_DOCS_HOST}
MXC_DB_HOST=${MXC_DB_HOST}
MXC_DB_PORT=${MXC_DB_PORT}
MXC_DB_NAME=${MXC_DB_NAME}
MXC_DB_USER=${MXC_DB_USER}
MXC_SOGO_DB_NAME=${MXC_SOGO_DB_NAME}
MXC_SOGO_DB_USER=${MXC_SOGO_DB_USER}
MXC_FIRST_RUN_REQUIRED=1
EOF
  mv "${tmp}" "${target}"
  chmod 0600 "${target}"
}

while [ "$#" -gt 0 ]; do
  case "$1" in
    --channel)
      MXC_CHANNEL="$2"
      shift 2
      ;;
    --repo-host)
      MXC_REPO_HOST="$2"
      shift 2
      ;;
    --env-file)
      ENV_FILE_PATH="$2"
      shift 2
      ;;
    --data-dir)
      MXC_DATA_DIR="$2"
      shift 2
      ;;
    --primary-host)
      MXC_PRIMARY_HOST="$2"
      shift 2
      ;;
    --app-host)
      MXC_APP_HOST="$2"
      shift 2
      ;;
    --api-host)
      MXC_API_HOST="$2"
      shift 2
      ;;
    --docs-host)
      MXC_DOCS_HOST="$2"
      shift 2
      ;;
    --db-host)
      MXC_DB_HOST="$2"
      shift 2
      ;;
    --db-port)
      MXC_DB_PORT="$2"
      shift 2
      ;;
    --db-name)
      MXC_DB_NAME="$2"
      shift 2
      ;;
    --db-user)
      MXC_DB_USER="$2"
      shift 2
      ;;
    --sogo-db-name)
      MXC_SOGO_DB_NAME="$2"
      shift 2
      ;;
    --sogo-db-user)
      MXC_SOGO_DB_USER="$2"
      shift 2
      ;;
    --help|-h)
      usage
      exit 0
      ;;
    *)
      die "unknown argument: $1"
      ;;
  esac
done

case "${MXC_CHANNEL}" in
  stable|testing)
    ;;
  *)
    die "unsupported channel: ${MXC_CHANNEL}"
    ;;
esac

require_root

log "ensuring APT prerequisites are installed"
apt-get update
apt-get install -y ca-certificates

if command -v debconf-set-selections > /dev/null 2>&1; then
  log "preseeding Postfix for MXCentral-managed mailstack configuration"
  printf '%s\n' 'postfix postfix/main_mailer_type select No configuration' | debconf-set-selections
  printf '%s\n' 'postfix postfix/mailname string localhost' | debconf-set-selections
fi

log "installing MXCentral archive keyring"
mkdir -p "$(dirname "${KEYRING_PATH}")"
fetch_to_file "https://${MXC_REPO_HOST}/mxcentral-archive-keyring.gpg" "${KEYRING_PATH}"
chmod 0644 "${KEYRING_PATH}"

log "writing ${SOURCES_PATH}"
mkdir -p "$(dirname "${SOURCES_PATH}")"
cat > "${SOURCES_PATH}" <<EOF
# Managed by mxcentral-release
Types: deb
URIs: https://${MXC_REPO_HOST}/apt
Suites: ${MXC_CHANNEL}
Components: main
Signed-By: ${KEYRING_PATH}
EOF
chmod 0644 "${SOURCES_PATH}"

log "writing starter MXCentral environment to ${ENV_FILE_PATH}"
write_env_file "${ENV_FILE_PATH}"

log "refreshing APT metadata"
apt-get update

cat <<EOF

MXCentral repository bootstrap is complete.

Next step:
  apt-get install mxcentral-release mxcentral-server

Current channel:
  ${MXC_CHANNEL}

Configured source:
  ${SOURCES_PATH}

Starter env file:
  ${ENV_FILE_PATH}
EOF
