#!/usr/bin/env bash
# OSS Setup-Only v1.0 — Wizard (:1234) + Hotspot + Captive (laat :80 onaangetast)
set -euo pipefail
LOGFILE="/var/log/oss-setup-only.log"
exec > >(tee -a "$LOGFILE") 2>&1
export DEBIAN_FRONTEND="${DEBIAN_FRONTEND:-noninteractive}"

# ---- Config ----
WIZ_ZIP_URL="${WORKDIR_URL:-https://repo.easycomp.cloud/public_access/BirdNET-Pi/oss-birdnetpi-workdir.zip}"
WIZ_DIR="${WIZ_DIR:-/opt/oss/birdnet-wizard}"
CADDYFILE="${CADDYFILE:-/etc/caddy/Caddyfile}"
HOTSPOT_SSID="${HOTSPOT_SSID:-BIRDNET-PI-SETUP}"
NFT_RULES="/etc/nftables.d/oss-captive.nft"
NFT_UNIT="/etc/systemd/system/oss-captive-nft.service"
WIZ_UNIT="/etc/systemd/system/oss-setup-wizard.service"
NFT_TABLE_NAME="oss_captive"

log(){ echo -e "[+] $*"; }
warn(){ echo -e "[!] $*"; }
die(){ echo -e "[✗] $*"; exit 1; }

require_birdnet_ready(){
  command -v caddy >/dev/null || die "Caddy ontbreekt — run eerst de BirdNET-Pi installer en reboot."
  local code; code="$(curl -fs -o /dev/null -w "%{http_code}" http://127.0.0.1:80/ || true)"
  [[ "$code" = 2* || "$code" = 3* ]] || die "Poort 80 reageert niet (HTTP $code). BirdNET-Pi nog niet klaar?"
}

detect_wdev(){
  local w
  w="$(iw dev 2>/dev/null | awk '$1=="Interface"{print $2}' | grep -E '^(ap0|uap0|wlan0|wlan1)$' | head -n1 || true)"
  [ -n "$w" ] || w="$(iw dev 2>/dev/null | awk '$1=="Interface"{print $2; exit}' || true)"
  echo "$w"
}

# ---- 0) Preflight ----
require_birdnet_ready
dpkg --configure -a || true
apt-get -f install -y || true
apt-get update -y
apt-get install -y network-manager python3 python3-pip rsync unzip nftables curl ca-certificates

# ---- 1) Wizard (luistert alleen op :1234) ----
log "Deploy wizard → $WIZ_DIR"
mkdir -p "$WIZ_DIR"
TMP="$(mktemp -d)"
curl -fL "$WIZ_ZIP_URL" -o "$TMP/payload.zip"
unzip -q "$TMP/payload.zip" -d "$TMP/unpacked"
if [[ -d "$TMP/unpacked/wizard" ]]; then SRC="$TMP/unpacked/wizard"; else SRC="$(find "$TMP/unpacked" -maxdepth 2 -type d -name wizard -print -quit)"; fi
[[ -n "${SRC:-}" ]] || SRC="$TMP/unpacked"
rsync -a --delete "$SRC"/ "$WIZ_DIR"/

log "Python deps (Flask)…"
pip3 install --break-system-packages Flask==3.0.3 Jinja2 itsdangerous Werkzeug || pip3 install Flask==3.0.3 Jinja2 itsdangerous Werkzeug

log "Wizard systemd-service (root, :1234)…"
cat > "$WIZ_UNIT" <<EOFU
[Unit]
Description=OSS BirdNET-Pi Setup Wizard (Flask, :1234)
After=network-online.target
Wants=network-online.target
[Service]
User=root
Group=root
WorkingDirectory=$WIZ_DIR
ExecStart=/usr/bin/python3 $WIZ_DIR/app.py --host 0.0.0.0 --port 1234
Restart=on-failure
RestartSec=3
Environment=PYTHONUNBUFFERED=1
[Install]
WantedBy=multi-user.target
EOFU
systemctl daemon-reload
systemctl enable --now oss-setup-wizard

# ---- 2) Hotspot via NetworkManager (OPEN, geen security) ----
log "Hotspot configureren (OPEN)…"
WDEV="$(detect_wdev)"; [[ -n "$WDEV" ]] || die "Geen Wi-Fi interface gevonden."
rfkill unblock wifi || true
nmcli radio wifi on || true
ip link set "$WDEV" up || true
# alle profielen met dezelfde SSID weg (voorkom WEP/secrets gedoe)
for UUID in $(nmcli -g UUID,NAME con show | awk -F: -v s="$HOTSPOT_SSID" '$2==s{print $1}'); do nmcli con delete "$UUID" || true; done
# nieuw OPEN AP-profiel
nmcli con add type wifi ifname "$WDEV" con-name "$HOTSPOT_SSID" ssid "$HOTSPOT_SSID" \
  802-11-wireless.mode ap 802-11-wireless.band bg 802-11-wireless.channel 6 \
  ipv4.method shared ipv6.method ignore connection.autoconnect yes
# forceer géén security-sectie
nmcli con mod "$HOTSPOT_SSID" -802-11-wireless-security 2>/dev/null || true
nmcli con mod "$HOTSPOT_SSID" -wifi-sec 2>/dev/null || true
systemctl restart NetworkManager
sleep 2
nmcli connection reload || true
nmcli con up "$HOTSPOT_SSID" ifname "$WDEV" || warn "Hotspot niet direct actief; probeer zo opnieuw."
# IP afwachten
for i in $(seq 1 25); do
  HIP="$(ip -4 addr show "$WDEV" | awk '/inet /{print $2}' | cut -d/ -f1)"
  [[ -n "${HIP:-}" ]] && break
  sleep 1
