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

INSTALL_DIR="${GENIEACS_INSTALL_DIR:-/opt/genieacs}"
LOCAL_MODE="${GENIEACS_LOCAL_MODE:-0}"
NON_INTERACTIVE="${GENIEACS_NON_INTERACTIVE:-0}"
REPAIR_MODE="${GENIEACS_REPAIR:-0}"
GENIEACS_VERSION="${GENIEACS_VERSION:-1.2.16}"
SYSTEMD_PREFIX="${GENIEACS_SYSTEMD_PREFIX:-genieacs}"
RUN_USER="${GENIEACS_RUN_USER:-genieacs}"

UI_PORT="${GENIEACS_UI_PORT:-3000}"
CWMP_PORT="${GENIEACS_CWMP_PORT:-7547}"
NBI_PORT="${GENIEACS_NBI_PORT:-7557}"
FS_PORT="${GENIEACS_FS_PORT:-7567}"
BIND_IP="${GENIEACS_BIND_IP:-0.0.0.0}"

MONGO_HOST="${GENIEACS_MONGO_HOST:-127.0.0.1}"
MONGO_PORT="${GENIEACS_MONGO_PORT:-27017}"
MONGO_DB="${GENIEACS_MONGO_DB:-genieacs}"
MONGO_USER="${GENIEACS_MONGO_USER:-genieacs}"
MONGO_PASSWORD="${GENIEACS_MONGO_PASSWORD:-}"
MONGO_ADMIN_PASSWORD="${GENIEACS_MONGO_ADMIN_PASSWORD:-}"

NBI_PROTECT="${GENIEACS_NBI_PROTECT:-0}"
NBI_USER="${GENIEACS_NBI_USER:-}"
NBI_PASS="${GENIEACS_NBI_PASS:-}"
NBI_PUBLIC_PORT="${GENIEACS_NBI_PUBLIC_PORT:-}"
NBI_INTERNAL_PORT=""

UI_JWT_SECRET="${GENIEACS_UI_JWT_SECRET:-}"
LOG_LEVEL="${GENIEACS_LOG_LEVEL:-info}"

MONGO_BUNDLE_VERSION="${GENIEACS_MONGO_BUNDLE_VERSION:-7.0.18}"
MONGO_BUNDLE_URL="https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2204-${MONGO_BUNDLE_VERSION}.tgz"
MONGO_MODE="${GENIEACS_MONGO_MODE:-auto}"
MONGO_SYSTEMD_UNIT="mongod.service"

log() { printf '[genieacs-install] %s\n' "$*"; }
die() { echo "[genieacs-install] erro: $*" >&2; exit 1; }

prompt_yes_no() {
  local question="$1"
  local default="${2:-n}"
  if [[ "$NON_INTERACTIVE" == "1" ]]; then
    [[ "$default" == "y" ]] && return 0 || return 1
  fi
  local hint="s/N"
  [[ "$default" == "y" ]] && hint="S/n"
  local answer
  read -r -p "${question} [${hint}]: " answer || true
  answer="${answer:-$default}"
  [[ "$answer" =~ ^[sSyY] ]]
}

prompt_value() {
  local question="$1"
  local default="$2"
  if [[ "$NON_INTERACTIVE" == "1" ]]; then
    printf '%s' "$default"
    return
  fi
  local answer
  read -r -p "${question} [${default}]: " answer || true
  if [[ -z "$answer" ]]; then
    printf '%s' "$default"
  else
    printf '%s' "$answer"
  fi
}

prompt_secret() {
  local question="$1"
  local default="${2:-}"
  if [[ "$NON_INTERACTIVE" == "1" ]]; then
    printf '%s' "$default"
    return
  fi
  local answer
  read -r -s -p "${question}: " answer || true
  echo >&2
  if [[ -z "$answer" ]]; then
    printf '%s' "$default"
  else
    printf '%s' "$answer"
  fi
}

rand_secret() {
  if command -v openssl >/dev/null 2>&1; then
    openssl rand -hex 24
  else
    tr -dc 'a-zA-Z0-9' </dev/urandom | head -c 48
  fi
}

