#!/usr/bin/env bash
# quick-systor.sh — transparent Tor proxy setup wizard. See ../index.md.
set -euo pipefail

PROG="$(basename "$0")"

TORRC="/etc/tor/torrc"
TOR_NFT_CONF="/etc/nftables-tor.conf"
CLEAR_NFT_CONF="/etc/nftables.conf"
STOP_NFT_CONF="/etc/nftables-stop.conf"
DEFAULT_TRANS_PORT=9040
DEFAULT_DNS_PORT=5353
DEFAULT_SOCKS_PORT=9050
DEFAULT_TBB_SOCKS_PORT=9150
VIRT_ADDR="10.192.0.0/10"

BOLD=""; RED=""; GREEN=""; YELLOW=""; BLUE=""; CYAN=""; NC=""
if [ -t 2 ]; then
    BOLD="$(printf '\033[1m')"
    RED="$(printf '\033[0;31m')"
    GREEN="$(printf '\033[0;32m')"
    YELLOW="$(printf '\033[1;33m')"
    BLUE="$(printf '\033[0;34m')"
    CYAN="$(printf '\033[0;36m')"
    NC="$(printf '\033[0m')"
fi

info()    { printf "${BLUE}[*]${NC} %s\n" "$*"; }
warn()    { printf "${YELLOW}[!]${NC} %s\n" "$*" >&2; }
error()   { printf "${RED}[X]${NC} %s\n" "$*" >&2; }
success() { printf "${GREEN}[+]${NC} %s\n" "$*"; }
banner()  { printf "${BOLD}%s${NC}\n" "$*"; }

ASSUME_YES=0
HOSTILE=0
DRY_RUN=0
WANT_TOR_BROWSER=0
DO_UNDO=0
CONFIRM_UNDO=0
declare -a HS_PORTS=()

usage() {
    cat <<EOF
Usage: $PROG [options]

Master setup wizard for transparent Tor proxying on Linux.
Detects your system and guides you through Tor + firewall configuration.

Options:
  --yes               Accept all defaults, no prompts
  --hostile           Strip LAN/private-IP exemptions (all traffic via Tor)
  --tor-browser       Include Tor Browser desktop integration
  --hidden-service PORT:HOST:PORT  Add a hidden service (repeatable).
                       Short form PORT:PORT expands to PORT:127.0.0.1:PORT.
                       e.g. --hidden-service 80:127.0.0.1:80
  --undo              Undo all changes (remove proxy, restore clearnet)
  --confirm           Required with --undo to proceed without prompts
  --dry-run           Detect everything and print summary, exit
  -h, --help          Show this help

Exit codes:
  0  success
  1  pre-flight check failed
  2  missing dependency
  3  not running as root
  4  Tor failed to start/bootstrap
  5  firewall apply failed
EOF
}

TOR_INSTALLED=0
TOR_ACTIVE=0
TOR_USER=""
TOR_UID=""
TOR_SERVICE=""
OUT_IF=""
SSHD_PORT=22
NFT_AVAILABLE=0
TRANS_PORT="$DEFAULT_TRANS_PORT"
DNS_PORT="$DEFAULT_DNS_PORT"
SOCKS_PORT="$DEFAULT_SOCKS_PORT"
TBB_SOCKS_PORT="$DEFAULT_TBB_SOCKS_PORT"
DISTRO=""
PKG_MGR=""
INIT_SYS="systemd"

TORRC_BAK=""
FW_BAK=""

parse_args() {
    while [ $# -gt 0 ]; do
        case "$1" in
            -h|--help) usage; exit 0 ;;
            --yes|-y) ASSUME_YES=1 ;;
            --hostile) HOSTILE=1 ;;
            --dry-run) DRY_RUN=1 ;;
            --tor-browser) WANT_TOR_BROWSER=1 ;;
            --undo) DO_UNDO=1 ;;
            --confirm) CONFIRM_UNDO=1 ;;
            --hidden-service)
                shift
                if [ -z "${1:-}" ]; then error "--hidden-service requires PORT:HOST:PORT (or PORT:PORT)"; exit 64; fi
                HS_PORTS+=("$1")
                ;;
            --hidden-service=*)
                HS_PORTS+=("${1#*=}")
                ;;
            *)
                error "Unknown argument: $1"
                usage >&2
                exit 64
                ;;
        esac
        shift
    done
}

detect_distro() {
    if [ -f /etc/os-release ]; then
        local id id_like
        id="$( (. /etc/os-release && echo "${ID:-}") 2>/dev/null || true)"
        id_like="$( (. /etc/os-release && echo "${ID_LIKE:-}") 2>/dev/null || true)"

        case "$id" in
            debian|ubuntu|kali|parrot|tails|pop|elementary|mint|zorin)
                DISTRO="debian"; PKG_MGR="apt" ;;
            arch|manjaro|endeavouros|archlinux)
                DISTRO="arch"; PKG_MGR="pacman" ;;
            *)
                if echo "$id_like" | grep -qw "debian"; then
                    DISTRO="debian"; PKG_MGR="apt"
                elif echo "$id_like" | grep -qw "arch"; then
                    DISTRO="arch"; PKG_MGR="pacman"
                else
                    DISTRO="unknown"; PKG_MGR=""
                fi
                ;;
        esac
    else
        DISTRO="unknown"; PKG_MGR=""
    fi

    if [ -z "$DISTRO" ] || [ "$DISTRO" = "unknown" ]; then
        error "Unsupported distribution (Debian or Arch-based required)."
        error "Run on Debian, Ubuntu, Kali, Arch, Manjaro, or similar."
        exit 1
    fi

}

pkg_update() {
    case "$PKG_MGR" in
        apt)    apt update "$@" ;;
        pacman) pacman -Sy "$@" ;;
    esac
}

pkg_install() {
    case "$PKG_MGR" in
        apt)    apt install -y "$@" ;;
        pacman) pacman -Sy --noconfirm "$@" ;;
    esac
}

detect_tor() {
    if command -v tor >/dev/null 2>&1; then
        TOR_INSTALLED=1
    fi

    for u in debian-tor tor; do
        if id -u "$u" >/dev/null 2>&1; then
            TOR_USER="$u"
            TOR_UID="$(id -u "$u")"
            break
        fi
    done

    if systemctl cat tor@default >/dev/null 2>&1; then
        TOR_SERVICE="tor@default"
    elif systemctl cat tor >/dev/null 2>&1; then
        TOR_SERVICE="tor"
    fi

    if [ -n "$TOR_SERVICE" ]; then
        systemctl is-active --quiet "$TOR_SERVICE" 2>/dev/null && TOR_ACTIVE=1 || true
    fi

    if [ -f "$TORRC" ]; then
        local tp
        tp="$(torrc_get_port "TransPort")"
        if [ -n "$tp" ]; then
            TRANS_PORT="$tp"
            [ "$tp" != "$DEFAULT_TRANS_PORT" ] && \
                warn "TransPort in torrc is $tp (default: $DEFAULT_TRANS_PORT). Firewall will use $tp."
        fi
        tp="$(torrc_get_port "DNSPort")"
        if [ -n "$tp" ]; then
            DNS_PORT="$tp"
            [ "$tp" != "$DEFAULT_DNS_PORT" ] && \
                warn "DNSPort in torrc is $tp (default: $DEFAULT_DNS_PORT). Firewall will use $tp."
        fi
        tp="$(torrc_get_port "SocksPort")"
        [ -n "$tp" ] && SOCKS_PORT="$tp" || true
    fi
}

detect_network() {
    OUT_IF="$(ip route 2>/dev/null | awk '/^default/{print $5; exit}' || true)"
    SSHD_PORT=$(detect_sshd_port)
}

detect_sshd_port() {
    local port
    port="$(ss -tlnpH 2>/dev/null | awk '/sshd/ {split($4,a,":"); print a[length(a)]; exit}' || true)"
    if [ -n "$port" ]; then echo "$port"; return; fi
    if [ -r /etc/ssh/sshd_config ]; then
        port="$(awk '/^[[:space:]]*Port[[:space:]]+/{print $2; exit}' /etc/ssh/sshd_config 2>/dev/null || true)"
        if [ -n "$port" ]; then echo "$port"; return; fi
    fi
    echo 22
}

