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

INSTALL_DIR="${GENIEACS_INSTALL_DIR:-/opt/genieacs}"
UI_PORT="${GENIEACS_UI_PORT:-3000}"
NBI_PORT="${GENIEACS_NBI_PORT:-7557}"
NBI_PUBLIC_PORT=""
FS_PORT="${GENIEACS_FS_PORT:-7567}"
CWMP_PORT="${GENIEACS_CWMP_PORT:-7547}"
BIND_IP="${GENIEACS_BIND_IP:-127.0.0.1}"

NBI_USER="${GENIEACS_NBI_USER:-}"
NBI_PASS="${GENIEACS_NBI_PASS:-}"
NBI_PROTECT=0

failures=0
ok() { printf '  OK  %s\n' "$*"; }
bad() { printf ' FAIL %s\n' "$*"; failures=$((failures + 1)); }

load_config() {
  local env_file="${INSTALL_DIR}/genieacs.env"
  if [[ ! -f "$env_file" ]]; then
    bad "arquivo ${env_file} ausente"
    exit 1
  fi
  if [[ -r "$env_file" ]]; then
    # shellcheck disable=SC1090
    source "$env_file"
  else
    GENIEACS_UI_PORT="$(grep '^GENIEACS_UI_PORT=' "$env_file" 2>/dev/null | cut -d= -f2- || true)"
    GENIEACS_CWMP_PORT="$(grep '^GENIEACS_CWMP_PORT=' "$env_file" 2>/dev/null | cut -d= -f2- || true)"
    GENIEACS_FS_PORT="$(grep '^GENIEACS_FS_PORT=' "$env_file" 2>/dev/null | cut -d= -f2- || true)"
    GENIEACS_NBI_PORT="$(grep '^GENIEACS_NBI_PORT=' "$env_file" 2>/dev/null | cut -d= -f2- || true)"
    GENIEACS_UI_INTERFACE="$(grep '^GENIEACS_UI_INTERFACE=' "$env_file" 2>/dev/null | cut -d= -f2- || true)"
  fi
  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}"
  CURL_HOST="127.0.0.1"
  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_PORT="${GENIEACS_NBI_PORT:-$(awk '/proxy_pass/ {split($2,a,":"); gsub(/\/.*/,"",a[3]); print a[3]; exit}' /etc/nginx/sites-enabled/genieacs-nbi)}"
    NBI_PORT="${NBI_PORT:-8557}"
  else
    NBI_PORT="${GENIEACS_NBI_PORT:-$NBI_PORT}"
  fi
  if [[ -f /etc/nginx/.genieacs-nbi-htpasswd ]]; then
    NBI_USER="${NBI_USER:-$(head -1 /etc/nginx/.genieacs-nbi-htpasswd | cut -d: -f1)}"
  fi
}

curl_auth=()
if [[ -n "$NBI_USER" && -n "$NBI_PASS" ]]; then
  curl_auth=(-u "${NBI_USER}:${NBI_PASS}")
fi

check_http() {
  local label="$1"
  local url="$2"
  local expect="${3:-}"
  local code body
  code="$(curl -sS -o /tmp/genieacs-validate-body -w '%{http_code}' "${curl_auth[@]}" "$url" 2>/dev/null || echo "000")"
  body="$(cat /tmp/genieacs-validate-body 2>/dev/null || true)"
  if [[ "$code" =~ ^[23] ]]; then
    if [[ -z "$expect" || "$body" == *"$expect"* ]]; then
      ok "${label} (${code}) ${url}"
      return
    fi
    bad "${label} corpo inesperado (${code})"
    return
  fi
  bad "${label} HTTP ${code} ${url}"
}

check_http_code() {
  local label="$1"
  local url="$2"
  local want="$3"
  local code
  code="$(curl -sS -o /dev/null -w '%{http_code}' "$url" 2>/dev/null || echo "000")"
  if [[ "$code" == "$want" ]]; then
    ok "${label} (${code}) ${url}"
  else
    bad "${label} esperado HTTP ${want}, obteve ${code} ${url}"
  fi
}

check_port() {
  local label="$1"
  local port="$2"
  if ss -ltn 2>/dev/null | grep -q ":${port} "; then
    ok "${label} escutando :${port}"
  else
    bad "${label} porta :${port} fechada"
  fi
}

load_config

printf 'Validando GenieACS em %s\n' "$INSTALL_DIR"

check_port "CWMP" "$CWMP_PORT"
check_port "FS" "$FS_PORT"
check_port "UI" "$UI_PORT"

if [[ "$NBI_PROTECT" == "1" ]]; then
  check_port "NBI público (nginx)" "$NBI_PUBLIC_PORT"
  check_port "NBI interno" "$NBI_PORT"
  check_http_code "NBI sem credencial" "http://${CURL_HOST}:${NBI_PUBLIC_PORT}/devices/" "401"
  if [[ -n "$NBI_PASS" ]]; then
    check_http "NBI autenticado" "http://${CURL_HOST}:${NBI_PUBLIC_PORT}/devices/" ""
  fi
else
  check_port "NBI" "$NBI_PORT"
  check_http "NBI devices" "http://${CURL_HOST}:${NBI_PORT}/devices/" ""
fi

check_http "UI" "http://${CURL_HOST}:${UI_PORT}/" ""

if systemctl is-active genieacs-mongod >/dev/null 2>&1 || systemctl is-active mongod >/dev/null 2>&1; then
  ok "serviço MongoDB ativo"
elif ss -ltn 2>/dev/null | grep -q ':27017 '; then
  ok "MongoDB escutando :27017"
else
  bad "MongoDB indisponível"
fi

if command -v mongosh >/dev/null 2>&1; then
  if mongosh --quiet "mongodb://127.0.0.1:27017/genieacs" --eval 'db.runCommand({ping:1}).ok' 2>/dev/null | grep -q 1; then
    ok "MongoDB ping"
  else
    bad "MongoDB ping"
  fi
fi

for svc in cwmp nbi fs ui; do
  if systemctl is-active "genieacs-${svc}" >/dev/null 2>&1; then
    ok "genieacs-${svc} ativo"
  else
    bad "genieacs-${svc} inativo"
  fi
done

if [[ "$failures" -eq 0 ]]; then
  printf '\nTudo certo.\n'
  exit 0
fi

printf '\n%d falha(s).\n' "$failures"
exit 1