require_cmd() {
  command -v "$1" >/dev/null 2>&1 || die "comando obrigatório ausente: $1"
}

detect_ubuntu() {
  if [[ -f /etc/os-release ]]; then
    # shellcheck disable=SC1091
    . /etc/os-release
    if [[ "${ID:-}" != "ubuntu" ]]; then
      log "aviso: testado em Ubuntu 22.04/24.04 (detectado: ${PRETTY_NAME:-desconhecido})"
    fi
    UBUNTU_VERSION_ID="${VERSION_ID:-}"
  else
    UBUNTU_VERSION_ID=""
  fi
}

mongo_repo_version() {
  case "${UBUNTU_VERSION_ID}" in
    22.04) printf '%s' "7.0" ;;
    24.04) printf '%s' "8.0" ;;
    *) printf '%s' "8.0" ;;
  esac
}

mongo_repo_codename() {
  case "${UBUNTU_VERSION_ID}" in
    22.04) printf '%s' "jammy" ;;
    24.04) printf '%s' "noble" ;;
    *) printf '%s' "noble" ;;
  esac
}

kernel_mongo_incompatible() {
  local major minor
  major="$(uname -r | cut -d. -f1)"
  minor="$(uname -r | cut -d. -f2)"
  if (( major > 6 )) || (( major == 6 && minor >= 19 )); then
    return 0
  fi
  return 1
}

resolve_mongo_mode() {
  case "$MONGO_MODE" in
    apt|bundle) return 0 ;;
    auto)
      if kernel_mongo_incompatible; then
        MONGO_MODE="bundle"
        log "kernel $(uname -r): MongoDB via apt incompatível, usando bundle"
      else
        MONGO_MODE="apt"
      fi
      ;;
    *)
      die "GENIEACS_MONGO_MODE inválido: ${MONGO_MODE} (use auto, apt ou bundle)"
      ;;
  esac
}

port_in_use() {
  local port="$1"
  ss -ltn 2>/dev/null | grep -q ":${port} "
}

port_owner() {
  local port="$1"
  ss -ltnp 2>/dev/null | awk -v p=":${port} " '$0 ~ p {print $0; exit}'
}

install_node_if_needed() {
  if command -v node >/dev/null 2>&1; then
    local major
    major="$(node -p 'process.versions.node.split(".")[0]')"
    if [[ "$major" -ge 18 ]]; then
      log "node $(node -v) ok"
      return
    fi
    log "node $(node -v) abaixo do mínimo (18+)"
  fi
  if [[ "$LOCAL_MODE" == "1" ]]; then
    die "instale Node.js 18+ antes de continuar"
  fi
  require_cmd curl
  curl -fsSL https://deb.nodesource.com/setup_20.x | bash -
  apt-get install -y nodejs
}

install_mongo_bundle() {
  local mongo_root="${INSTALL_DIR}/mongodb"
  local mongo_bin="${mongo_root}/bin/mongod"
  if [[ ! -x "$mongo_bin" ]]; then
    log "baixando MongoDB ${MONGO_BUNDLE_VERSION} (bundle)"
    mkdir -p "${INSTALL_DIR}/cache"
    local archive="${INSTALL_DIR}/cache/mongo.tgz"
    curl -fsSL "$MONGO_BUNDLE_URL" -o "$archive"
    rm -rf "${INSTALL_DIR}/cache/mongo-extract"
    mkdir -p "${INSTALL_DIR}/cache/mongo-extract"
    tar -xzf "$archive" -C "${INSTALL_DIR}/cache/mongo-extract" --strip-components=1
    rm -rf "$mongo_root"
    mv "${INSTALL_DIR}/cache/mongo-extract" "$mongo_root"
  fi
}

write_mongo_bundle_config() {
  local conf="${INSTALL_DIR}/mongod.conf"
  mkdir -p "${INSTALL_DIR}/mongo-data" "${INSTALL_DIR}/log" "${INSTALL_DIR}/run"
  cat >"$conf" <<EOF
storage:
  dbPath: ${INSTALL_DIR}/mongo-data
systemLog:
  destination: file
  path: ${INSTALL_DIR}/log/mongod.log
  logAppend: true
net:
  bindIp: ${MONGO_HOST}
  port: ${MONGO_PORT}
processManagement:
  fork: true
  pidFilePath: ${INSTALL_DIR}/run/mongod.pid
EOF
}

