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

APP_NAME="imonitor"
APP_VERSION="1.2.1"
INSTALLER_URL="https://irnmo.ir/download/imonitor/install.sh"
DOWNLOAD_BASE_URL="https://irnmo.ir/download/imonitor"
INSTALL_ROOT="/opt/imonitor"
BIN_DIR="${INSTALL_ROOT}/bin"
RUNTIME_DIR="${INSTALL_ROOT}/runtime"
SERVICE_NAME="imonitor"
SYSTEMD_UNIT="/etc/systemd/system/${SERVICE_NAME}.service"
OPENRC_SCRIPT="/etc/init.d/${SERVICE_NAME}"
LISTEN_ADDR="${IMONITOR_LISTEN_ADDR:-0.0.0.0:6060}"
ADMIN_USER="${IMONITOR_ADMIN_USER:-admin}"
ADMIN_PASSWORD="${IMONITOR_ADMIN_PASSWORD:-}"
ASKED_FOR_SETUP=0
EXISTING_INSTALL=0
DETECTED_SERVICE_NAME=""
DETECTED_SERVICE_FILE=""
DETECTED_BINARY_PATH=""
ASCII_ART="$(cat <<'EOF'
================================================================================
                                ≠≈∞∞∞≈                                      
                        ∞≈≈≈≈∞≈=÷÷÷÷÷=≠≈√√∞∞∞   π  √                        
                  ≈≈≈≈≈≠=÷÷÷=≠≈≈≈≈∞∞∞∞∞∞≈≠==≠≈√≈∞ -∞√π∞√√√                  
              ≠≠==××==≈≠≈≠≈∞              ≈≈∞≈≠÷=≠=  ≈≠==≠≈√√√              
           ≈≠=÷×÷=≠≠≈                         √≈≠÷÷≠≈  ≈√≈≠÷÷≠≈√=           
       =≠≠=÷×÷=≠≠-    =≠≈∞√        π≈∞∞∞≈∞∞√    ∞≠=÷≠=    π√≈≠==≠∞√√        
     ==÷××÷==≠      ≈≠÷÷÷≠         ∞=÷×÷÷÷÷=≈√    ≈÷÷÷≈      ∞∞∞≈≠÷≠∞∞√     
   ≠=÷×××=≠         ≠×××=   ≠≈≈≠≠≠  -÷×÷÷×÷÷÷=∞   ≠÷÷÷=√         √≠÷÷÷≠∞÷   
 ≈≠÷××-×-          ÷=×××=   ≠×××÷=≠≠÷×÷×××÷××÷∞   ≈÷÷÷÷≈          ÷=÷÷÷=∞   
   =÷÷××÷==         =×××=   ≈=÷××××××÷××÷××÷÷=∞   ≠÷÷÷=∞        ≠≈≠÷÷=≈∞√   
     ===÷×÷÷=≠      ≠÷××÷=    ≠=÷××××××××××÷≠≠    ≠÷=≈∞      √∞≈≠=÷≠∞∞      
        ==÷÷×÷÷==÷   ÷÷÷×÷=     ≠≠≠≠≠≠≠≈≠≈≠≈    π∞∞≈∞     ∞∞≈=÷÷=≈∞≈        
           ≠==÷××÷===  =÷×÷=≠                         √∞≈≠=÷÷=≠∞∞           
              ÷==÷÷×÷÷× -÷÷×÷=≠==÷             ≠==≈≈≈≠=÷÷=≠≈≈               
                  ====≠≠÷  ×≠≠=÷÷÷=≠≠≠≠≠≈≠≠≠≈≠÷÷÷×÷=≠≈≈≈≠≠                  
                        =≠≠    ≠≠=≠≠=÷÷×××÷=≠≈≠≠≠≠≠                         
================================================================================
EOF
)"

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

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

