#!/usr/bin/env bash
# Bring up the POG-EDGE LAN/WiFi uplink (WireGuard transport only — never game ETH).
#
# EDGE_UPLINK=eth0|wlan0|wlan1|…  (from /etc/fixture/edge.env)
# Game ports (eth0/eth1 per EDGE_GAME_IF) stay IP-less for AF_PACKET.
#
#   sudo bash prep_edge_uplink.sh

set -euo pipefail

if [[ "${EUID}" -ne 0 ]]; then
  echo "Run with sudo" >&2
  exit 1
fi

# shellcheck disable=SC1091
source "$(dirname "$0")/pog_edge_env.sh"

UPLINK="${EDGE_UPLINK:-${POG_EDGE_LAN_IF:-eth0}}"
# Empty GAME = tunnel-only (pos5 end-of-bank). Do not default empty → eth1.
GAME="${POG_EDGE_GAME_IF-}"
DHCP_ONCE="${EDGE_DHCP_ONCE:-1}"

_is_wlan_uplink() {
  [[ "${1}" == wlan* ]]
}

if [[ "${UPLINK}" != "eth0" ]] && ! _is_wlan_uplink "${UPLINK}"; then
  echo "FATAL: EDGE_UPLINK must be eth0 or wlanN (got ${UPLINK})" >&2
  exit 1
fi

if [[ ! -d "/sys/class/net/${UPLINK}" ]]; then
  echo "FATAL: uplink ${UPLINK} not found under /sys/class/net" >&2
  exit 1
fi

if pgrep -f 'pog422_fixture_bridge' >/dev/null 2>&1; then
  echo "FATAL: stop fixture bridge before prep_edge_uplink" >&2
  exit 1
fi

unmanage_game_ports() {
  local p
  for p in eth0 eth1; do
    if [[ "${p}" == "${UPLINK}" ]]; then
      continue
    fi
    if [[ -n "${GAME}" && "${p}" == "${GAME}" ]]; then
      if command -v nmcli >/dev/null 2>&1; then
        nmcli dev set "${p}" managed no 2>/dev/null || true
      fi
      ip addr flush dev "${p}" 2>/dev/null || true
      ip link set "${p}" nomaster 2>/dev/null || true
      ip link set "${p}" up 2>/dev/null || true
      continue
    fi
    if [[ -d "/sys/class/net/${p}" ]]; then
      if command -v nmcli >/dev/null 2>&1; then
        nmcli dev set "${p}" managed no 2>/dev/null || true
      fi
      ip addr flush dev "${p}" 2>/dev/null || true
      ip link set "${p}" nomaster 2>/dev/null || true
      ip link set "${p}" up 2>/dev/null || true
    fi
  done
}

bring_uplink_eth0() {
  ip link set eth0 nomaster 2>/dev/null || true
  ip link set eth0 up
  if command -v nmcli >/dev/null 2>&1; then
    nmcli dev set eth0 managed yes 2>/dev/null || true
    nmcli dev connect eth0 2>/dev/null || true
  fi
  if ! ip -4 addr show dev eth0 | grep -q 'inet '; then
    if command -v dhclient >/dev/null 2>&1; then
      if [[ "${DHCP_ONCE}" == "1" ]]; then
        dhclient -1 -v eth0 2>/dev/null || dhclient -1 eth0 || true
        pkill -f 'dhclient.*eth0' 2>/dev/null || true
      else
        dhclient -v eth0 2>/dev/null || dhclient eth0 || true
      fi
    else
      echo "WARN: no IPv4 on eth0 and dhclient missing" >&2
    fi
  elif [[ "${DHCP_ONCE}" == "1" ]]; then
    pkill -f 'dhclient.*eth0' 2>/dev/null || true
  fi
}

# Bring up EDGE_UPLINK when it is wlan0/wlan1/…
# If the iface already has IPv4 (operator-associated USB stick), leave it alone.
bring_uplink_wlan() {
  local ifc="$1"
  local ssid psk conn

  ssid="${EDGE_WIFI_SSID:-POGCOM}"
  psk="${EDGE_WIFI_PSK:-}"
  conn="${EDGE_WIFI_CONN_NAME:-POGCOM}"

  if command -v nmcli >/dev/null 2>&1; then
    nmcli dev set "${ifc}" managed yes 2>/dev/null || true
    nmcli radio wifi on 2>/dev/null || true
  fi
  ip link set "${ifc}" up 2>/dev/null || true

  if ip -4 addr show dev "${ifc}" | grep -q 'inet '; then
    echo "uplink ${ifc}: already has IPv4 — skipping WiFi (re)associate"
  elif command -v nmcli >/dev/null 2>&1; then
    if ! nmcli -t -f NAME connection show | grep -qx "${conn}"; then
      if [[ -z "${psk}" ]]; then
        echo "FATAL: EDGE_WIFI_PSK required for ${ifc} uplink (SSID ${ssid})" >&2
        exit 1
      fi
      nmcli connection add type wifi con-name "${conn}" ifname "${ifc}" ssid "${ssid}" \
        wifi.hidden yes wifi-sec.key-mgmt wpa-psk wifi-sec.psk "${psk}"
    else
      # Prefer this iface if the profile was created for another wlan*
      nmcli connection modify "${conn}" connection.interface-name "${ifc}" 2>/dev/null || true
    fi
    nmcli connection up "${conn}" ifname "${ifc}" || nmcli device connect "${ifc}"
  else
    echo "FATAL: NetworkManager (nmcli) required for ${ifc} edge uplink" >&2
    exit 1
  fi

  local i=0
  while [[ "${i}" -lt 30 ]]; do
    if ip -4 addr show dev "${ifc}" | grep -q 'inet '; then
      break
    fi
    sleep 1
    i=$((i + 1))
  done

  if [[ "${DHCP_ONCE}" == "1" ]]; then
    pkill -f "dhclient.*${ifc}" 2>/dev/null || true
  fi

  if ! ip -4 addr show dev "${ifc}" | grep -q 'inet '; then
    echo "WARN: ${ifc} has no IPv4 after connect — check ${ssid} / PSK / AP" >&2
  fi
}

unmanage_game_ports

case "${UPLINK}" in
  eth0) bring_uplink_eth0 ;;
  wlan*) bring_uplink_wlan "${UPLINK}" ;;
esac

echo "=== edge uplink ${UPLINK} (WG transport only) ==="
ip -br addr show "${UPLINK}" 2>/dev/null || true
if [[ -n "${GAME}" ]] && [[ -d "/sys/class/net/${GAME}" ]]; then
  echo "eth_game ${GAME} (no IP — AF_PACKET):"
  ip -br addr show "${GAME}" 2>/dev/null || true
fi