ensure_mongo_bundle_permissions() {
  id "$RUN_USER" >/dev/null 2>&1 || useradd --system --home "$INSTALL_DIR" --shell /usr/sbin/nologin "$RUN_USER"
  mkdir -p "${INSTALL_DIR}/mongo-data" "${INSTALL_DIR}/log" "${INSTALL_DIR}/run"
  chown -R "${RUN_USER}:${RUN_USER}" \
    "${INSTALL_DIR}/mongo-data" \
    "${INSTALL_DIR}/log" \
    "${INSTALL_DIR}/run" \
    "${INSTALL_DIR}/mongodb" \
    "${INSTALL_DIR}/mongod.conf"
  chmod 750 "${INSTALL_DIR}/mongo-data" "${INSTALL_DIR}/log" "${INSTALL_DIR}/run"
  chmod 640 "${INSTALL_DIR}/mongod.conf"
}

setup_mongo_bundle_systemd() {
  write_mongo_bundle_config
  ensure_mongo_bundle_permissions
  cat >"/etc/systemd/system/${SYSTEMD_PREFIX}-mongod.service" <<EOF
[Unit]
Description=GenieACS MongoDB (bundle)
After=network.target

[Service]
Type=forking
User=${RUN_USER}
Group=${RUN_USER}
PermissionsStartOnly=true
ExecStartPre=/bin/mkdir -p ${INSTALL_DIR}/mongo-data ${INSTALL_DIR}/log ${INSTALL_DIR}/run
ExecStartPre=/bin/chown -R ${RUN_USER}:${RUN_USER} ${INSTALL_DIR}/mongo-data ${INSTALL_DIR}/log ${INSTALL_DIR}/run ${INSTALL_DIR}/mongodb ${INSTALL_DIR}/mongod.conf
ExecStart=${INSTALL_DIR}/mongodb/bin/mongod --config ${INSTALL_DIR}/mongod.conf
PIDFile=${INSTALL_DIR}/run/mongod.pid
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
  systemctl daemon-reload
  systemctl disable mongod 2>/dev/null || true
  systemctl stop mongod 2>/dev/null || true
  systemctl enable "${SYSTEMD_PREFIX}-mongod"
  systemctl reset-failed "${SYSTEMD_PREFIX}-mongod" 2>/dev/null || true
  systemctl restart "${SYSTEMD_PREFIX}-mongod"
  MONGO_SYSTEMD_UNIT="${SYSTEMD_PREFIX}-mongod.service"
}

start_mongo_bundle() {
  for _ in $(seq 1 30); do
    if mongo_ready; then
      log "mongod bundle pronto"
      return
    fi
    sleep 1
  done
  die "mongod bundle não respondeu"
}

install_mongo_apt() {
  if systemctl is-active mongod >/dev/null 2>&1; then
    log "mongod (apt) já ativo"
    MONGO_SYSTEMD_UNIT="mongod.service"
    return
  fi
  local mongo_ver repo_codename
  mongo_ver="$(mongo_repo_version)"
  repo_codename="$(mongo_repo_codename)"
  log "instalando MongoDB ${mongo_ver} (${repo_codename}) via apt"
  apt-get update -qq
  apt-get install -y gnupg curl ca-certificates
  curl -fsSL "https://www.mongodb.org/static/pgp/server-${mongo_ver}.asc" \
    | gpg -o "/usr/share/keyrings/mongodb-server-${mongo_ver}.gpg" --dearmor
  echo "deb [ arch=amd64,arm64 signed-by=/usr/share/keyrings/mongodb-server-${mongo_ver}.gpg ] https://repo.mongodb.org/apt/ubuntu ${repo_codename}/mongodb-org/${mongo_ver} multiverse" \
    > "/etc/apt/sources.list.d/mongodb-org-${mongo_ver}.list"
  apt-get update -qq
  apt-get install -y mongodb-org
  systemctl enable mongod
  if ! systemctl start mongod; then
    log "mongod via apt falhou, tentando bundle"
    systemctl disable mongod 2>/dev/null || true
    MONGO_MODE="bundle"
    return 1
  fi
  MONGO_SYSTEMD_UNIT="mongod.service"
}