trim() {
  local value="$1"
  value="${value#"${value%%[![:space:]]*}"}"
  value="${value%"${value##*[![:space:]]}"}"
  printf '%s' "${value}"
}

print_banner() {
  printf '%s\n' "${ASCII_ART}" | awk -v start="1e3e87" -v end="5fbfcf" '
    function hex2dec(h) { return strtonum("0x" h); }
    function clamp(x) { return (x < 0 ? 0 : (x > 255 ? 255 : x)); }
    function leading_indent(line,    i, ch) {
      for (i = 1; i <= length(line); i++) {
        ch = substr(line, i, 1);
        if (ch != " " && ch != "\t") return i - 1;
      }
      return length(line);
    }
    BEGIN {
      sr = hex2dec(substr(start,1,2)); sg = hex2dec(substr(start,3,2)); sb = hex2dec(substr(start,5,2));
      er = hex2dec(substr(end,1,2));   eg = hex2dec(substr(end,3,2));   eb = hex2dec(substr(end,5,2));
    }
    {
      sub(/[[:space:]]+$/, "", $0);
      lines[NR] = $0;
    }
    END {
      indent = -1;
      total = NR;
      for (l = 1; l <= total; l++) {
        if (lines[l] ~ /^[[:space:]]*$/) continue;
        current = leading_indent(lines[l]);
        if (indent < 0 || current < indent) indent = current;
      }
      if (indent < 0) indent = 0;
      for (l = 1; l <= total; l++) {
        line = substr(lines[l], indent + 1);
        n = length(line);
        if (n == 0) { print ""; continue; }
        for (i = 1; i <= n; i++) {
          ch = substr(line, i, 1);
          if (ch == " ") { printf " "; continue; }
          tline = (total <= 1) ? 0 : (l - 1) / (total - 1);
          tcol = (n <= 1) ? 0 : 1 - ((i - 1) / (n - 1));
          t = (tline + tcol) / 2;
          r = clamp(int(sr + (er - sr) * t));
          g = clamp(int(sg + (eg - sg) * t));
          b = clamp(int(sb + (eb - sb) * t));
          printf "\033[38;2;%d;%d;%dm%s", r, g, b, ch;
        }
        printf "\033[0m\n";
      }
    }'
  printf '\033[38;2;30;62;135miMonitor V%s Installer\033[0m\n\n' "${APP_VERSION}"
}

need_root() {
  if [ "$(id -u)" -eq 0 ]; then
    return 0
  fi
  if command -v sudo >/dev/null 2>&1; then
    log "root access is required; retrying with sudo"
    exec sudo -E bash -c "$(curl -fsSL "${INSTALLER_URL}")"
  fi
  fail "please run this installer as root"
}

detect_arch() {
  case "$(uname -m)" in
    x86_64|amd64) printf 'amd64' ;;
    *) return 1 ;;
  esac
}

detect_service_manager() {
  if command -v systemctl >/dev/null 2>&1 && [ -d /run/systemd/system ]; then
    printf 'systemd'
    return 0
  fi
  if command -v rc-service >/dev/null 2>&1 && command -v rc-update >/dev/null 2>&1; then
    printf 'openrc'
    return 0
  fi
  printf 'none'
}