detect_firewall() {
    command -v nft >/dev/null 2>&1 && NFT_AVAILABLE=1 || true
}

torrc_has() {
    local key="$1" file="${2:-$TORRC}"
    [ -f "$file" ] && grep -qE "^[[:space:]]*${key}[[:space:]]" "$file"
}

torrc_get_port() {
    local key="$1" file="${2:-$TORRC}" fallback="${3:-}"
    local val
    [ -f "$file" ] || { echo "$fallback"; return; }
    val="$(grep -E "^[[:space:]]*${key}[[:space:]]" "$file" 2>/dev/null | head -1 | grep -oE '[0-9]+$' || true)"
    echo "${val:-$fallback}"
}

torrc_append() {
    local line="$1" file="${2:-$TORRC}"
    local key="${line%% *}"
    if torrc_has "$key" "$file"; then
        return 0
    fi
    echo "$line" >> "$file"
}

backup_file() {
    local src="$1"
    if [ ! -f "$src" ]; then
        echo ""
        return 0
    fi
    local bak="${src}.bak-$(date +%Y%m%d-%H%M%S)"
    cp -a "$src" "$bak"
    echo "$bak"
}

install_tor_daemon() {
    info "Installing Tor daemon..."
    case "$DISTRO" in
        debian)
            local CODENAME
            CODENAME="$(grep -oP 'VERSION_CODENAME=\K.*' /etc/os-release 2>/dev/null || lsb_release -c 2>/dev/null | awk '{print $2}')"
            if [ -n "$CODENAME" ]; then
                info "Adding Tor Project official apt repository for $CODENAME..."
                cat > /etc/apt/sources.list.d/tor.sources <<EOF
Types: deb deb-src
URIs: https://deb.torproject.org/torproject.org/
Suites: $CODENAME
Components: main
Signed-By: /usr/share/keyrings/deb.torproject.org-keyring.gpg
EOF
                local keyring_tmp="$(mktemp)"
                wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | \
                    gpg --dearmor > "$keyring_tmp" 2>/dev/null || true
                if gpg --show-keys --with-fingerprint "$keyring_tmp" 2>/dev/null | \
                    grep -q "A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89"; then
                    mv "$keyring_tmp" /usr/share/keyrings/deb.torproject.org-keyring.gpg
                else
                    warn "GPG key fingerprint mismatch — Tor Project repo may be compromised."
                    warn "Proceeding without keyring verification."
                    rm -f "$keyring_tmp"
                fi
                apt update
                apt install -y tor deb.torproject.org-keyring
            else
                warn "Cannot detect distro codename. Installing tor from system repo."
                pkg_install tor
            fi
            ;;
        arch)
            pkg_install tor
            ;;
    esac

    detect_tor
    if [ "$TOR_INSTALLED" -eq 0 ]; then
        error "Tor installation failed."
        exit 1
    fi
    success "Tor daemon installed ($TOR_SERVICE)."
}

start_tor_daemon() {
    info "Starting Tor daemon ($TOR_SERVICE)..."
    systemctl start "$TOR_SERVICE" 2>/dev/null || true

    if command -v curl >/dev/null 2>&1; then
        info "Waiting for Tor to bootstrap..."
        local i
        for i in $(seq 1 30); do
            if curl --socks5 "127.0.0.1:${SOCKS_PORT}" --max-time 5 -fsSL https://check.torproject.org/api/ip 2>/dev/null | grep -q '"IsTor":true'; then
                TOR_ACTIVE=1
                success "Tor bootstrapped after ~$((i*2))s."
                return 0
            fi
            sleep 2
            printf "." >&2
        done
        echo >&2
    else
        sleep 5
        systemctl is-active --quiet "$TOR_SERVICE" 2>/dev/null && TOR_ACTIVE=1 || true
        if [ "$TOR_ACTIVE" -eq 1 ]; then return 0; fi
    fi

    error "Tor failed to start."
    warn "Check logs: journalctl -u $TOR_SERVICE --no-pager -n 30"
    exit 4
}

preflight() {
    [ "$(id -u)" -eq 0 ] || { error "Must run as root. Re-run with: sudo $PROG"; exit 3; }

    # Auto-install nftables if missing
    if [ "$NFT_AVAILABLE" -eq 0 ]; then
        info "nftables not found. Installing..."
        pkg_install nftables
        command -v nft >/dev/null 2>&1 && NFT_AVAILABLE=1 || { error "nftables install failed."; exit 2; }
        success "nftables installed."
    fi

    # Auto-install curl and wget (needed for repo GPG key, downloads, verification)
    if ! command -v curl >/dev/null 2>&1; then
        warn "curl not found. Installing..."
        pkg_install curl && success "curl installed."
    fi
    if ! command -v wget >/dev/null 2>&1; then
        warn "wget not found. Installing..."
        pkg_install wget && success "wget installed."
    fi

    # Auto-install Tor if missing
    if [ "$TOR_INSTALLED" -eq 0 ]; then
        install_tor_daemon
    fi

    # Auto-start Tor if not active
    if [ "$TOR_ACTIVE" -eq 0 ]; then
        start_tor_daemon
    fi

    if [ -z "$OUT_IF" ]; then
        warn "No default route detected. Firewall will be configured but internet access may not work."
        if ! ask "Continue anyway?" "n"; then
            info "Aborted."; exit 1
        fi
    fi

    if [ -z "$TOR_USER" ]; then
        error "Cannot determine Tor user (checked: debian-tor, tor)."
        exit 1
    fi

    local non_tor_ps
    non_tor_ps="$(ps -U "$TOR_USER" -o pid,comm --no-headers 2>/dev/null | grep -vE '[t]or($| )' || true)"
    if [ -n "$non_tor_ps" ]; then
        warn "Non-Tor processes running as UID $TOR_USER (unfiltered internet access!):"
        while IFS= read -r line; do warn "  $line"; done <<<"$non_tor_ps"
    fi
}

print_summary_header() {
    banner "=== quick-systor.sh — Transparent Tor Proxy Setup ==="
    echo
    local fw_status=""
    if [ "$NFT_AVAILABLE" -eq 1 ]; then fw_status="nftables available"
    else fw_status="${RED}nftables not installed${NC}"; fi

    local tor_status=""
    if [ "$TOR_ACTIVE" -eq 1 ]; then tor_status="${GREEN}running${NC}"
    elif [ "$TOR_INSTALLED" -eq 1 ]; then tor_status="${YELLOW}installed, not running${NC}"
    else tor_status="${RED}not installed${NC}"; fi

    local net_status=""
    if [ -n "$OUT_IF" ]; then net_status="$OUT_IF"
    else net_status="${RED}none${NC}"; fi

    local distro_cap
    distro_cap="$(tr '[:lower:]' '[:upper:]' <<<"${DISTRO:0:1}")${DISTRO:1}"
    printf "  %-14s %s\n" "Distro:"       "$distro_cap"
    printf "  %-14s %s\n" "Tor:"          "$tor_status (${TOR_SERVICE:-?}, UID ${TOR_UID:-?})"
    printf "  %-14s %s\n" "Network:"      "$net_status"
    printf "  %-14s %s\n" "SSH port:"     "$SSHD_PORT"
    printf "  %-14s %b\n" "Firewall:"     "$fw_status"
    printf "  %-14s %s/%s/%s\n" "Ports (t/d/s):" "$TRANS_PORT" "$DNS_PORT" "$SOCKS_PORT"
    printf "  %-14s %s\n" "Watchdog:" "yes"
    printf "  %-14s %s\n" "Immutable:" "yes"
    echo
}