install_mongo_system() {
  resolve_mongo_mode
  if [[ "$MONGO_MODE" == "bundle" ]]; then
    install_mongo_bundle
    setup_mongo_bundle_systemd
    start_mongo_bundle
    return
  fi
  if ! install_mongo_apt; then
    install_mongo_bundle
    setup_mongo_bundle_systemd
    start_mongo_bundle
  fi
}

configure_mongo_auth_system() {
  [[ -n "$MONGO_PASSWORD" ]] || return 0
  [[ "$MONGO_MODE" == "bundle" ]] && die "auth Mongo no bundle ainda não suportada; use sem senha"
  require_cmd mongosh
  log "configurando usuário MongoDB ${MONGO_USER}"
  mongosh --quiet <<EOF
use ${MONGO_DB}
if (db.getUser("${MONGO_USER}") == null) {
  db.createUser({
    user: "${MONGO_USER}",
    pwd: "${MONGO_PASSWORD}",
    roles: [{ role: "readWrite", db: "${MONGO_DB}" }]
  })
}
EOF
  if ! grep -q 'authorization: enabled' /etc/mongod.conf 2>/dev/null; then
    if grep -q '^security:' /etc/mongod.conf 2>/dev/null; then
      sed -i '/^security:/,/authorization:/ s/authorization:.*/  authorization: enabled/' /etc/mongod.conf
    else
      printf '\nsecurity:\n  authorization: enabled\n' >> /etc/mongod.conf
    fi
    systemctl restart mongod
    for _ in $(seq 1 20); do
      if mongosh --quiet "mongodb://${MONGO_USER}:${MONGO_PASSWORD}@${MONGO_HOST}:${MONGO_PORT}/${MONGO_DB}" --eval 'db.runCommand({ping:1})' >/dev/null 2>&1; then
        log "MongoDB com autenticação ativa"
        return
      fi
      sleep 1
    done
    die "MongoDB não aceitou autenticação após restart"
  fi
}

prepare_nbi_ports() {
  [[ "$NBI_PROTECT" == "1" ]] || return 0
  [[ "$LOCAL_MODE" == "1" ]] && die "proteção nginx do NBI só no modo sistema"
  [[ -n "$NBI_INTERNAL_PORT" ]] && return 0
  NBI_PUBLIC_PORT="${NBI_PORT}"
  NBI_INTERNAL_PORT=$((NBI_PORT + 1000))
  NBI_PORT="$NBI_INTERNAL_PORT"
}

start_mongo_local() {
  install_mongo_bundle
  write_mongo_bundle_config
  local mongo_bin="${INSTALL_DIR}/mongodb/bin/mongod"
  local pid_file="${INSTALL_DIR}/run/mongod.pid"
  mkdir -p "${INSTALL_DIR}/mongo-data" "${INSTALL_DIR}/log" "${INSTALL_DIR}/run"
  if [[ -f "$pid_file" ]] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
    log "mongod local já em execução"
    return
  fi
  "$mongo_bin" --config "${INSTALL_DIR}/mongod.conf" >/dev/null
  for _ in $(seq 1 30); do
    if mongo_ready; then
      log "mongod local pronto"
      return
    fi
    sleep 1
  done
  die "mongod local não respondeu"
}

mongo_ready() {
  if command -v mongosh >/dev/null 2>&1; then
    mongosh --quiet "mongodb://${MONGO_HOST}:${MONGO_PORT}/admin" --eval 'db.runCommand({ping:1})' >/dev/null 2>&1
    return $?
  fi
  ss -ltn 2>/dev/null | grep -q ":${MONGO_PORT} "
}

npm_prefix() {
  if [[ "$LOCAL_MODE" == "1" ]]; then
    printf '%s/npm' "$INSTALL_DIR"
  else
    printf '%s' "/usr/local"
  fi
}