detect_existing_install() {
  local exec_line service_file runtime_candidate listen_candidate binary_candidate

  if [ -f "${SYSTEMD_UNIT}" ]; then
    service_file="${SYSTEMD_UNIT}"
  elif [ -f "/lib/systemd/system/${SERVICE_NAME}.service" ]; then
    service_file="/lib/systemd/system/${SERVICE_NAME}.service"
  elif [ -f "/etc/systemd/system/iranmonitor-node.service" ]; then
    service_file="/etc/systemd/system/iranmonitor-node.service"
  elif [ -f "/lib/systemd/system/iranmonitor-node.service" ]; then
    service_file="/lib/systemd/system/iranmonitor-node.service"
  elif [ -f "${OPENRC_SCRIPT}" ]; then
    service_file="${OPENRC_SCRIPT}"
  elif [ -f "/etc/init.d/iranmonitor-node" ]; then
    service_file="/etc/init.d/iranmonitor-node"
  else
    service_file=""
  fi

  if [ -n "${service_file}" ]; then
    DETECTED_SERVICE_FILE="${service_file}"
    DETECTED_SERVICE_NAME="$(basename "${service_file}")"
    exec_line="$(grep -E '^(ExecStart=|command_args=)' "${service_file}" 2>/dev/null | head -n1 || true)"
    runtime_candidate="$(printf '%s\n' "${exec_line}" | sed -n 's/.*--data-dir[ =]\([^ "][^ ]*\).*/\1/p' | head -n1)"
    listen_candidate="$(printf '%s\n' "${exec_line}" | sed -n 's/.*--listen[ =]\([^ "][^ ]*\).*/\1/p' | head -n1)"
    binary_candidate="$(printf '%s\n' "${exec_line}" | sed -n 's/.*ExecStart=\([^ ]*\).*/\1/p' | head -n1)"

    if [ -n "${runtime_candidate}" ]; then
      RUNTIME_DIR="${runtime_candidate}"
      INSTALL_ROOT="$(dirname "${RUNTIME_DIR}")"
      BIN_DIR="${INSTALL_ROOT}/bin"
    fi
    if [ -n "${listen_candidate}" ]; then
      LISTEN_ADDR="${listen_candidate}"
    fi
    if [ -n "${binary_candidate}" ] && [ -x "${binary_candidate}" ]; then
      DETECTED_BINARY_PATH="${binary_candidate}"
      BIN_DIR="$(dirname "${binary_candidate}")"
      INSTALL_ROOT="$(dirname "${BIN_DIR}")"
      if [ -z "${runtime_candidate}" ]; then
        RUNTIME_DIR="${INSTALL_ROOT}/runtime"
      fi
    fi
  fi

  if [ ! -f "${RUNTIME_DIR}/iranmonitor.db" ]; then
    for candidate in \
      "/opt/imonitor/runtime" \
      "/usr/local/runtime" \
      "/var/www/imonitor/1.0/runtime" \
      "/var/www/iranmonitor/node_runtime" \
      "/opt/iranmonitor-node/runtime"
    do
      if [ -f "${candidate}/iranmonitor.db" ]; then
        RUNTIME_DIR="${candidate}"
        INSTALL_ROOT="$(dirname "${RUNTIME_DIR}")"
        if [ -d "${INSTALL_ROOT}/bin" ]; then
          BIN_DIR="${INSTALL_ROOT}/bin"
        fi
        break
      fi
    done
  fi

  if [ ! -f "${RUNTIME_DIR}/iranmonitor.db" ] && [ -z "${service_file}" ]; then
    return 1
  fi

  EXISTING_INSTALL=1
  return 0
}

disable_conflicting_service() {
  if ! command -v systemctl >/dev/null 2>&1; then
    return 0
  fi

  if [ -n "${DETECTED_SERVICE_NAME}" ] && [ "${DETECTED_SERVICE_NAME}" = "iranmonitor-node.service" ]; then
    if systemctl list-unit-files imonitor.service >/dev/null 2>&1; then
      systemctl disable --now imonitor.service >/dev/null 2>&1 || true
    fi
  elif [ -n "${DETECTED_SERVICE_NAME}" ] && [ "${DETECTED_SERVICE_NAME}" = "imonitor.service" ]; then
    if systemctl list-unit-files iranmonitor-node.service >/dev/null 2>&1; then
      systemctl disable --now iranmonitor-node.service >/dev/null 2>&1 || true
    fi
  fi
}

detect_package_manager() {
  for manager in apt-get dnf yum zypper pacman apk; do
    if command -v "${manager}" >/dev/null 2>&1; then
      printf '%s' "${manager}"
      return 0
    fi
  done
  return 1
}

write_cli_launcher() {
  local target_binary_path="$1"
  rm -f /usr/local/bin/imonitor
  cat > /usr/local/bin/imonitor <<EOF
#!/usr/bin/env bash
exec "${target_binary_path}" "\$@"
EOF
  chmod 0755 /usr/local/bin/imonitor
}

cache_local_installer() {
  local local_installer="${INSTALL_ROOT}/install.sh"
  if [ -r "$0" ]; then
    cat "$0" > "${local_installer}"
  else
    curl -fsSL "${INSTALLER_URL}" -o "${local_installer}" || return 0
  fi
  chmod 0700 "${local_installer}"
}

