#!/usr/bin/env bash
set -Eeuo pipefail
export LC_ALL=C

CONFIG_FILE="/etc/pi-car-companion/companion.env"
HOTSPOT_CONNECTION="pi-car-hotspot"
HOTSPOT_INTERFACE="wlan0"
UPSTREAM_INTERFACE="wlan1"
HOTSPOT_ADDRESS="10.42.0.1/24"
HOTSPOT_SSID="${1:-MG4-Companion}"

if [[ ${EUID} -ne 0 ]]; then
  exec sudo -- "$0" "$@"
fi
if [[ ! -f "${CONFIG_FILE}" ]]; then
  echo "Pi Car Companion is not installed. Run install.sh first." >&2
  exit 1
fi
if [[ ! "${HOTSPOT_SSID}" =~ ^[[:alnum:]_.-]{1,32}$ ]]; then
  echo "The hotspot SSID must contain 1-32 letters, numbers, dots, hyphens, or underscores." >&2
  exit 1
fi
if [[ "$(nmcli --get-values GENERAL.STATE device show "${UPSTREAM_INTERFACE}" 2>/dev/null || true)" != 100* ]]; then
  echo "${UPSTREAM_INTERFACE} must be connected to a saved upstream network before failover is enabled." >&2
  echo "Connect it first with: sudo nmcli --ask device wifi connect '<SSID>' ifname ${UPSTREAM_INTERFACE} name upstream-home" >&2
  exit 1
fi

IFS= read -r -s -p "Password for ${HOTSPOT_SSID} (8-63 characters): " hotspot_password
echo
if (( ${#hotspot_password} < 8 || ${#hotspot_password} > 63 )) || [[ ! "${hotspot_password}" =~ ^[[:print:]]+$ ]]; then
  echo "The hotspot password must contain 8-63 printable ASCII characters." >&2
  exit 1
fi
psk_hex="$(printf '%s\n' "${hotspot_password}" | wpa_passphrase "${HOTSPOT_SSID}" | sed -n 's/^[[:space:]]*psk=//p')"
if [[ ! "${psk_hex}" =~ ^[[:xdigit:]]{64}$ ]]; then
  echo "The hotspot password could not be converted into a WPA key." >&2
  exit 1
fi

hotspot_file="/etc/NetworkManager/system-connections/${HOTSPOT_CONNECTION}.nmconnection"
hotspot_uuid="$(uuidgen)"
temporary_file="$(mktemp)"
trap 'rm -f -- "${temporary_file}"' EXIT
cat > "${temporary_file}" <<EOF
[connection]
id=${HOTSPOT_CONNECTION}
uuid=${hotspot_uuid}
type=wifi
interface-name=${HOTSPOT_INTERFACE}
autoconnect=false

[wifi]
band=bg
mode=ap
ssid=${HOTSPOT_SSID}

[wifi-security]
key-mgmt=wpa-psk
psk=${psk_hex}

[ipv4]
address1=${HOTSPOT_ADDRESS}
method=shared

[ipv6]
method=disabled
EOF
if nmcli --get-values NAME connection show | grep -Fxq "${HOTSPOT_CONNECTION}"; then
  nmcli connection delete "${HOTSPOT_CONNECTION}"
fi
install -m 0600 -o root -g root "${temporary_file}" "${hotspot_file}"
nmcli connection load "${hotspot_file}"
hotspot_password=""
psk_hex=""

set_env() {
  local key="$1"
  local value="$2"
  if grep -q "^${key}=" "${CONFIG_FILE}"; then
    sed -i "s|^${key}=.*|${key}=${value}|" "${CONFIG_FILE}"
  else
    printf '%s=%s\n' "${key}" "${value}" >> "${CONFIG_FILE}"
  fi
}

set_env NETWORK_MANAGER_ENABLED true
set_env NETWORK_HOTSPOT_INTERFACE "${HOTSPOT_INTERFACE}"
set_env NETWORK_UPSTREAM_INTERFACE "${UPSTREAM_INTERFACE}"
set_env NETWORK_HOTSPOT_CONNECTION "${HOTSPOT_CONNECTION}"
set_env NETWORK_PROBE_TIMEOUT_SECONDS 60
set_env NETWORK_STABILITY_SECONDS 10
set_env NETWORK_POLL_SECONDS 5

systemctl enable --now pi-car-companion-network.service
systemctl restart pi-car-companion.service

upstream_address="$(nmcli --get-values IP4.ADDRESS device show "${UPSTREAM_INTERFACE}" | head -n 1)"
echo "Network failover is enabled."
echo "The dashboard will remain reachable through ${UPSTREAM_INTERFACE} at ${upstream_address:-its current address}."
echo "The car hotspot is ${HOTSPOT_SSID} and its dashboard address is http://10.42.0.1:8787."