install_genieacs_npm() {
  local prefix
  prefix="$(npm_prefix)"
  log "instalando genieacs@${GENIEACS_VERSION} (prefix ${prefix})"
  if [[ "$LOCAL_MODE" == "1" ]]; then
    mkdir -p "$prefix"
    npm install -g "genieacs@${GENIEACS_VERSION}" --prefix "$prefix"
  else
    npm install -g "genieacs@${GENIEACS_VERSION}"
  fi
}

genieacs_bin() {
  local name="$1"
  local prefix
  prefix="$(npm_prefix)"
  if [[ -x "${prefix}/bin/${name}" ]]; then
    printf '%s' "${prefix}/bin/${name}"
    return
  fi
  if command -v "$name" >/dev/null 2>&1; then
    command -v "$name"
    return
  fi
  die "binário não encontrado: ${name}"
}

mongo_connection_url() {
  if [[ -n "$MONGO_PASSWORD" ]]; then
    printf 'mongodb://%s:%s@%s:%s/%s' \
      "$MONGO_USER" "$MONGO_PASSWORD" "$MONGO_HOST" "$MONGO_PORT" "$MONGO_DB"
  else
    printf 'mongodb://%s:%s/%s' "$MONGO_HOST" "$MONGO_PORT" "$MONGO_DB"
  fi
}

write_env_file() {
  local env_file="${INSTALL_DIR}/genieacs.env"
  mkdir -p "${INSTALL_DIR}/ext" "${INSTALL_DIR}/log"
  [[ -n "$UI_JWT_SECRET" ]] || UI_JWT_SECRET="$(rand_secret)"

  cat >"$env_file" <<EOF
GENIEACS_EXT_DIR=${INSTALL_DIR}/ext
GENIEACS_MONGODB_CONNECTION_URL=$(mongo_connection_url)
GENIEACS_CWMP_INTERFACE=${BIND_IP}
GENIEACS_CWMP_PORT=${CWMP_PORT}
GENIEACS_NBI_INTERFACE=${BIND_IP}
GENIEACS_NBI_PORT=${NBI_PORT}
GENIEACS_FS_INTERFACE=${BIND_IP}
GENIEACS_FS_PORT=${FS_PORT}
GENIEACS_UI_INTERFACE=${BIND_IP}
GENIEACS_UI_PORT=${UI_PORT}
GENIEACS_UI_JWT_SECRET=${UI_JWT_SECRET}
GENIEACS_LOG_FILE=${INSTALL_DIR}/log/genieacs-%s.log
GENIEACS_LOG_LEVEL=${LOG_LEVEL}
EOF

  if [[ "$LOCAL_MODE" != "1" ]]; then
    chown -R "${RUN_USER}:${RUN_USER}" "$INSTALL_DIR" /var/log/genieacs 2>/dev/null || true
    chmod 640 "$env_file"
  fi
  log "env gravado em ${env_file}"
}

write_systemd_unit() {
  local svc="$1"
  local bin
  bin="$(genieacs_bin "genieacs-${svc}")"
  cat >"/etc/systemd/system/${SYSTEMD_PREFIX}-${svc}.service" <<EOF
[Unit]
Description=GenieACS ${svc}
After=network.target ${MONGO_SYSTEMD_UNIT}
Wants=${MONGO_SYSTEMD_UNIT}

[Service]
User=${RUN_USER}
Group=${RUN_USER}
EnvironmentFile=${INSTALL_DIR}/genieacs.env
ExecStart=${bin}
Restart=on-failure
RestartSec=5

[Install]
WantedBy=multi-user.target
EOF
}

setup_systemd() {
  id "$RUN_USER" >/dev/null 2>&1 || useradd --system --home "$INSTALL_DIR" --shell /usr/sbin/nologin "$RUN_USER"
  mkdir -p /var/log/genieacs
  chown -R "${RUN_USER}:${RUN_USER}" "$INSTALL_DIR" /var/log/genieacs

  for svc in cwmp nbi fs ui; do
    write_systemd_unit "$svc"
    systemctl daemon-reload
    systemctl enable "${SYSTEMD_PREFIX}-${svc}"
    systemctl restart "${SYSTEMD_PREFIX}-${svc}"
  done
}

