#!/usr/bin/env bash
# install_all.sh — BirdNET‑Pi (Nachtzuster) + Open‑Source Setup Wizard (hotspot + captive + wizard)
set -euo pipefail

# ----- APT non‑interactive / no prompts -----
export DEBIAN_FRONTEND="${DEBIAN_FRONTEND:-noninteractive}"
APT_OPTS='-y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::=--force-confold'

BPI_USER="${BPI_USER:-birdnet}"
PKG_NAME="oss-birdnetpi-workdir"
CALLER="${SUDO_USER:-$USER}"
HOME_CALLER="$(eval echo ~${CALLER})"
LOCAL_DIR="${LOCAL_DIR:-$HOME_CALLER/${PKG_NAME}}"
LOCAL_ZIP="${LOCAL_DIR}.zip"
WIZ_DIR="/home/${BPI_USER}/birdnet-setup-wizard"
STAGE_ROOT="/tmp/${PKG_NAME}-stage.$$"

NM_CONN_ID_DEFAULT="BIRDNET-PI-SETUP"
NM_CONN_DST_DIR="/etc/NetworkManager/system-connections"
CADDYFILE="/etc/caddy/Caddyfile"
WIFI_COUNTRY="${WIFI_COUNTRY:-}"   # e.g. NL/BE/DE/GB

WORKDIR_URL="${WORKDIR_URL:-https://repo.easycomp.cloud/public_access/BirdNET-Pi/oss-birdnetpi-workdir.zip}"
BIRDN_INSTALL_URL="https://raw.githubusercontent.com/Nachtzuster/BirdNET-Pi/main/newinstaller.sh"

log(){ echo -e "\n\033[1;34m[+] $*\033[0m"; }
warn(){ echo -e "\n\033[1;33m[!] $*\033[0m"; }
die(){ echo -e "\n\033[1;31m[✗] $*\033[0m"; exit 1; }
require_root(){ [[ $EUID -eq 0 ]] || die "Run this script as root (sudo)."; }

preflight_apt(){
  log "Preflight: clean APT/dpkg and avoid prompts…"
  killall -q whiptail dialog || true
  dpkg --configure -a ${APT_OPTS} || true
  apt-get ${APT_OPTS} -f install || true
}

ensure_user(){
  if ! id -u "$BPI_USER" >/dev/null 2>&1; then
    log "Create user ${BPI_USER}…"
    adduser --disabled-password --gecos "" "$BPI_USER"
    usermod -aG sudo,audio,video,plugdev,netdev "$BPI_USER"
  else
    log "User ${BPI_USER} already exists."
  fi
}

fix_wifi_country(){
  if rfkill list 2>/dev/null | grep -qi 'Wireless LAN.*Soft blocked: yes'; then
    log "Unblock Wi‑Fi via rfkill…"
    rfkill unblock wifi || true
  fi
  if [[ -n "${WIFI_COUNTRY}" ]]; then
    if command -v raspi-config >/dev/null 2>&1; then
      log "Set Wi‑Fi country: ${WIFI_COUNTRY}"
      raspi-config nonint do_wifi_country "${WIFI_COUNTRY}" || true
      iw reg set "${WIFI_COUNTRY}" || true
    else
      warn "raspi-config not found; skipping Wi‑Fi country set."
    fi
  else
    warn "WIFI_COUNTRY not set — skipping Wi‑Fi country."
  fi
}

install_prereqs(){
  log "Install base packages…"
  apt-get update
  apt-get ${APT_OPTS} install \
    curl ca-certificates network-manager caddy python3 python3-pip \
    rsync unzip
}

install_birdnet(){
  log "Install BirdNET‑Pi as ${BPI_USER}…"
  sudo -u "$BPI_USER" bash -lc "curl -fsSL ${BIRDN_INSTALL_URL} | bash" || warn "BirdNET installer gave a warning."
}

stage_package(){
  log "Stage package → ${STAGE_ROOT}"
  rm -rf "$STAGE_ROOT"
  mkdir -p "$STAGE_ROOT"

  if [[ -d "$LOCAL_DIR" ]]; then
    log "Using local directory: $LOCAL_DIR"
    rsync -a "$LOCAL_DIR/." "$STAGE_ROOT/"
  elif [[ -f "$LOCAL_ZIP" ]]; then
    log "Using local zip: $LOCAL_ZIP"
    unzip -o "$LOCAL_ZIP" -d "$STAGE_ROOT" >/dev/null
  else
    log "Downloading zip from repo…"
    curl -fL "$WORKDIR_URL" -o "/tmp/${PKG_NAME}.zip"
    unzip -o "/tmp/${PKG_NAME}.zip" -d "$STAGE_ROOT" >/dev/null
  fi

  # Promote nested folder if the zip contains a single top-level directory
  if [[ $(find "$STAGE_ROOT" -mindepth 1 -maxdepth 1 -type d | wc -l) -eq 1 ]] \
     && [[ $(find "$STAGE_ROOT" -mindepth 1 -maxdepth 1 -type f | wc -l) -eq 0 ]]; then
    local onlydir; onlydir="$(find "$STAGE_ROOT" -mindepth 1 -maxdepth 1 -type d)"
    log "Promote subdir: ${onlydir} → ${STAGE_ROOT}"
    rsync -a "${onlydir}/" "$STAGE_ROOT/"
  fi
}