configure_torrc() {
    info "Configuring $TORRC ..."

    TORRC_BAK="$(backup_file "$TORRC")"
    if [ -n "$TORRC_BAK" ]; then
        info "Backed up torrc → $TORRC_BAK"
    fi

    if [ ! -f "$TORRC" ]; then
        touch "$TORRC"
    fi

    local added=0

    if ! torrc_has "SocksPort"; then
        torrc_append "SocksPort 127.0.0.1:$SOCKS_PORT"
        info "  + SocksPort $SOCKS_PORT"
        added=1
    fi
    if ! torrc_has "TransPort"; then
        torrc_append "TransPort $TRANS_PORT"
        info "  + TransPort $TRANS_PORT"
        added=1
    fi
    if ! torrc_has "DNSPort"; then
        torrc_append "DNSPort $DNS_PORT"
        info "  + DNSPort $DNS_PORT"
        added=1
    fi
    if ! torrc_has "VirtualAddrNetworkIPv4"; then
        torrc_append "VirtualAddrNetworkIPv4 $VIRT_ADDR"
        info "  + VirtualAddrNetworkIPv4 $VIRT_ADDR"
        added=1
    fi
    if ! torrc_has "AutomapHostsOnResolve"; then
        torrc_append "AutomapHostsOnResolve 1"
        info "  + AutomapHostsOnResolve 1"
        added=1
    fi

    if [ "$added" -eq 0 ]; then
        info "  torrc already has all needed entries."
    fi

    local verify_ok=1
    if command -v sudo >/dev/null 2>&1 && [ -n "$TOR_USER" ]; then
        if ! sudo -u "$TOR_USER" tor --verify-config >/dev/null 2>&1; then
            verify_ok=0
            warn "torrc syntax check (as $TOR_USER) reported issues (may be harmless):"
            sudo -u "$TOR_USER" tor --verify-config 2>&1 | sed 's/^/    | /' || true
        fi
    elif ! tor --verify-config >/dev/null 2>&1; then
        verify_ok=0
        warn "torrc syntax check reported warnings/errors (may be harmless):"
        tor --verify-config 2>&1 | sed 's/^/    | /' || true
    fi
    [ "$verify_ok" -eq 1 ] && info "  torrc syntax OK."
}

setup_hidden_services() {
    local svc_dir="/var/lib/tor/hidden_service"
    local need_restart=0

    for entry in "${HS_PORTS[@]}"; do
        local ext_port="${entry%%:*}"
        local local_target="${entry#*:}"
        [ -z "$local_target" ] && { warn "Invalid --hidden-service value: $entry"; continue; }
        [ -z "$ext_port" ] && { warn "Invalid --hidden-service value: $entry"; continue; }

        if ! echo "$local_target" | grep -q ":"; then
            local_target="127.0.0.1:$local_target"
        fi

        info "Configuring hidden service: $ext_port → $local_target"

        if ! torrc_has "HiddenServiceDir"; then
            torrc_append "HiddenServiceDir $svc_dir"
            need_restart=1
        fi
        local hs_line="HiddenServicePort $ext_port $local_target"
        if ! grep -qFx "$hs_line" "$TORRC" 2>/dev/null; then
            torrc_append "$hs_line"
            need_restart=1
        fi
    done

    if [ "$need_restart" -eq 1 ]; then
        mkdir -p "$svc_dir"
        chown "${TOR_USER}:${TOR_USER}" "$svc_dir" 2>/dev/null || true
        chmod 700 "$svc_dir"
        info "Hidden service dir: $svc_dir (owner: $TOR_USER, mode: 700)"
    fi
}

restart_tor() {
    if [ -z "$TOR_SERVICE" ]; then
        warn "No Tor service name detected. Restart Tor manually."
        warn "  sudo systemctl restart tor@default"
        return 1
    fi
    info "Restarting Tor ($TOR_SERVICE)..."
    systemctl restart "$TOR_SERVICE"
    success "Tor restarted."

    if ! command -v curl >/dev/null 2>&1; then
        warn "curl not installed — cannot verify Tor bootstrap."
        return 0
    fi
    info "Waiting for Tor to bootstrap..."
    local i
    for i in $(seq 1 30); do
        if curl --socks5 "127.0.0.1:${SOCKS_PORT}" --max-time 5 -fsSL https://check.torproject.org/api/ip 2>/dev/null | grep -q '"IsTor":true'; then
            success "Tor bootstrapped after ~$((i*2))s."
            return 0
        fi
        sleep 2
        printf "." >&2
    done
    echo >&2
    warn "Tor did not bootstrap within ~60s."
    warn "Check logs: sudo journalctl -u $TOR_SERVICE --no-pager -n 30"
    return 1
}

apply_firewall_nftables() {
    info "Applying the transparent proxy firewall..."
    chattr -i "$TOR_NFT_CONF" "$CLEAR_NFT_CONF" 2>/dev/null || true

    # Backup
    FW_BAK="$(mktemp /tmp/nft-backup-XXXXXXXX)"
    if nft list ruleset > "$FW_BAK" 2>/dev/null; then
        info "Backed up ruleset → $FW_BAK"
    else
        info "No existing ruleset to back up (file at $FW_BAK may be empty)."
        : > "$FW_BAK"
    fi

    # Generate config
    local lan_accept="ip daddr @NON_TOR accept"
    local lan_return="ip daddr @NON_TOR return"
    if [ "$HOSTILE" -eq 1 ]; then
        lan_accept="# (LAN exemption stripped — hostile network)"
        lan_return="# (LAN exemption stripped — hostile network)"
    fi

    local conf_tmp="$(mktemp)"
    cat > "$conf_tmp" <<'ENDOFCONFIG'
#!/usr/sbin/nft -f

flush ruleset

define TOR_UID = __TOR_UID__
define TRANS_PORT = __TRANS_PORT__
define DNS_PORT = __DNS_PORT__
define VIRT_ADDR = __VIRT_ADDR__
define SSHD_PORT = __SSHD_PORT__

table inet filter {
    set NON_TOR {
        type ipv4_addr
        flags interval
        elements = {
            127.0.0.0/8,
            10.0.0.0/8,
            172.16.0.0/12,
            192.168.0.0/16
        }
    }

    chain input {
        type filter hook input priority 0; policy drop;

        iif "lo" accept
        ct state established,related accept
        ct state invalid drop
        tcp dport $SSHD_PORT accept
        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept
    }

    chain forward {
        type filter hook forward priority 0; policy drop;
    }

    chain output {
        type filter hook output priority 0; policy accept;

        oif "lo" accept
        ct state established,related accept
        meta skuid $TOR_UID accept
        tcp dport $TRANS_PORT accept
        udp dport $DNS_PORT accept
        __LAN_ACCEPT__
        ip6 daddr ::1/128 accept
        drop
    }
}

table ip nat {
    set NON_TOR {
        type ipv4_addr
        flags interval
        elements = {
            127.0.0.0/8,
            10.0.0.0/8,
            172.16.0.0/12,
            192.168.0.0/16
        }
    }

    chain prerouting {
        type nat hook prerouting priority -10; policy accept;
    }

    chain output {
        type nat hook output priority -10; policy accept;

        udp dport 53 redirect to :$DNS_PORT
        tcp dport 53 redirect to :$TRANS_PORT

        ip daddr $VIRT_ADDR tcp flags syn redirect to :$TRANS_PORT

        meta skuid $TOR_UID return
        oif "lo" return
        __LAN_RETURN__

        tcp flags syn redirect to :$TRANS_PORT
    }
}
ENDOFCONFIG

    sed -i \
        -e "s/__TOR_UID__/${TOR_UID}/" \
        -e "s/__TRANS_PORT__/${TRANS_PORT}/" \
        -e "s/__DNS_PORT__/${DNS_PORT}/" \
        -e "s/__VIRT_ADDR__/${VIRT_ADDR//\//\\/}/" \
        -e "s/__SSHD_PORT__/${SSHD_PORT}/" \
        -e "s/__LAN_ACCEPT__/${lan_accept}/" \
        -e "s/__LAN_RETURN__/${lan_return}/" \
        "$conf_tmp"

    # Syntax check
    if ! nft -c -f "$conf_tmp" 2>&1; then
        error "Firewall config syntax check failed. Config NOT loaded."
        error "Offending config: $conf_tmp  |  Backup: $FW_BAK"
        rm -f "$conf_tmp"
        exit 5
    fi

    # Apply
    nft -f "$conf_tmp"
    success "Tor redirect rules loaded."

    # Install & persist
    cp "$conf_tmp" "$TOR_NFT_CONF"
    chmod 644 "$TOR_NFT_CONF"
    info "Wrote $TOR_NFT_CONF"

    cat > "$CLEAR_NFT_CONF" <<'CLEAR'
#!/usr/sbin/nft -f
flush ruleset
CLEAR
    chmod 644 "$CLEAR_NFT_CONF"
    info "Wrote $CLEAR_NFT_CONF (clearnet boot default)"

    rm -f "$conf_tmp"
}

