#!/usr/bin/env bash
set -euo pipefail
state=/run/cookbook-routing-lab
names=(lr-app lr-router lr-db)
[[ $EUID -eq 0 ]] || { echo 'Run with sudo on an isolated Linux VM.' >&2; exit 1; }
for tool in ip python3 curl sysctl; do command -v "$tool" >/dev/null; done
cleanup() {
  [[ -d "$state" && -f "$state/owned" ]] || { echo 'No owned lab to clean.'; return; }
  while IFS= read -r ns; do
    case "$ns" in lr-app|lr-router|lr-db) ;; *) echo 'Invalid ownership record' >&2; return 1;; esac
    if ip netns list | awk '{print $1}' | grep -Fxq "$ns"; then
      while IFS= read -r pid; do
        [[ -z "$pid" ]] || kill "$pid" 2>/dev/null || true
      done < <(ip netns pids "$ns")
      ip netns del "$ns"
    fi
  done < "$state/owned"
  rm -rf -- "$state"
}
case "${1:-}" in
  cleanup) cleanup; exit 0 ;;
  setup|connected) ;;
  *) echo "Usage: sudo bash $0 setup|connected|cleanup" >&2; exit 2 ;;
esac
[[ ! -e "$state" ]] || { echo 'Lab state exists; clean the existing lab first.' >&2; exit 1; }
for ns in "${names[@]}"; do
  if ip netns list | awk '{print $1}' | grep -Fxq "$ns"; then
    echo "Namespace $ns already exists; refusing to change it." >&2; exit 1
  fi
done
umask 077
mkdir "$state"
touch "$state/owned"
trap cleanup ERR
for ns in "${names[@]}"; do
  ip netns add "$ns"
  printf '%s\n' "$ns" >> "$state/owned"
  ip -n "$ns" link set lo up
done
ip -n lr-app link add eth0 type veth peer name app0 netns lr-router
ip -n lr-db link add eth0 type veth peer name db0 netns lr-router
ip -n lr-app addr add 10.10.0.10/24 dev eth0
ip -n lr-router addr add 10.10.0.1/24 dev app0
ip -n lr-router addr add 10.20.0.1/24 dev db0
ip -n lr-db addr add 10.20.0.10/24 dev eth0
ip -n lr-app link set eth0 up
ip -n lr-db link set eth0 up
ip -n lr-router link set app0 up
ip -n lr-router link set db0 up
ip netns exec lr-router sysctl -qw net.ipv4.ip_forward=0
# No default routes, NAT, host interfaces or host sysctls are changed.
mkdir "$state/www"
printf 'backend-ready\n' > "$state/www/health"
# Avoid HTTPServer's startup reverse-DNS lookup in this deliberately offline lab.
ip netns exec lr-db python3 -c 'import runpy,socket; socket.getfqdn=lambda name="": "lr-db"; runpy.run_module("http.server",run_name="__main__")' 8080 --bind 10.20.0.10 --directory "$state/www" > "$state/http.log" 2>&1 &
ready=0
for attempt in {1..30}; do
  if ip netns exec lr-db curl --noproxy '*' -fsS --max-time 1 http://10.20.0.10:8080/health >/dev/null 2>&1; then
    ready=1; break
  fi
  sleep 0.1
done
[[ $ready -eq 1 ]] || { echo 'Backend failed to start.' >&2; cat "$state/http.log" >&2; false; }
if [[ "$1" == connected ]]; then
  ip -n lr-app route add 10.20.0.0/24 via 10.10.0.1
  ip -n lr-db route add 10.10.0.0/24 via 10.20.0.1
  ip netns exec lr-router sysctl -qw net.ipv4.ip_forward=1
fi
trap - ERR
echo 'Created lr-app, lr-router, lr-db. Follow the routing hands-on; then run cleanup.'