install_packages() {
  local pm="$1"
  local failed=()
  local pkgs
  log "installing required packages with ${pm}"
  case "${pm}" in
    apt-get)
      export DEBIAN_FRONTEND=noninteractive
      if ! apt-get update -y; then
        printf '\033[0;31m[iMonitor] warning: apt-get update failed; continuing with the existing package metadata.\033[0m\n' >&2
      fi
      pkgs=(ca-certificates curl unzip sqlite3 iproute2 iputils-ping iptables iperf3 dnsutils openssh-client openssh-server socat procps wireguard-tools)
      if ! apt-get install -y "${pkgs[@]}"; then
        for pkg in "${pkgs[@]}"; do
          if ! apt-get install -y "${pkg}" >/dev/null 2>&1; then
            failed+=("${pkg}")
          fi
        done
      fi
      ;;
    dnf)
      pkgs=(ca-certificates curl unzip sqlite iproute iputils iptables iperf3 bind-utils openssh-clients openssh-server socat procps-ng wireguard-tools)
      if ! dnf install -y "${pkgs[@]}"; then
        for pkg in "${pkgs[@]}"; do
          if ! dnf install -y "${pkg}" >/dev/null 2>&1; then
            failed+=("${pkg}")
          fi
        done
      fi
      ;;
    yum)
      pkgs=(ca-certificates curl unzip sqlite iproute iputils iptables iperf3 bind-utils openssh-clients openssh-server socat procps-ng wireguard-tools)
      if ! yum install -y "${pkgs[@]}"; then
        for pkg in "${pkgs[@]}"; do
          if ! yum install -y "${pkg}" >/dev/null 2>&1; then
            failed+=("${pkg}")
          fi
        done
      fi
      ;;
    zypper)
      if ! zypper --non-interactive refresh; then
        printf '\033[0;31m[iMonitor] warning: zypper refresh failed; continuing with the existing package metadata.\033[0m\n' >&2
      fi
      pkgs=(ca-certificates curl unzip sqlite3 iproute2 iputils iptables iperf3 bind-utils openssh-clients openssh socat procps wireguard-tools)
      if ! zypper --non-interactive install "${pkgs[@]}"; then
        for pkg in "${pkgs[@]}"; do
          if ! zypper --non-interactive install "${pkg}" >/dev/null 2>&1; then
            failed+=("${pkg}")
          fi
        done
      fi
      ;;
    pacman)
      pkgs=(ca-certificates curl unzip sqlite iproute2 iputils iptables iperf3 bind openssh socat procps-ng wireguard-tools)
      if ! pacman -Sy --noconfirm "${pkgs[@]}"; then
        for pkg in "${pkgs[@]}"; do
          if ! pacman -Sy --noconfirm "${pkg}" >/dev/null 2>&1; then
            failed+=("${pkg}")
          fi
        done
      fi
      ;;
    apk)
      pkgs=(ca-certificates curl unzip sqlite iproute2 iputils iptables iperf3 bind-tools openssh-client openssh-server socat procps wireguard-tools openrc)
      if ! apk add --no-cache "${pkgs[@]}"; then
        for pkg in "${pkgs[@]}"; do
          if ! apk add --no-cache "${pkg}" >/dev/null 2>&1; then
            failed+=("${pkg}")
          fi
        done
      fi
      ;;
    *)
      fail "unsupported package manager: ${pm}"
      ;;
  esac

  if [ "${#failed[@]}" -gt 0 ]; then
    printf '\033[0;31m[iMonitor] warning: these packages failed to install automatically:\n' >&2
    printf '\033[0;31m - %s\033[0m\n' "${failed[@]}" >&2
    printf '\033[0;31mPlease install them manually if you need related features.\033[0m\n' >&2
  fi
}

write_systemd_unit() {
  if [ "${EXISTING_INSTALL}" -eq 1 ] && [ -n "${DETECTED_SERVICE_NAME}" ] && [ "${DETECTED_SERVICE_NAME}" != "${SERVICE_NAME}.service" ]; then
    systemctl daemon-reload
    systemctl restart "${DETECTED_SERVICE_NAME}"
    return 0
  fi
  cat > "${SYSTEMD_UNIT}" <<EOF
[Unit]
Description=iMonitor V1.2.1
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
WorkingDirectory=${RUNTIME_DIR}
ExecStart=${BIN_DIR}/imonitor serve --db ${RUNTIME_DIR}/iranmonitor.db --data-dir ${RUNTIME_DIR} --listen ${LISTEN_ADDR}
Restart=always
RestartSec=5
User=root
Group=root
PrivateTmp=true
ProtectHome=true
ProtectControlGroups=true
ProtectKernelLogs=true
ProtectKernelModules=true
ProtectSystem=full
ReadWritePaths=${RUNTIME_DIR}
RestrictSUIDSGID=true
LockPersonality=true

[Install]
WantedBy=multi-user.target
EOF
  systemctl daemon-reload
  systemctl enable --now "${SERVICE_NAME}.service"
}