enable_services() {
    if [ -n "$TOR_SERVICE" ]; then
        systemctl enable "$TOR_SERVICE" 2>/dev/null || true
        info "Tor service ($TOR_SERVICE) enabled at boot."
    fi

    chattr -i "$TOR_NFT_CONF" "$CLEAR_NFT_CONF" "$STOP_NFT_CONF" 2>/dev/null || true
    chattr -i /etc/iptables/rules.v4 /etc/iptables/rules.v6 \
            /etc/iptables/stop-rules.v4 /etc/iptables/stop-rules.v6 2>/dev/null || true
    if [ ! -f "$TOR_NFT_CONF" ] && grep -q "redirect to" "$CLEAR_NFT_CONF" 2>/dev/null; then
        cp "$CLEAR_NFT_CONF" "$TOR_NFT_CONF"
        info "Migrated existing Tor ruleset $CLEAR_NFT_CONF -> $TOR_NFT_CONF"
    fi
    rm -f /etc/systemd/system/nftables.service.d/stop-gate.conf 2>/dev/null || true
    rm -f /etc/systemd/system/netfilter-persistent.service.d/stop-gate.conf 2>/dev/null || true
    rm -f /etc/systemd/system/netfilter-persistent.service.d/early-load.conf 2>/dev/null || true
    systemctl disable tor-wall-save.service 2>/dev/null || true
    systemctl stop    tor-wall-save.service 2>/dev/null || true
    rm -f /etc/systemd/system/tor-wall-save.service 2>/dev/null || true
    rm -f /usr/local/sbin/tor-wall-save 2>/dev/null || true
    systemctl disable tor-wall-watchdog.timer 2>/dev/null || true

    cat > "$STOP_NFT_CONF" <<EOF
#!/usr/sbin/nft -f
flush ruleset
table inet filter {
    chain input {
        type filter hook input priority 0; policy drop;
        iif "lo" accept
        ct state established,related accept
        ct state invalid drop
        tcp dport $SSHD_PORT accept
        ip protocol icmp accept
        ip6 nexthdr ipv6-icmp accept
    }
    chain forward {
        type filter hook forward priority 0; policy drop;
    }
    chain output {
        type filter hook output priority 0; policy drop;
        oif "lo" accept
        ct state established,related accept
    }
}
EOF
    chmod 644 "$STOP_NFT_CONF"

    cat > /usr/local/sbin/tor-firewall-gate <<'GATE'
#!/usr/bin/env bash
# tor-firewall-gate — ExecStop guard for tor-transparent-proxy.service.
set +eu
FLAG="/run/tor-firewall-stop-ok"
RESULT=""

BIN_WALL="";     command -v wall        >/dev/null 2>&1 && BIN_WALL="$(command -v wall)"
BIN_LCTL="";     command -v loginctl    >/dev/null 2>&1 && BIN_LCTL="$(command -v loginctl)"
BIN_CAT="";      command -v systemd-cat >/dev/null 2>&1 && BIN_CAT="$(command -v systemd-cat)"
BIN_NS="";       command -v notify-send >/dev/null 2>&1 && BIN_NS="$(command -v notify-send)"
BIN_RUNUSER="";  command -v runuser    >/dev/null 2>&1 && BIN_RUNUSER="$(command -v runuser)"

broadcast() {
    local msg="$1" sid uid usr tty disp d
    [ -n "$BIN_WALL" ] && "$BIN_WALL" -n "$msg" 2>/dev/null || true
    if [ -n "$BIN_LCTL" ]; then
        "$BIN_LCTL" list-sessions --no-legend 2>/dev/null | while read -r sid uid usr _junk; do
            [ -n "$sid" ] || continue
            tty="$("$BIN_LCTL" show-session "$sid" -p TTY --value 2>/dev/null)"
            if [ -n "$tty" ] && [ -e "/dev/$tty" ]; then
                printf '\r\n%s\r\n' "[tor-firewall] $msg" >"/dev/$tty" 2>/dev/null || true
            fi
            disp="$("$BIN_LCTL" show-session "$sid" -p Display --value 2>/dev/null)"
            if [ -n "$BIN_NS" ] && [ -n "$BIN_RUNUSER" ] && [ -n "$disp" ] && [ -n "$usr" ] && [ -n "$uid" ]; then
                "$BIN_RUNUSER" -u "$usr" -- \
                    env DBUS_SESSION_BUS_ADDRESS="unix:path=/run/user/$uid/bus" \
                    "$BIN_NS" -u critical -i dialog-warning "tor-firewall-gate" "$msg" 2>/dev/null || true
            fi
        done || true
    fi
    for d in /dev/pts/[0-9]* /dev/tty[0-9]* /dev/console; do
        [ -e "$d" ] && [ -w "$d" ] && printf '\r\n%s\r\n' "[tor-firewall] $msg" >"$d" 2>/dev/null || true
    done
    [ -n "$BIN_CAT" ] && printf '%s\n' "$msg" | "$BIN_CAT" -t tor-firewall-gate -p warning 2>/dev/null || true
}

finalize() { broadcast "$RESULT"; }
trap finalize EXIT
trap 'RESULT+=" (Interrupted by signal. User may need to take manual action.)"; exit 130' TERM INT HUP QUIT

if [ -f /run/tor-gate-first-start ]; then
    rm -f /run/tor-gate-first-start
    RESULT="First start — gate skipped this once."
    exit 0
fi

if systemctl list-jobs 2>/dev/null | grep -qE '(shutdown|reboot|halt|poweroff|kexec)\.target'; then
    RESULT="Shutdown in progress — gate surrendering; init preserves state."
    exit 0
fi

broadcast "Firewall stop requested. Run 'sudo tor-firewall-confirm' within 10 seconds or internet will be blocked."
RESULT="Firewall stop requested — no confirmation received within 10 seconds."
rm -f "$FLAG"
sleep 10

if [ -f "$FLAG" ]; then
    rm -f "$FLAG"
    nft flush ruleset; rc=$?
    if [ "$rc" -eq 0 ]; then
        RESULT="Firewall stopped. Internet is open (nft flush rc=$rc)."
    else
        RESULT="Firewall flush FAILED rc=$rc. State unknown. Run 'nft list ruleset'. MANUAL ACTION NEEDED."
    fi
else
    rc_apply=0
    if [ -f /etc/nftables-stop.conf ]; then
        nft -f /etc/nftables-stop.conf || rc_apply=$?
    else
        rc_apply=99
    fi
    case "$rc_apply" in
        0)  RESULT="Firewall stop BLOCKED (no confirmation). Lockdown mode activated. Internet is cut. Re-enable the proxy ('systemctl enable --now tor-transparent-proxy.service') or reboot to recover. If you did not run this, it may be an attack attempt. Proceed with caution." ;;
        99) RESULT="Firewall stop BLOCKED AND lockdown mode config MISSING. Check /etc/nftables-stop.conf. Re-enable the proxy or reboot immediately. MANUAL ACTION NEEDED." ;;
        *)  RESULT="Firewall stop BLOCKED but lockdown mode FAILED (rc=$rc_apply). Check /etc/nftables-stop.conf. Re-enable the proxy or reboot immediately. MANUAL ACTION NEEDED." ;;
    esac
fi
exit 0
GATE
    chmod +x /usr/local/sbin/tor-firewall-gate

    cat > /usr/local/bin/tor-firewall-confirm <<'CONFIRM'