start_local_service() {
  local svc="$1"
  local bin pid_file log_file
  bin="$(genieacs_bin "genieacs-${svc}")"
  pid_file="${INSTALL_DIR}/run/${svc}.pid"
  log_file="${INSTALL_DIR}/log/${svc}.log"
  mkdir -p "${INSTALL_DIR}/run" "${INSTALL_DIR}/log"

  if [[ -f "$pid_file" ]] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
    kill "$(cat "$pid_file")" 2>/dev/null || true
    sleep 1
  fi

  set -a
  # shellcheck disable=SC1090
  source "${INSTALL_DIR}/genieacs.env"
  set +a

  nohup "$bin" >>"$log_file" 2>&1 &
  echo $! >"$pid_file"
}

wait_for_tcp() {
  local port="$1"
  local label="$2"
  for _ in $(seq 1 40); do
    if ss -ltn 2>/dev/null | grep -q ":${port} "; then
      log "${label} escutando na porta ${port}"
      return 0
    fi
    sleep 1
  done
  die "${label} não abriu a porta ${port}"
}

wait_for_http() {
  local url="$1"
  local label="$2"
  local auth="${3:-}"
  local curl_auth=()
  [[ -n "$auth" ]] && curl_auth=(-u "$auth")
  for _ in $(seq 1 40); do
    local code
    code="$(curl -sS "${curl_auth[@]}" -o /dev/null -w '%{http_code}' "$url" 2>/dev/null || echo 000)"
    if [[ "$code" =~ ^[23] ]]; then
      log "${label} HTTP ${code} em ${url}"
      return 0
    fi
    sleep 1
  done
  die "${label} sem resposta HTTP em ${url}"
}

ensure_port_for_nginx() {
  local port="$1"
  if ! port_in_use "$port"; then
    return 0
  fi
  local owner
  owner="$(port_owner "$port")"
  if [[ "$owner" == *nginx* ]]; then
    return 0
  fi
  die "porta ${port} ocupada (${owner:-processo desconhecido}); libere antes de continuar"
}

setup_nginx_nbi_auth() {
  [[ "$NBI_PROTECT" == "1" ]] || return 0
  [[ -n "$NBI_PUBLIC_PORT" && -n "$NBI_INTERNAL_PORT" ]] \
    || die "configuração NBI/nginx incompleta"
  [[ -n "$NBI_USER" ]] || NBI_USER="genieacs"

  ensure_port_for_nginx "$NBI_PUBLIC_PORT"
  apt-get install -y nginx apache2-utils
  if [[ -f /etc/nginx/.genieacs-nbi-htpasswd && -z "$NBI_PASS" ]]; then
    log "mantendo htpasswd existente"
  else
    [[ -n "$NBI_PASS" ]] || die "senha NBI obrigatória para criar htpasswd"
    htpasswd -bc "/etc/nginx/.genieacs-nbi-htpasswd" "$NBI_USER" "$NBI_PASS"
  fi

  cat >/etc/nginx/sites-available/genieacs-nbi <<EOF
server {
    listen ${NBI_PUBLIC_PORT};
    server_name _;

    location / {
        auth_basic "GenieACS NBI";
        auth_basic_user_file /etc/nginx/.genieacs-nbi-htpasswd;
        proxy_pass http://127.0.0.1:${NBI_INTERNAL_PORT}/;
        proxy_http_version 1.1;
        proxy_set_header Host \$host;
        proxy_set_header X-Real-IP \$remote_addr;
    }
}
EOF

  ln -sf /etc/nginx/sites-available/genieacs-nbi /etc/nginx/sites-enabled/genieacs-nbi
  nginx -t
  systemctl enable nginx
  if port_in_use "$NBI_PUBLIC_PORT"; then
    systemctl reload nginx
  else
    systemctl restart nginx
  fi
  wait_for_tcp "$NBI_PUBLIC_PORT" "nginx NBI"
  log "NBI público em :${NBI_PUBLIC_PORT} (auth básica) -> :${NBI_INTERNAL_PORT}"
}