write_openrc_service() {
  if [ "${EXISTING_INSTALL}" -eq 1 ] && [ -n "${DETECTED_SERVICE_NAME}" ] && [ "${DETECTED_SERVICE_NAME}" != "${SERVICE_NAME}" ]; then
    rc-service "${DETECTED_SERVICE_NAME}" restart || rc-service "${DETECTED_SERVICE_NAME}" start
    return 0
  fi
  cat > "${OPENRC_SCRIPT}" <<'EOF'
#!/sbin/openrc-run
name="iMonitor V1.2.1"
description="iMonitor monitoring and tunnel node"
command="/opt/imonitor/bin/imonitor"
command_args="serve --db /opt/imonitor/runtime/iranmonitor.db --data-dir /opt/imonitor/runtime --listen __LISTEN_ADDR__"
command_background="yes"
pidfile="/run/imonitor.pid"
directory="/opt/imonitor/runtime"
output_log="/var/log/imonitor.log"
error_log="/var/log/imonitor.err"
depend() {
  need net
}
EOF
  sed -i "s#__LISTEN_ADDR__#${LISTEN_ADDR}#g" "${OPENRC_SCRIPT}"
  chmod 0755 "${OPENRC_SCRIPT}"
  rc-update add "${SERVICE_NAME}" default
  rc-service "${SERVICE_NAME}" restart || rc-service "${SERVICE_NAME}" start
}

generate_password() {
  local password=""
  while [ "${#password}" -lt 16 ]; do
    password="$(tr -dc 'A-Za-z0-9' </dev/urandom | head -c 16 || true)"
  done
  printf '%s' "${password}"
}

panel_host() {
  local host_ip=""
  host_ip="$(hostname -I 2>/dev/null | awk '{print $1}')"
  host_ip="$(trim "${host_ip}")"
  if [ -z "${host_ip}" ]; then
    host_ip="127.0.0.1"
  fi
  printf '%s' "${host_ip}"
}

prompt_for_setup() {
  local port_input username_input password_input confirm_input
  [ -t 0 ] || return 0

  ASKED_FOR_SETUP=1
  if [ "${EXISTING_INSTALL}" -eq 1 ]; then
    printf 'Update setup\n'
    printf 'Existing iMonitor service detected. Current runtime and port will be preserved automatically.\n\n'
    return 0
  fi

  printf 'Interactive setup\n'
  printf 'Press Enter to keep defaults shown in brackets.\n\n'

  read -r -p "Panel port [${LISTEN_ADDR##*:}]: " port_input || true
  port_input="${port_input//[[:space:]]/}"
  if [ -n "${port_input}" ]; then
    case "${port_input}" in
      ''|*[!0-9]*)
        fail "panel port must be a number"
        ;;
    esac
    if [ "${port_input}" -lt 1 ] || [ "${port_input}" -gt 65535 ]; then
      fail "panel port must be between 1 and 65535"
    fi
    LISTEN_ADDR="0.0.0.0:${port_input}"
  fi

  read -r -p "Admin username [${ADMIN_USER}]: " username_input || true
  if [ -n "${username_input}" ]; then
    ADMIN_USER="${username_input}"
  fi

  read -r -s -p "Admin password [auto-generate if empty]: " password_input || true
  printf '\n'
  if [ -n "${password_input}" ]; then
    read -r -s -p "Confirm admin password: " confirm_input || true
    printf '\n'
    if [ "${password_input}" != "${confirm_input}" ]; then
      fail "password confirmation does not match"
    fi
    ADMIN_PASSWORD="${password_input}"
  fi

  printf '\n'
}