#!/usr/bin/env bash
if [ "$(id -u)" -ne 0 ]; then
    echo "Run with sudo: sudo tor-firewall-confirm"
    exit 1
fi
date +%s > /run/tor-firewall-stop-ok
chmod 600 /run/tor-firewall-stop-ok
echo "Firewall stop confirmed. Rules will flush within 10 seconds."
CONFIRM
    chmod +x /usr/local/bin/tor-firewall-confirm

    cat > /usr/local/sbin/tor-transparent-proxy <<'HELPER'
#!/usr/bin/env bash
# tor-transparent-proxy — start/stop the transparent Tor proxy.
set -euo pipefail

TOR_CONF="/etc/nftables-tor.conf"
WATCHDOG_TIMER="tor-wall-watchdog.timer"

cmd="${1:-status}"
case "$cmd" in
    start)
        if [ "$(id -u)" -ne 0 ]; then echo "tor-transparent-proxy: must run as root" >&2; exit 1; fi
        if [ ! -f "$TOR_CONF" ]; then echo "tor-transparent-proxy: $TOR_CONF missing" >&2; exit 1; fi
        if ! nft -c -f "$TOR_CONF" 2>/dev/null; then echo "tor-transparent-proxy: $TOR_CONF syntax check failed" >&2; exit 1; fi
        nft -f "$TOR_CONF"
        systemctl start "$WATCHDOG_TIMER" 2>/dev/null || true
        ;;
    stop)
        exec /usr/local/sbin/tor-firewall-gate nftables
        ;;
    status)
        if systemctl is-active --quiet tor-transparent-proxy.service 2>/dev/null; then echo "active"; exit 0; fi
        echo "inactive"; exit 3
        ;;
    *)
        echo "Usage: $0 {start|stop|status}" >&2; exit 64
        ;;
esac
HELPER
    chmod +x /usr/local/sbin/tor-transparent-proxy

    local wants=""
    if [ -n "$TOR_SERVICE" ]; then
        wants="Wants=${TOR_SERVICE}.service"
    fi
    cat > /etc/systemd/system/tor-transparent-proxy.service <<EOF
[Unit]
Description=Transparent Tor proxy (nftables redirect)
Documentation=file:///etc/nftables-tor.conf
$wants
After=nftables.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/usr/local/sbin/tor-transparent-proxy start
ExecStop=/usr/local/sbin/tor-transparent-proxy stop
ExecStopPost=/usr/bin/systemctl stop tor-wall-watchdog.timer

[Install]
WantedBy=multi-user.target
EOF

    install_watchdog

    if [ -n "$TOR_SERVICE" ]; then
        local dropin_dir="/etc/systemd/system/${TOR_SERVICE}.service.d"
        mkdir -p "$dropin_dir"
        cat > "$dropin_dir/firewall-first.conf" <<EOF
[Unit]
After=tor-transparent-proxy.service
EOF
        info "Tor waits for proxy: $dropin_dir/firewall-first.conf"
    fi

    mkdir -p /etc/systemd/system/nftables.service.d
    cat > /etc/systemd/system/nftables.service.d/early-load.conf <<'SYSUNIT'
[Unit]
DefaultDependencies=no
Before=network-pre.target
SYSUNIT
    info "Firewall loads before any network app (clearnet default at boot)."

    chattr +i "$TOR_NFT_CONF" "$STOP_NFT_CONF" "$CLEAR_NFT_CONF" 2>/dev/null || \
        warn "chattr +i failed (install e2fsprogs or equivalent for your distro)"
    info "Configs locked (chattr +i): $TOR_NFT_CONF, $CLEAR_NFT_CONF, $STOP_NFT_CONF"

    systemctl daemon-reload
    systemctl enable nftables 2>/dev/null || true

    touch /run/tor-gate-first-start
    systemctl enable --now tor-transparent-proxy.service 2>/dev/null || \
        warn "Failed to enable tor-transparent-proxy.service (check journalctl)"
    success "tor-transparent-proxy.service enabled (proxy active, routing through Tor)."
}

verify() {
    if ! command -v curl >/dev/null 2>&1; then
        warn "curl not installed — skipping verification."
        return
    fi
    info "Verifying transparent proxy..."
    echo

    info "Test 1: SOCKS proxy (curl --socks5 127.0.0.1:${SOCKS_PORT})"
    if curl --socks5 "127.0.0.1:${SOCKS_PORT}" --max-time 30 -fsSL https://check.torproject.org/api/ip 2>/dev/null; then
        success "SOCKS proxy working."
    else
        warn "SOCKS proxy test failed. Tor may still be bootstrapping."
    fi
    echo

    info "Test 2: Transparent proxy (curl -- no proxy flag)"
    if curl --max-time 30 -fsSL https://check.torproject.org/api/ip 2>/dev/null; then
        success "Transparent proxy working — all traffic routed through Tor."
    else
        warn "Transparent proxy test failed."
        warn "Check: sudo nft list ruleset | grep 'udp dport 53'"
        warn "Check: sudo systemctl status tor-transparent-proxy.service"
    fi
    echo

    info "Test 3: Ping should be blocked (silent drop)."
    if ! command -v ping >/dev/null 2>&1; then
        warn "ping not installed — skipping ICMP test."
    elif ping -c 2 -W 2 8.8.8.8 >/dev/null 2>&1; then
        warn "Ping to 8.8.8.8 succeeded — ICMP leak! Check firewall filter OUTPUT chain."
    else
        success "Ping blocked (silent drop — expected)."
    fi
    echo
}