load_existing_env() {
  local env_file="${INSTALL_DIR}/genieacs.env"
  [[ -f "$env_file" ]] || return 0
  log "carregando ${env_file}"
  # shellcheck disable=SC1090
  source "$env_file"
  UI_PORT="${GENIEACS_UI_PORT:-$UI_PORT}"
  CWMP_PORT="${GENIEACS_CWMP_PORT:-$CWMP_PORT}"
  FS_PORT="${GENIEACS_FS_PORT:-$FS_PORT}"
  BIND_IP="${GENIEACS_UI_INTERFACE:-$BIND_IP}"
  UI_JWT_SECRET="${GENIEACS_UI_JWT_SECRET:-$UI_JWT_SECRET}"
  if [[ -f /etc/nginx/sites-enabled/genieacs-nbi ]]; then
    NBI_PROTECT=1
    NBI_PUBLIC_PORT="$(awk '/listen / {print $2; exit}' /etc/nginx/sites-enabled/genieacs-nbi | tr -d ';')"
    NBI_INTERNAL_PORT="${GENIEACS_NBI_PORT:-}"
    NBI_PORT="${NBI_INTERNAL_PORT:-${GENIEACS_NBI_PORT:-$NBI_PORT}}"
  else
    NBI_PORT="${GENIEACS_NBI_PORT:-$NBI_PORT}"
  fi
  if [[ -f /etc/nginx/.genieacs-nbi-htpasswd ]]; then
    NBI_USER="$(head -1 /etc/nginx/.genieacs-nbi-htpasswd | cut -d: -f1)"
  fi
}

stop_local_test_conflicts() {
  if [[ -d /tmp/genieacs/run ]]; then
    log "removendo instância de teste em /tmp/genieacs"
    GENIEACS_LOCAL_MODE=1 GENIEACS_INSTALL_DIR=/tmp/genieacs GENIEACS_PURGE_DATA=1 \
      "$(dirname "$0")/uninstall-genieacs-bare.sh" || true
  fi
}

collect_interactive_options() {
  if [[ "$NON_INTERACTIVE" == "1" ]]; then
    return
  fi

  if [[ "$LOCAL_MODE" == "1" ]]; then
    INSTALL_DIR="$(prompt_value "Diretório de instalação" "$INSTALL_DIR")"
    BIND_IP="127.0.0.1"
  else
    INSTALL_DIR="$(prompt_value "Diretório de instalação" "$INSTALL_DIR")"
    BIND_IP="$(prompt_value "IP de escuta dos serviços" "$BIND_IP")"
  fi

  UI_PORT="$(prompt_value "Porta da UI" "$UI_PORT")"
  CWMP_PORT="$(prompt_value "Porta CWMP (TR-069)" "$CWMP_PORT")"
  NBI_PORT="$(prompt_value "Porta NBI (API)" "$NBI_PORT")"
  FS_PORT="$(prompt_value "Porta FS (arquivos)" "$FS_PORT")"

  if prompt_yes_no "Deseja configurar senha do MongoDB?" "n"; then
    MONGO_PASSWORD="$(prompt_secret "Senha do usuário ${MONGO_USER}" "")"
    [[ -n "$MONGO_PASSWORD" ]] || die "senha Mongo vazia"
  fi

  if [[ "$LOCAL_MODE" != "1" ]] && prompt_yes_no "Deseja proteger o NBI com usuário e senha (nginx)?" "n"; then
    NBI_PROTECT=1
    NBI_USER="$(prompt_value "Usuário NBI" "genieacs")"
    NBI_PASS="$(prompt_secret "Senha NBI" "")"
    [[ -n "$NBI_PASS" ]] || die "senha NBI vazia"
  fi

  if prompt_yes_no "Deseja definir manualmente o JWT secret da UI?" "n"; then
    UI_JWT_SECRET="$(prompt_secret "GENIEACS_UI_JWT_SECRET" "")"
    [[ -n "$UI_JWT_SECRET" ]] || UI_JWT_SECRET="$(rand_secret)"
  fi
}