find_assets(){
  # Wizard root (contains app.py + templates/) or wizard/
  if [[ -d "$STAGE_ROOT/wizard" ]]; then
    WIZARD_SRC="$STAGE_ROOT/wizard"
  elif [[ -f "$STAGE_ROOT/app.py" ]]; then
    WIZARD_SRC="$STAGE_ROOT"
  else
    WIZARD_SRC="$(find "$STAGE_ROOT" -maxdepth 3 -type f -name app.py -printf '%h\n' | while read -r d; do
      [[ -d "$d/templates" ]] && echo "$d" && break
    done || true)"
  fi
  [[ -n "${WIZARD_SRC:-}" ]] || die "No wizard source found (app.py + templates/)."

  # .nmconnection (prefer default name but allow fallback)
  NM_FILE_FOUND="$(find "$STAGE_ROOT" -maxdepth 5 -type f -name "${NM_CONN_ID_DEFAULT}.nmconnection" | head -n1 || true)"
  if [[ -z "$NM_FILE_FOUND" ]]; then
    NM_FILE_FOUND="$(find "$STAGE_ROOT" -maxdepth 5 -type f -name '*.nmconnection' | head -n1 || true)"
  fi
  [[ -n "${NM_FILE_FOUND:-}" ]] || die "No .nmconnection found in package."

  # systemd service (oss default name)
  if   [[ -f "$STAGE_ROOT/systemd/birdnet-setup-wizard.service" ]]; then
    SERVICE_SRC="$STAGE_ROOT/systemd/birdnet-setup-wizard.service"
  elif [[ -f "$STAGE_ROOT/systemd/ecz-setup-wizard.service" ]]; then
    SERVICE_SRC="$STAGE_ROOT/systemd/ecz-setup-wizard.service"
  else
    SERVICE_SRC="$(find "$STAGE_ROOT" -maxdepth 4 -type f -name '*-setup-wizard.service' | head -n1 || true)"
  fi
  [[ -n "${SERVICE_SRC:-}" ]] || die "No systemd service file found in package."
}

deploy_wizard(){
  log "Deploy wizard → ${WIZ_DIR}"
  mkdir -p "$WIZ_DIR"
  rsync -a "${WIZARD_SRC}/" "$WIZ_DIR/"
  chown -R "$BPI_USER:$BPI_USER" "$WIZ_DIR"

  # home path fixes
  sed -i "s#/home/shaady/BirdNET-Pi/birdnet.conf#/home/${BPI_USER}/BirdNET-Pi/birdnet.conf#g" "$WIZ_DIR/app.py" || true
  sed -i "s#/home/shaady#/home/${BPI_USER}#g" "$WIZ_DIR/app.py" || true

  log "Python deps (Flask)…"
  if ! pip3 install --break-system-packages Flask==3.0.3 Jinja2 itsdangerous Werkzeug; then
    pip3 install Flask==3.0.3 Jinja2 itsdangerous Werkzeug
  fi
}

install_service(){
  local svcname
  svcname="$(basename "$SERVICE_SRC")"
  svcname="${svcname%.service}"

  log "Install service ${svcname}…"
  install -m 0644 "$SERVICE_SRC" "/etc/systemd/system/${svcname}.service"
  sed -i "s#/home/ecz-gebruiker#/home/${BPI_USER}#g" "/etc/systemd/system/${svcname}.service"
  sed -i "s#/home/birdnet#/home/${BPI_USER}#g"       "/etc/systemd/system/${svcname}.service"
  systemctl daemon-reload
  systemctl enable --now "${svcname}"
}

enable_hotspot(){
  local dst_nm="$NM_CONN_DST_DIR/$(basename "$NM_FILE_FOUND")"
  log "Install hotspot profile → ${dst_nm}"
  install -m 0600 -o root -g root "$NM_FILE_FOUND" "$dst_nm"
  nmcli connection load "$dst_nm" >/dev/null || true

  systemctl restart NetworkManager
  nmcli dev set wlan0 managed yes 2>/dev/null || true
  ip link set wlan0 up 2>/dev/null || true
  nmcli con down "client-wifi-setup" 2>/dev/null || true

  local nm_id; nm_id="$(awk -F= '/^id=/{print $2; exit}' "$dst_nm")"
  nm_id="${nm_id:-$NM_CONN_ID_DEFAULT}"
  log "Activate hotspot: ${nm_id}"
  nmcli con up "${nm_id}" ifname wlan0 || warn "Could not activate ${nm_id} immediately."

  log "wlan0 IP: $(ip -4 addr show wlan0 | awk '/inet /{print $2}' | cut -d/ -f1 || true) (expected 10.42.0.1)"
}

enable_captive(){
  log "Configure captive redirect in Caddy…"
  [[ -f "$CADDYFILE" ]] || echo 'http:// { respond "Caddy up" 200 }' > "$CADDYFILE"
  if ! grep -q "Captive Portal redirect" "$CADDYFILE"; then
    cat >> "$CADDYFILE" <<'EOF'

# --- Captive Portal redirect (OSS) ---
@captive path /generate_204 /hotspot-detect.html /connecttest.txt /
handle @captive {
    redir http://10.42.0.1:1234 302
}
EOF
  fi
  caddy validate --config "$CADDYFILE"
  systemctl reload caddy || systemctl restart caddy
}

cleanup(){
  rm -rf "$STAGE_ROOT" 2>/dev/null || true
}

main(){
  trap cleanup EXIT
  require_root
  preflight_apt
  ensure_user
  fix_wifi_country
  install_prereqs
  install_birdnet
  stage_package
  find_assets
  deploy_wizard
  install_service
  enable_hotspot
  enable_captive

  log "✅ Done. SSID: ${NM_CONN_ID_DEFAULT} (open) → http://10.42.0.1:1234"
}
main "$@"