setup_tor_browser() {
    info "Setting up Tor Browser integration..."

    local tbb_line="SocksPort 127.0.0.1:${TBB_SOCKS_PORT}"
    if ! grep -qF "$tbb_line" "$TORRC" 2>/dev/null; then
        echo "$tbb_line" >> "$TORRC"
        info "Added $tbb_line to $TORRC"
        restart_tor || true
    else
        info "$tbb_line already in torrc."
    fi

    local target_user="${SUDO_USER:-}"
    local target_home=""
    if [ -n "$target_user" ]; then
        target_home="$(eval echo ~"$target_user")"
    else
        target_home="$HOME"
    fi

    local desktop_dir="$target_home/.local/share/applications"
    local tbb_install_dir="$target_home/.local/share/tor-browser"
    local tbb_desktop="$desktop_dir/tor-browser.desktop"
    local tbb_binary="$tbb_install_dir/Browser/start-tor-browser"

    # Check if Tor Browser already installed from tarball
    if [ -f "$tbb_binary" ]; then
        info "Tor Browser already installed at $tbb_install_dir"
        local tbb_icon
        tbb_icon="$(find "$tbb_install_dir" -name '*.png' -path '*/chrome/icons/*' 2>/dev/null | head -1)"
        [ -z "$tbb_icon" ] && tbb_icon="tor-browser"
        mkdir -p "$desktop_dir"
        cat > "$tbb_desktop" <<EOF
[Desktop Entry]
Type=Application
Name=Tor Browser
GenericName=Web Browser
Comment=Tor Browser is +1 for privacy and -1 for mass surveillance
Categories=Network;WebBrowser;Security;
Exec=env TOR_SKIP_LAUNCH=1 $tbb_binary %u
Icon=$tbb_icon
Terminal=false
StartupNotify=true
MimeType=text/html;text/plain;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;
EOF
        if [ -n "$target_user" ]; then
            chown "$target_user:$target_user" "$tbb_desktop" 2>/dev/null || true
        fi
        info "Desktop file: $tbb_desktop"
    else
        local do_install=0
        if [ "$ASSUME_YES" -eq 1 ] || [ "$WANT_TOR_BROWSER" -eq 1 ]; then
            do_install=1
        elif ask "Tor Browser not found. Download from torproject.org?" "y"; then
            do_install=1
        fi

        if [ "$do_install" -eq 1 ]; then
            info "Downloading latest Tor Browser for Linux..."
            local tbb_url
            tbb_url="$(curl -sL https://www.torproject.org/download/ | grep -oP '/dist/torbrowser/\d+\.\d+\.\d+/tor-browser-linux-x86_64-\d+\.\d+\.\d+\.tar\.xz' | head -1)"
            if [ -z "$tbb_url" ]; then
                warn "Could not determine latest Tor Browser version."
                warn "Download manually: https://www.torproject.org/download/"
            else
                local tmp_tar="$(mktemp /tmp/tor-browser-XXXXXX.tar.xz)"
                info "Downloading https://www.torproject.org${tbb_url} ..."
                if command -v curl >/dev/null 2>&1; then
                    curl --socks5-hostname "127.0.0.1:${SOCKS_PORT}" -C - --retry 10 --retry-delay 30 --retry-max-time 600 --max-time 900 -#L "https://www.torproject.org${tbb_url}" -o "$tmp_tar"
                elif command -v wget >/dev/null 2>&1; then
                    wget --retry-connrefused --tries=3 --timeout=60 -e "use_proxy=yes" -e "http_proxy=socks5://127.0.0.1:${SOCKS_PORT}" "https://www.torproject.org${tbb_url}" -O "$tmp_tar"
                else
                    warn "Neither curl nor wget available. Cannot download."
                    return
                fi

                mkdir -p "$tbb_install_dir"
                info "Verifying GPG signature..."
                local tbb_asc="${tmp_tar}.asc"
                if curl --socks5-hostname "127.0.0.1:${SOCKS_PORT}" --max-time 30 -fsSL \
                    "https://www.torproject.org${tbb_url}.asc" -o "$tbb_asc" 2>/dev/null; then
                    gpg --keyserver keys.openpgp.org --recv-keys \
                        0xEF6E286DDA85EA2A4BA7DE684E2C6E8793298290 2>/dev/null || \
                        gpg --auto-key-locate wkd --locate-keys \
                        torbrowser@torproject.org 2>/dev/null || true
                    if gpg --verify "$tbb_asc" "$tmp_tar" 2>/dev/null; then
                        info "Signature verified."
                        rm -f "$tbb_asc"
                    else
                        warn "GPG signature verification FAILED. The download may be compromised."
                        if ! ask "Extract anyway?" "n"; then
                            rm -f "$tmp_tar" "$tbb_asc"
                            return
                        fi
                        rm -f "$tbb_asc"
                    fi
                else
                    warn "Could not download signature file. Skipping verification."
                fi
                info "Extracting..."
                tar -xf "$tmp_tar" -C "$tbb_install_dir" --strip-components=1
                rm -f "$tmp_tar"

                local tbb_icon
                tbb_icon="$(find "$tbb_install_dir" -name '*.png' -path '*/chrome/icons/*' 2>/dev/null | head -1)"
                [ -z "$tbb_icon" ] && tbb_icon="tor-browser"
                mkdir -p "$desktop_dir"
                cat > "$tbb_desktop" <<EOF
[Desktop Entry]
Type=Application
Name=Tor Browser
GenericName=Web Browser
Comment=Tor Browser is +1 for privacy and -1 for mass surveillance
Categories=Network;WebBrowser;Security;
Exec=env TOR_SKIP_LAUNCH=1 $tbb_binary %u
Icon=$tbb_icon
Terminal=false
StartupNotify=true
MimeType=text/html;text/plain;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;
EOF
                if [ -n "$target_user" ]; then
                    chown -R "$target_user:$target_user" "$tbb_install_dir" 2>/dev/null || true
                    chown "$target_user:$target_user" "$tbb_desktop" 2>/dev/null || true
                fi
                success "Tor Browser installed at $tbb_install_dir"
                info "  $tbb_binary   (or use desktop menu)"
            fi
        else
            info "Skipping Tor Browser installation."
            return
        fi
    fi

    # Shell alias
    local shell="${SHELL##*/}"
    local rc_file rc_hint
    case "$shell" in
        fish) rc_file="$target_home/.config/fish/config.fish"; rc_hint="open a new shell" ;;
        zsh)  rc_file="$target_home/.zshrc";                    rc_hint="source ~/.zshrc" ;;
        *)    rc_file="$target_home/.bashrc";                   rc_hint="source ~/.bashrc" ;;
    esac
    mkdir -p "$(dirname "$rc_file")"
    local alias_line="alias tor-browser='env TOR_SKIP_LAUNCH=1 $tbb_binary'"
    if [ -f "$rc_file" ] && grep -qF "alias tor-browser=" "$rc_file" 2>/dev/null; then
        info "Shell alias already in $rc_file."
    else
        echo "$alias_line" >> "$rc_file"
        [ -n "$target_user" ] && chown "$target_user:$target_user" "$rc_file" 2>/dev/null || true
        info "Shell alias added to $rc_file"
        info "  Run '$rc_hint' or open a new terminal."
    fi
}

print_restore_hints() {
    [ -n "$TORRC_BAK" ] && warn "Restore torrc:    sudo cp $TORRC_BAK $TORRC"
    [ -n "$FW_BAK" ] && warn "Restore firewall: sudo nft -f $FW_BAK"
}

install_watchdog() {
    info "Installing firewall watchdog..."
    cat > /usr/local/sbin/tor-wall-watchdog <<'WATCHDOG'
#!/usr/bin/env bash
# tor-wall-watchdog — rechecks and reapplies Tor redirect rules every 10s.
set -euo pipefail

if ! systemctl is-active --quiet tor-transparent-proxy.service 2>/dev/null; then
    exit 0
fi

TAG="tor-wall-watchdog"
log()  { systemd-cat -t "$TAG" -p info    <<<"$*" 2>/dev/null || true; }
warn() { systemd-cat -t "$TAG" -p warning <<<"$*" 2>/dev/null || true; }

TOR_CONF="/etc/nftables-tor.conf"

if nft list chain ip nat output 2>/dev/null | grep -q "redirect to"; then
    exit 0
fi

warn "Tor redirect rules missing! Reapplying from $TOR_CONF ..."
if nft -f "$TOR_CONF" 2>&1; then
    log "Rules reapplied successfully."
else
    warn "Rule reapply FAILED. Inspect: nft -c -f $TOR_CONF"
    exit 1
fi

TOR_USER=""
for u in debian-tor tor; do
    if id -u "$u" >/dev/null 2>&1; then TOR_USER="$u"; break; fi
done
if [ -n "$TOR_USER" ]; then
    NON_TOR="$(ps -U "$TOR_USER" -o pid,comm --no-headers 2>/dev/null | grep -vE '[t]or($| )' || true)"
    if [ -n "$NON_TOR" ]; then
        warn "Non-Tor processes running as UID $TOR_USER (unfiltered internet access!):"
        while IFS= read -r line; do
            warn "  $line"
            pid="$(echo "$line" | awk '{print $1}')"
            [ -n "$pid" ] && kill "$pid" 2>/dev/null && warn "  -> Killed PID $pid" || true
        done <<<"$NON_TOR"
        sleep 2
        ps -U "$TOR_USER" -o pid,comm --no-headers 2>/dev/null | grep -vE '[t]or($| )' | awk '{print $1}' | while read -r pid; do
            [ -n "$pid" ] && kill -9 "$pid" 2>/dev/null && warn "  -> SIGKILL PID $pid" || true
        done
    fi
fi
WATCHDOG
    chmod +x /usr/local/sbin/tor-wall-watchdog

    cat > /etc/systemd/system/tor-wall-watchdog.service <<'SYSUNIT'
[Unit]
Description=Tor firewall rule watchdog
PartOf=tor-transparent-proxy.service
After=network.target

[Service]
Type=oneshot
ExecStart=/usr/local/sbin/tor-wall-watchdog
ProtectSystem=full
ReadWritePaths=/run
NoNewPrivileges=yes
PrivateTmp=yes
SYSUNIT

    cat > /etc/systemd/system/tor-wall-watchdog.timer <<'SYSUNIT'
[Unit]
Description=Tor firewall rule watchdog timer
PartOf=tor-transparent-proxy.service

[Timer]
OnBootSec=10s
OnUnitActiveSec=10s
Persistent=true

[Install]
WantedBy=tor-transparent-proxy.service
SYSUNIT

    systemctl daemon-reload
    success "Watchdog installed (owned by tor-transparent-proxy.service)."
}