main() {
  detect_ubuntu

  if [[ "$LOCAL_MODE" != "1" && "$(id -u)" -ne 0 ]]; then
    die "modo sistema exige root (ou use GENIEACS_LOCAL_MODE=1)"
  fi

  if [[ "$LOCAL_MODE" == "1" ]]; then
    BIND_IP="127.0.0.1"
  fi

  if [[ "$REPAIR_MODE" == "1" ]]; then
    NON_INTERACTIVE=1
    load_existing_env
    log "modo reparo em ${INSTALL_DIR}"
  else
    collect_interactive_options
  fi
  require_cmd curl
  require_cmd npm

  mkdir -p "$INSTALL_DIR"
  install_node_if_needed

  if [[ "$LOCAL_MODE" == "1" ]]; then
    start_mongo_local
  else
    stop_local_test_conflicts
    install_mongo_system
    configure_mongo_auth_system
  fi

  if [[ "${GENIEACS_SKIP_NPM:-0}" != "1" ]]; then
    install_genieacs_npm
  else
    log "pulando npm (GENIEACS_SKIP_NPM=1)"
  fi
  prepare_nbi_ports
  write_env_file

  if [[ "$LOCAL_MODE" == "1" ]]; then
    for svc in cwmp nbi fs ui; do
      start_local_service "$svc"
    done
    wait_for_http "http://127.0.0.1:${UI_PORT}/" "UI"
    if [[ "$NBI_PROTECT" == "1" ]]; then
      if [[ -n "$NBI_PASS" ]]; then
        wait_for_http "http://127.0.0.1:${NBI_PUBLIC_PORT}/devices/" "NBI" "${NBI_USER}:${NBI_PASS}"
      else
        local code
        code="$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1:${NBI_PUBLIC_PORT}/devices/" 2>/dev/null || echo 000)"
        [[ "$code" == "401" ]] && log "NBI exige auth (HTTP 401)" || wait_for_http "http://127.0.0.1:${NBI_PUBLIC_PORT}/devices/" "NBI"
      fi
    else
      wait_for_http "http://127.0.0.1:${NBI_PORT}/devices/" "NBI"
    fi
    wait_for_tcp "$CWMP_PORT" "CWMP"
    wait_for_tcp "$FS_PORT" "FS"
  else
    setup_systemd
    setup_nginx_nbi_auth
    wait_for_http "http://127.0.0.1:${UI_PORT}/" "UI"
    if [[ "$NBI_PROTECT" == "1" ]]; then
      if [[ -n "$NBI_PASS" ]]; then
        wait_for_http "http://127.0.0.1:${NBI_PUBLIC_PORT}/devices/" "NBI" "${NBI_USER}:${NBI_PASS}"
      else
        local code
        code="$(curl -sS -o /dev/null -w '%{http_code}' "http://127.0.0.1:${NBI_PUBLIC_PORT}/devices/" 2>/dev/null || echo 000)"
        [[ "$code" == "401" ]] && log "NBI exige auth (HTTP 401)" || wait_for_http "http://127.0.0.1:${NBI_PUBLIC_PORT}/devices/" "NBI"
      fi
    else
      wait_for_http "http://127.0.0.1:${NBI_PORT}/devices/" "NBI"
    fi
    wait_for_tcp "$CWMP_PORT" "CWMP"
    wait_for_tcp "$FS_PORT" "FS"
  fi

  local nbi_url_port="$NBI_PORT"
  [[ "$NBI_PROTECT" == "1" ]] && nbi_url_port="$NBI_PUBLIC_PORT"

  cat <<EOF

Instalação concluída.

Diretório: ${INSTALL_DIR}
UI:        http://${BIND_IP}:${UI_PORT}/
NBI:       http://${BIND_IP}:${nbi_url_port}/devices/
FS:        http://${BIND_IP}:${FS_PORT}/
CWMP:      ${BIND_IP}:${CWMP_PORT}

Env:       ${INSTALL_DIR}/genieacs.env
Validação: $(dirname "$0")/validate-genieacs-bare.sh

EOF
}

main "$@"