main() {
  need_root
  print_banner

  local arch service_manager package_manager bundle_name bundle_url sums_url tmp_dir bundle_path binary_path target_binary_path init_output fresh_install bpf_bundle_name bpf_bundle_url bpf_bundle_path
  arch="$(detect_arch)" || fail "unsupported architecture: $(uname -m)"
  service_manager="$(detect_service_manager)"
  [ "${service_manager}" != "none" ] || fail "this installer currently supports systemd or openrc based Linux distributions"
  package_manager="$(detect_package_manager)" || fail "could not detect a supported package manager"
  fresh_install=0

  detect_existing_install || true
  disable_conflicting_service
  prompt_for_setup

  bundle_name="imonitor-linux-${arch}.zip"
  bundle_url="${DOWNLOAD_BASE_URL}/${bundle_name}"
  sums_url="${DOWNLOAD_BASE_URL}/sha256sums.txt"
  bpf_bundle_name="imonitor-bpf-${arch}.zip"
  bpf_bundle_url="${DOWNLOAD_BASE_URL}/${bpf_bundle_name}"
  tmp_dir="$(mktemp -d)"
  bundle_path="${tmp_dir}/${bundle_name}"
  bpf_bundle_path="${tmp_dir}/${bpf_bundle_name}"

  trap "rm -rf '${tmp_dir}'" EXIT

  install_packages "${package_manager}"

  mkdir -p "${BIN_DIR}" "${RUNTIME_DIR}"
  chmod 0700 "${INSTALL_ROOT}" "${BIN_DIR}" "${RUNTIME_DIR}"

  log "downloading private iMonitor bundle"
  curl -fsSL "${bundle_url}" -o "${bundle_path}"
  curl -fsSL "${sums_url}" -o "${tmp_dir}/sha256sums.txt"
  (
    cd "${tmp_dir}"
    sha256sum -c "sha256sums.txt" --ignore-missing
  )

  unzip -oq "${bundle_path}" -d "${tmp_dir}/bundle"
  binary_path="${tmp_dir}/bundle/imonitor"
  [ -f "${binary_path}" ] || fail "downloaded bundle did not contain the imonitor binary"

  target_binary_path="${BIN_DIR}/imonitor"
  if [ -n "${DETECTED_BINARY_PATH}" ]; then
    target_binary_path="${DETECTED_BINARY_PATH}"
  fi

  mkdir -p "$(dirname "${target_binary_path}")"
  install -m 0755 "${binary_path}" "${target_binary_path}"
  if [ "${target_binary_path}" != "${BIN_DIR}/imonitor" ]; then
    mkdir -p "${BIN_DIR}"
    install -m 0755 "${binary_path}" "${BIN_DIR}/imonitor"
  fi
  write_cli_launcher "${target_binary_path}"
  cache_local_installer

  log "downloading source ip engine bundle"
  if curl -fsSL "${bpf_bundle_url}" -o "${bpf_bundle_path}"; then
    unzip -oq "${bpf_bundle_path}" -d "${tmp_dir}/bpf"
    if [ -f "${tmp_dir}/bpf/imonitor-bpf" ]; then
      install -m 0700 "${tmp_dir}/bpf/imonitor-bpf" "${BIN_DIR}/imonitor-bpf"
      chown root:root "${BIN_DIR}/imonitor-bpf" 2>/dev/null || true
      mkdir -p "${INSTALL_ROOT}/bpf"
      cp -f "${tmp_dir}/bpf/"*.o "${INSTALL_ROOT}/bpf/" 2>/dev/null || true
      log "source ip engine installed"
    else
      log "warning: source ip engine bundle missing imonitor-bpf binary"
    fi
  else
    log "warning: source ip engine bundle not available; source ip rules will remain inactive"
  fi

  if [ ! -f "${RUNTIME_DIR}/iranmonitor.db" ]; then
    fresh_install=1
    if [ -z "${ADMIN_PASSWORD}" ]; then
      ADMIN_PASSWORD="$(generate_password)"
    fi
    log "initializing iMonitor runtime"
    init_output="$("${BIN_DIR}/imonitor" init --db "${RUNTIME_DIR}/iranmonitor.db" --data-dir "${RUNTIME_DIR}" --listen "${LISTEN_ADDR}" --username "${ADMIN_USER}" --password "${ADMIN_PASSWORD}" --plan free)"
    printf '%s\n' "${init_output}" > "${RUNTIME_DIR}/install-init.json"
    chmod 0600 "${RUNTIME_DIR}/install-init.json"
  else
    log "existing runtime detected at ${RUNTIME_DIR}; preserving current database and admin credentials"
  fi

  case "${service_manager}" in
    systemd) write_systemd_unit ;;
    openrc) write_openrc_service ;;
  esac

  if [ "${EXISTING_INSTALL}" -eq 1 ]; then
    log "update completed"
    if [ -n "${DETECTED_SERVICE_NAME}" ]; then
      log "updated service: ${DETECTED_SERVICE_NAME}"
    fi
    log "updated binary: ${target_binary_path}"
  else
    log "installation completed"
  fi
  log "panel address: http://$(panel_host):${LISTEN_ADDR##*:}/admin/login"
  if [ "${fresh_install}" -eq 1 ]; then
    log "admin username: ${ADMIN_USER}"
    log "admin password: ${ADMIN_PASSWORD}"
  fi
  log "for the local CLI management panel, run: imonitor"
}

main "$@"