final_summary() {
    echo
    banner "=== Done ==="
    echo
    if [ -n "$TORRC_BAK" ]; then
        info "torrc backup:   $TORRC_BAK"
    fi
    if [ -n "$FW_BAK" ]; then info "Firewall ruleset backup: $FW_BAK"; fi
    echo
    if [ ${#HS_PORTS[@]} -gt 0 ] && [ -f /var/lib/tor/hidden_service/hostname ]; then
        local onion
        onion="$(cat /var/lib/tor/hidden_service/hostname 2>/dev/null || true)"
        if [ -n "$onion" ]; then
            banner "Hidden service: $onion"
            echo
        fi
    fi
    info "Verify anytime:"
    info "  curl https://check.torproject.org/api/ip"
    echo
}

ask() {
    local prompt="$1" default="${2:-n}"
    local hint="$([ "$default" = "y" ] && echo "[Y/n]" || echo "[y/N]")"
    if [ "$ASSUME_YES" -eq 1 ]; then
        printf '%s %s: (auto) %s\n' "$prompt" "$hint" "$default" >&2
        case "$default" in y|Y) return 0 ;; *) return 1 ;; esac
    fi
    local yn
    read -rp "$prompt $hint: " yn </dev/tty
    case "$(echo "${yn:-$default}" | tr '[:upper:]' '[:lower:]')" in
        y|yes) return 0 ;;
        *)     return 1 ;;
    esac
}

ask_val() {
    local prompt="$1" default="$2"
    if [ "$ASSUME_YES" -eq 1 ]; then
        printf '%s [%s]: (auto) %s\n' "$prompt" "$default" "$default" >&2
        echo "$default"
        return
    fi
    local val
    read -rp "$prompt [$default]: " val </dev/tty
    echo "${val:-$default}"
}