done
[[ -n "${HIP:-}" ]] && log "Hotspot IP: $HIP" || warn "Geen hotspot IP gezien (verwacht 10.42.x.x)."

# ---- 3) Caddy captive-probe injectie (safe, optioneel) ----
log "Caddy captive-probes toevoegen (zonder :80 over te nemen)…"
if [[ -f "$CADDYFILE" ]]; then
  cp -a "$CADDYFILE" "${CADDYFILE}.bak.$(date +%s)"
  if grep -q "OSS captive probes" "$CADDYFILE"; then
    sed -i "s#redir http://[^ ]\\+:1234#redir http://${HIP:-10.42.0.1}:1234#g" "$CADDYFILE"
    INJECTED=1
  else
    # 3a) proberen in :80-blok
    if grep -qE "^[[:space:]]*:80[[:space:]]*{" "$CADDYFILE"; then
      awk -v ip="${HIP:-10.42.0.1}" '
        BEGIN{in80=0; inserted=0}
        /^\s*:80\s*\{/ { if(!inserted) in80=1 }
        { print
          if(in80 && /^\}\s*$/ && !inserted){
            print "  # OSS captive probes → wizard (alleen probe-paden)"
            print "  @captive path /generate_204 /hotspot-detect.html /connecttest.txt /ncsi.txt /success.txt"
            print "  handle @captive {"
            print "    redir http://" ip ":1234 302"
            print "  }"
            inserted=1; in80=0
          }
        }' "$CADDYFILE" > "${CADDYFILE}.new"
      if grep -q "OSS captive probes" "${CADDYFILE}.new"; then
        mv "${CADDYFILE}.new" "$CADDYFILE"; INJECTED=1
      else
        rm -f "${CADDYFILE}.new"
      fi
    fi
    # 3b) zo niet: injecteer in het eerste server-blok (niet global {})
    if [[ -z "${INJECTED:-}" ]]; then
      awk -v ip="${HIP:-10.42.0.1}" '
        BEGIN{in_global=0; in_server=0; inserted=0}
        /^[[:space:]]*\{[[:space:]]*$/ { if(!inserted){ in_global=1 } }   # global open
        /^[[:space:]]*\}[[:space:]]*$/ {                                  # block close
          print
          if(in_server && !inserted){
            print "  # OSS captive probes → wizard (alleen probe-paden)"
            print "  @captive path /generate_204 /hotspot-detect.html /connecttest.txt /ncsi.txt /success.txt"
            print "  handle @captive {"
            print "    redir http://" ip ":1234 302"
            print "  }"
            inserted=1
          }
          in_global=0; in_server=0; next
        }
        /^[[:space:]]*[^#][^[:space:]]+[[:space:]]*\{/ {                   # server block open
          if(!inserted && !in_global){ in_server=1; print; next }
        }
        { print }
      ' "$CADDYFILE" > "${CADDYFILE}.new"
      if grep -q "OSS captive probes" "${CADDYFILE}.new"; then
        mv "${CADDYFILE}.new" "$CADDYFILE"; INJECTED=1
      else
        rm -f "${CADDYFILE}.new"
        warn "Geen geschikt server-blok gevonden om te injecteren; sla Caddy-injectie over."
      fi
    fi
  fi
  # reload alleen indien gewijzigd
  if [[ -n "${INJECTED:-}" ]]; then
    caddy validate --config "$CADDYFILE" && systemctl reload caddy || {
      warn "Caddy validatie faalde — rollback."
      cp "${CADDYFILE}.bak."* "$CADDYFILE" 2>/dev/null || true
      systemctl restart caddy
    }
  fi
else
  warn "Caddyfile niet gevonden — sla Caddy-injectie over (nftables regelt captive)."
fi

# ---- 4) nftables captive NAT (HTTP via hotspot → :1234) ----
log "nftables captive-redirect activeren…"
systemctl enable --now nftables
mkdir -p /etc/nftables.d
cat > "$NFT_RULES" <<EOFR
table inet ${NFT_TABLE_NAME} {
  chain prerouting {
    type nat hook prerouting priority -100; policy accept;
    iifname "$WDEV" tcp dport 80 redirect to :1234
  }
}
EOFR
cat > "$NFT_UNIT" <<'EOFU'
[Unit]
Description=OSS captive HTTP redirect (hotspot -> :1234)
After=network-online.target
Wants=network-online.target
[Service]
Type=oneshot
ExecStart=/usr/sbin/nft -f /etc/nftables.d/oss-captive.nft
RemainAfterExit=yes
[Install]
WantedBy=multi-user.target
EOFU
systemctl daemon-reload
systemctl enable --now oss-captive-nft

# ---- 5) Smoketest ----
log "Smoketest…"
H80="$(curl -fs -o /dev/null -w "%{http_code}" http://127.0.0.1:80/ || true)"
H12="$(curl -fs -o /dev/null -w "%{http_code}" http://127.0.0.1:1234/ || true)"
systemctl is-active --quiet caddy && echo "[OK] caddy actief" || die "caddy inactief"
systemctl is-active --quiet oss-setup-wizard && echo "[OK] wizard actief" || die "wizard-service inactief"
[[ "$H80" = 2* || "$H80" = 3* ]] || die "poort 80 geen 2xx/3xx ($H80)"
[[ "$H12" = 2* || "$H12" = 3* ]] || die "poort 1234 geen 2xx/3xx ($H12)"
sudo nft list ruleset | grep -A2 "table inet ${NFT_TABLE_NAME}" >/dev/null || die "nftables captive rules niet geladen"

echo
echo "✅ Klaar. Hotspot: ${HOTSPOT_SSID} (open). Captive → wizard:  http://${HIP:-10.42.0.1}:1234"
echo "ℹ️  BirdNET-Pi blijft op poort 80 (onaangetast). Log: $LOGFILE"
