#!/bin/bash

# dns-rescue.sh — emergency DNS recovery on a machine where AdGuard Home is the
# sole local resolver (systemd-resolved is masked). If AGH fails to start, this
# machine has no DNS until you intervene. Run this script from a TTY login.
#
# Author: Justin Moore
# Version: 0.1.0

set -u

RESOLV=/etc/resolv.conf
FALLBACK=1.1.1.1

require_root() {
    if [[ $EUID -ne 0 ]]; then
        echo "Re-running with sudo..."
        exec sudo -E "$0" "$@"
    fi
}

show_status() {
    echo "=== /etc/resolv.conf ==="
    cat "$RESOLV" 2>/dev/null || echo "(missing!)"
    echo
    echo "=== AdGuard Home service ==="
    systemctl is-active adguardhome 2>&1 | head -1
    systemctl is-enabled adguardhome 2>&1 | head -1
    echo
    echo "=== Last 15 AGH log lines (this boot) ==="
    journalctl -u adguardhome -b --no-pager -n 15 2>&1 | tail -15
    echo
    echo "=== Port 53 listeners ==="
    ss -lntu 2>/dev/null | awk '/:53 /{print}' | head -5
    echo
    echo "=== Masked resolved units ==="
    systemctl is-enabled systemd-resolved.service systemd-resolved-varlink.socket systemd-resolved-monitor.socket 2>&1 | paste -d' ' - - - -
}

add_fallback_dns() {
    if grep -q "nameserver $FALLBACK" "$RESOLV" 2>/dev/null; then
        echo "$FALLBACK is already in $RESOLV — nothing to do."
        return
    fi
    echo "nameserver $FALLBACK" >> "$RESOLV"
    echo "Added fallback nameserver $FALLBACK to $RESOLV."
    echo "Test:"
    getent hosts archlinux.org && echo "  DNS now resolves."
}

restart_agh() {
    systemctl restart adguardhome
    sleep 1
    systemctl is-active adguardhome
    journalctl -u adguardhome -b --no-pager -n 10 | tail -10
}

unmask_resolved() {
    cat <<MSG
This rolls back the local-DNS setup partway:
  - unmasks systemd-resolved + its varlink/monitor sockets
  - starts systemd-resolved (will bind 127.0.0.53:53)
  - does NOT change /etc/resolv.conf, NetworkManager dropin, or nsswitch.conf

Use this if AGH itself is broken and you want resolved back as a stopgap.
You will still need to point /etc/resolv.conf at 127.0.0.53 (or let NM regenerate it)
to actually use resolved.

MSG
    read -rp "Proceed? [y/N] " ans
    [[ "$ans" =~ ^[Yy]$ ]] || { echo "Cancelled."; return; }
    systemctl unmask systemd-resolved.service systemd-resolved-varlink.socket systemd-resolved-monitor.socket
    systemctl start systemd-resolved
    systemctl status systemd-resolved --no-pager -n 5
}

menu() {
    cat <<MENU

DNS rescue menu:
  1) Show DNS status (resolv.conf, AGH state, log, port 53)
  2) Add $FALLBACK as a temporary fallback nameserver
  3) Restart AdGuard Home and tail its log
  4) Unmask + start systemd-resolved (heavier rollback)
  5) Open editor on /etc/resolv.conf
  q) Quit
MENU
    read -rp "> " choice
    case "$choice" in
        1) show_status ;;
        2) add_fallback_dns ;;
        3) restart_agh ;;
        4) unmask_resolved ;;
        5) "${EDITOR:-vi}" "$RESOLV" ;;
        q|Q) exit 0 ;;
        *) echo "Unknown choice." ;;
    esac
}

require_root "$@"

if [[ $# -gt 0 ]]; then
    case "$1" in
        status)    show_status ;;
        fallback)  add_fallback_dns ;;
        restart)   restart_agh ;;
        unmask)    unmask_resolved ;;
        *) echo "Usage: $0 [status|fallback|restart|unmask]   (no arg = interactive menu)"; exit 2 ;;
    esac
    exit 0
fi

show_status
while true; do menu; done