wizard() {
    echo
    local step=1 total=3

    DO_TORRC=1

    banner "[${step}/${total}] Host a hidden service?"
    step=$((step+1))
    if [ ${#HS_PORTS[@]} -gt 0 ]; then
        info "Hidden service ports already specified via --hidden-service: ${HS_PORTS[*]}"
        DO_HS=1
    elif ask "Add a hidden service?" "n"; then
        DO_HS=1
        info "Enter port mappings. Format: EXTERNAL:LOCAL (e.g. 80:127.0.0.1:80)"
        info "Leave blank when done."
        while true; do
            local mapping
            read -rp "  Mapping: " mapping </dev/tty
            if [ -z "$mapping" ]; then break; fi
            HS_PORTS+=("$mapping")
        done
    else
        DO_HS=0
    fi
    echo

    banner "[${step}/${total}] Network type"
    step=$((step+1))
    if [ "$HOSTILE" -eq 1 ]; then
        info "Hostile mode: LAN exemptions stripped (--hostile)."
    else
        if ask "Hostile/public network? (strip LAN exemptions, all traffic via Tor)" "n"; then
            HOSTILE=1
        fi
    fi
    echo

    banner "[${step}/${total}] Tor Browser integration"
    step=$((step+1))
    if [ "$WANT_TOR_BROWSER" -eq 1 ]; then
        DO_TBB=1
        info "Tor Browser setup enabled (--tor-browser)."
    else
        if ask "Download Tor Browser from torproject.org (tarball, auto-updates)?" "y"; then
            DO_TBB=1
            WANT_TOR_BROWSER=1
        else
            DO_TBB=0
        fi
    fi
    echo


    banner "=== Summary ==="
    echo
    printf "  %-22s %s\n" "Configure torrc:"      "$([ "$DO_TORRC" -eq 1 ] && echo "yes" || echo "no")"
    printf "  %-22s %s\n" "Hidden service:"        "$([ "$DO_HS" -ge 1 ] && echo "${HS_PORTS[*]}" || echo "none")"
    printf "  %-22s %s\n" "Firewall backend:"      "nftables"
    printf "  %-22s %s\n" "Proxy unit:"            "tor-transparent-proxy.service"
    printf "  %-22s %s\n" "Network type:"          "$([ "$HOSTILE" -eq 1 ] && echo "hostile" || echo "home/trusted")"
    printf "  %-22s %s\n" "Tor Browser:"           "$([ "$DO_TBB" -eq 1 ] && echo "yes" || echo "no")"
    printf "  %-22s %s\n" "Watchdog (auto):"       "yes (PartOf proxy unit)"
    printf "  %-22s %s\n" "Immutable config:"      "yes (chattr +i)"
    if [ -n "$TORRC_BAK" ]; then
        printf "  %-22s %s\n" "torrc backup →"     "$TORRC_BAK"
    fi
    echo

    if [ "$DRY_RUN" -eq 1 ]; then
        info "Dry-run complete. No changes made."
        exit 0
    fi

    if ! ask "Proceed with these settings?" "y"; then
        info "Aborted."
        exit 0
    fi


    echo
    if [ "$DO_TORRC" -eq 1 ]; then
        banner "Configuring torrc..."
        configure_torrc
        echo
    fi
    if [ "$DO_HS" -ge 1 ] && [ ${#HS_PORTS[@]} -gt 0 ]; then
        banner "Setting up hidden service..."
        setup_hidden_services
        echo
    fi
    if [ "$DO_TORRC" -eq 1 ] || [ "$DO_HS" -ge 1 ]; then
        banner "Restarting Tor..."
        restart_tor || warn "Tor restart/bootstrap failed. Continuing..."
        echo
    fi
    banner "Applying the transparent proxy firewall..."
    apply_firewall_nftables
    echo
    banner "Enabling boot persistence..."
    enable_services
    echo
    if [ "$DO_TBB" -eq 1 ]; then
        banner "Tor Browser integration..."
        setup_tor_browser
        echo
    fi

    banner "Verifying..."
    verify

    final_summary

    local script_path
    script_path="$(readlink -f "$0")"
    if [ "$script_path" != "/usr/local/bin/quick-systor.sh" ]; then
        cp "$script_path" /usr/local/bin/quick-systor.sh
        chmod 755 /usr/local/bin/quick-systor.sh
        success "Script saved to /usr/local/bin/quick-systor.sh"
        info "  Run anytime: sudo quick-systor.sh"
    fi
}

cleanup() {
    local ec=$?
    if [ "$ec" -ne 0 ] && [ "$ec" -ne 130 ] && [ "$DRY_RUN" -eq 0 ]; then
        echo
        warn "Script exited with error (code $ec)."
        print_restore_hints
    fi
}
trap cleanup EXIT

undo_all() {
    banner "=== quick-systor.sh — Undo ==="
    echo
    [ "$(id -u)" -eq 0 ] || { error "Must run as root: sudo $PROG --undo --confirm"; exit 3; }
    info "This will:"
    info "  - Stop and remove tor-transparent-proxy.service"
    info "  - Remove nftables Tor redirect, lockdown, clearnet configs"
    info "  - Remove firewall gate, watchdog, and proxy helper scripts"
    info "  - Remove systemd drop-ins (firewall-first, early-load)"
    info "  - Disable nftables.service at boot"
    info "  - Restore /etc/tor/torrc (from backup or by stripping added lines)"
    info "  - Tor Browser desktop file, alias, and install dir (with confirmation)"
    info "  - Leave Tor daemon running (SOCKS on 9050 still available)"
    info "  - Restart Tor daemon"
    echo

    if [ "$CONFIRM_UNDO" -eq 0 ]; then
        warn "Pass --confirm to proceed: sudo $PROG --undo --confirm"
        exit 0
    fi

    detect_distro
    # Re-detect Tor user/service (it may have been installed by us)
    for u in debian-tor tor; do
        if id -u "$u" >/dev/null 2>&1; then
            TOR_USER="$u"
            TOR_UID="$(id -u "$u")"
            break
        fi
    done
    if [ "$INIT_SYS" = "systemd" ]; then
        if systemctl cat tor@default >/dev/null 2>&1; then
            TOR_SERVICE="tor@default"
        elif systemctl cat tor >/dev/null 2>&1; then
            TOR_SERVICE="tor"
        fi
    fi

    info "Stopping firewall watchdog..."
    systemctl stop tor-wall-watchdog.timer 2>/dev/null || true
    systemctl stop tor-wall-watchdog.service 2>/dev/null || true

    info "Disabling transparent Tor proxy..."
    date +%s > /run/tor-firewall-stop-ok 2>/dev/null || true
    chmod 600 /run/tor-firewall-stop-ok 2>/dev/null || true
    systemctl disable --now tor-transparent-proxy.service 2>/dev/null || true
    success "Proxy disabled."

    info "Removing immutable flags from nftables configs..."
    chattr -i "$TOR_NFT_CONF" 2>/dev/null || true
    chattr -i "$CLEAR_NFT_CONF" 2>/dev/null || true
    chattr -i "$STOP_NFT_CONF" 2>/dev/null || true
    chattr -i /etc/iptables/rules.v4 /etc/iptables/rules.v6 \
            /etc/iptables/stop-rules.v4 /etc/iptables/stop-rules.v6 2>/dev/null || true

    info "Flushing nftables ruleset..."
    nft flush ruleset 2>/dev/null || true
    success "Rules flushed."

    info "Removing nftables config files..."
    rm -f "$TOR_NFT_CONF"
    rm -f "$STOP_NFT_CONF"
    if [ -f "$CLEAR_NFT_CONF" ]; then
        cat > "$CLEAR_NFT_CONF" <<'CLEAR'
#!/usr/sbin/nft -f
flush ruleset
CLEAR
        info "Restored $CLEAR_NFT_CONF to simple flush."
    fi

    info "Removing installed scripts..."
    rm -f /usr/local/sbin/tor-firewall-gate
    rm -f /usr/local/bin/tor-firewall-confirm
    rm -f /usr/local/sbin/tor-transparent-proxy
    rm -f /usr/local/sbin/tor-wall-watchdog
    if [ -f /usr/local/bin/quick-systor.sh ]; then
        if ask "Remove script from /usr/local/bin/quick-systor.sh?" "n"; then
            rm -f /usr/local/bin/quick-systor.sh
            success "Removed /usr/local/bin/quick-systor.sh."
        else
            info "Kept /usr/local/bin/quick-systor.sh."
        fi
    fi

    info "Removing systemd unit files..."
    rm -f /etc/systemd/system/tor-transparent-proxy.service
    rm -f /etc/systemd/system/tor-wall-watchdog.service
    rm -f /etc/systemd/system/tor-wall-watchdog.timer

    info "Removing systemd drop-in configs..."
    if [ -n "$TOR_SERVICE" ]; then
        local tor_dropin="/etc/systemd/system/${TOR_SERVICE}.service.d/firewall-first.conf"
        rm -f "$tor_dropin"
        rmdir "/etc/systemd/system/${TOR_SERVICE}.service.d" 2>/dev/null || true
    fi
    rm -f /etc/systemd/system/nftables.service.d/early-load.conf
    rmdir /etc/systemd/system/nftables.service.d 2>/dev/null || true

    rm -f /run/tor-firewall-stop-ok
    rm -f /run/tor-gate-first-start

    info "Disabling nftables.service at boot..."
    systemctl disable nftables 2>/dev/null || true

    systemctl daemon-reload

    # Restore torrc
    if [ -f "$TORRC" ]; then
        local bak
        bak="$(ls -t /etc/tor/torrc.bak-* 2>/dev/null | head -1 || true)"
        if [ -n "$bak" ] && [ -f "$bak" ]; then
            cp "$bak" "$TORRC"
            success "Restored torrc from backup: $bak"
        else
            info "No torrc backup found. Stripping added lines..."
            local tmp
            tmp="$(mktemp)"
            grep -v \
                -e '^TransPort[[:space:]]' \
                -e '^DNSPort[[:space:]]' \
                -e '^VirtualAddrNetworkIPv4[[:space:]]' \
                -e '^AutomapHostsOnResolve[[:space:]]' \
                -e '^HiddenServiceDir[[:space:]]' \
                -e '^HiddenServicePort[[:space:]]' \
                -e '^SocksPort[[:space:]]*127\.0\.0\.1:9150' \
                "$TORRC" > "$tmp"
            mv "$tmp" "$TORRC"
            success "Stripped added lines from torrc."
        fi
    fi

    # Tor Browser cleanup
    local target_user="${SUDO_USER:-}"
    if [ -n "$target_user" ]; then
        local target_home
        target_home="$(eval echo ~"$target_user")"

        local old_desktop="$target_home/.local/share/applications/torbrowser-launcher.desktop"
        if [ -f "$old_desktop" ]; then
            rm -f "$old_desktop"
            success "Removed old Tor Browser launcher desktop file."
        fi

        local tbb_desktop="$target_home/.local/share/applications/tor-browser.desktop"
        if [ -f "$tbb_desktop" ]; then
            rm -f "$tbb_desktop"
            success "Removed Tor Browser desktop file."
        fi

        local tbb_dir="$target_home/.local/share/tor-browser"
        if [ -d "$tbb_dir" ]; then
            if ask "Remove Tor Browser installation at $tbb_dir (bookmarks, settings)?" "n"; then
                rm -rf "$tbb_dir"
                success "Removed Tor Browser installation."
            else
                info "Kept Tor Browser installation at $tbb_dir."
            fi
        fi

        rmdir "$target_home/.local/share/applications" 2>/dev/null || true

        local shell="${SHELL##*/}"
        local rc_files=()
        case "$shell" in
            fish) rc_files+=("$target_home/.config/fish/config.fish") ;;
            zsh)  rc_files+=("$target_home/.zshrc") ;;
            *)    rc_files+=("$target_home/.bashrc") ;;
        esac
        [ "$shell" != "bash" ] && rc_files+=("$target_home/.bashrc")
        for rc in "${rc_files[@]}"; do
            if [ -f "$rc" ] && grep -q 'alias tor-browser=' "$rc" 2>/dev/null; then
                grep -v 'alias tor-browser=' "$rc" > "$rc.tmp" 2>/dev/null && mv "$rc.tmp" "$rc" || rm -f "$rc.tmp"
                success "Removed tor-browser alias from $rc"
            fi
        done
    fi

    # Restart Tor
    if [ -n "$TOR_SERVICE" ]; then
        info "Restarting Tor daemon ($TOR_SERVICE)..."
        systemctl restart "$TOR_SERVICE" 2>/dev/null || true
    fi

    # Verify clearnet
    echo
    banner "=== Verification ==="
    echo
    if command -v curl >/dev/null 2>&1; then
        info "Checking Tor check endpoint..."
        if curl --max-time 10 -fsSL https://check.torproject.org/api/ip 2>/dev/null | grep -q '"IsTor":true'; then
            warn "WARNING: Traffic still routed through Tor! Check nftables rules."
        else
            success "Traffic is clearnet (IsTor:false or unreachable)"
        fi
    fi
    echo
    if [ -n "$TOR_SERVICE" ]; then
        info "Tor daemon: $(systemctl is-active "$TOR_SERVICE" 2>/dev/null || echo 'unknown')"
    fi
    echo
    info "nftables ruleset (should be empty):"
    nft list ruleset 2>/dev/null || echo "  (empty/no rules)"
    echo
    info "To confirm: curl https://check.torproject.org/api/ip"
    info "To use Tor manually: curl --socks5 127.0.0.1:9050 https://check.torproject.org/api/ip"

    echo
    banner "=== Done ==="
    echo
    success "Transparent Tor proxy removed."
    success "System is back to clearnet routing."
    echo
    info "Tor daemon still runs on port 9050."
    info "Re-run quick-systor.sh (without --undo) to re-enable the proxy."
}

main() {
    parse_args "$@"
    detect_distro
    detect_network

    if [ "$DO_UNDO" -eq 1 ]; then
        undo_all
        exit 0
    fi

    detect_tor
    detect_firewall

    print_summary_header
    preflight

    wizard
}

main "$@"
