#!/bin/bash
# Swapmap VPN Helper Script
# This script is installed to /opt/Swapmap/scripts/vpn-helper.sh
# It is configured in sudoers to run without password

set -e

COMMAND="$1"
PROXY_PORT="$2"
SERVER_IP="$3"

REDIRECT_PORT=$((PROXY_PORT + 1))

BACKUP_FILE="/etc/resolv.conf.swapmap.original.bak"
SYMLINK_FILE="/etc/resolv.conf.swapmap.original.symlink"
TEMP_FILE="/etc/resolv.conf.swapmap.tmp"
VPN_MARKER="# swapmap-vpn-managed"

case "$COMMAND" in
    setup)
        if [ -z "$PROXY_PORT" ]; then
            echo "Error: proxy port is required" >&2
            exit 1
        fi

        # Remove any stale state from previous crashed sessions
        rm -f "$BACKUP_FILE" "$SYMLINK_FILE" "$TEMP_FILE"

        # Clean up any previous iptables state
        iptables -t nat -F OUTPUT 2>/dev/null || true
        iptables -F OUTPUT 2>/dev/null || true
        ip6tables -t nat -F OUTPUT 2>/dev/null || true
        ip6tables -F OUTPUT 2>/dev/null || true

        # 1. Exclude traffic to proxy ports (prevent loop)
        iptables -t nat -A OUTPUT -p tcp --dport "$PROXY_PORT" -j RETURN
        iptables -t nat -A OUTPUT -p udp --dport "$PROXY_PORT" -j RETURN
        iptables -t nat -A OUTPUT -p tcp --dport "$REDIRECT_PORT" -j RETURN
        iptables -t nat -A OUTPUT -p udp --dport "$REDIRECT_PORT" -j RETURN
        ip6tables -t nat -A OUTPUT -p tcp --dport "$PROXY_PORT" -j RETURN 2>/dev/null || true
        ip6tables -t nat -A OUTPUT -p udp --dport "$PROXY_PORT" -j RETURN 2>/dev/null || true
        ip6tables -t nat -A OUTPUT -p tcp --dport "$REDIRECT_PORT" -j RETURN 2>/dev/null || true
        ip6tables -t nat -A OUTPUT -p udp --dport "$REDIRECT_PORT" -j RETURN 2>/dev/null || true

        # 2. Exclude traffic to VPN server (prevent loop)
        if [ -n "$SERVER_IP" ]; then
            iptables -t nat -A OUTPUT -d "$SERVER_IP" -j RETURN
            ip6tables -t nat -A OUTPUT -d "$SERVER_IP" -j RETURN 2>/dev/null || true
        fi

        # 3. Exclude loopback traffic
        iptables -t nat -A OUTPUT -o lo -j RETURN
        ip6tables -t nat -A OUTPUT -o lo -j RETURN 2>/dev/null || true

        # 4. Redirect all DNS (UDP port 53) to Xray SOCKS proxy
        iptables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports "$PROXY_PORT"
        ip6tables -t nat -A OUTPUT -p udp --dport 53 -j REDIRECT --to-ports "$PROXY_PORT" 2>/dev/null || true

        # 5. Redirect all TCP traffic to Xray dokodemo-door (transparent proxy)
        iptables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports "$REDIRECT_PORT"
        ip6tables -t nat -A OUTPUT -p tcp -j REDIRECT --to-ports "$REDIRECT_PORT" 2>/dev/null || true

        # 6. Force existing HTTP/HTTPS connections to reconnect through VPN
        if [ -n "$SERVER_IP" ]; then
            iptables -A OUTPUT -p tcp --dport 80 ! -d "$SERVER_IP" -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -A OUTPUT -p tcp --dport 443 ! -d "$SERVER_IP" -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -A OUTPUT -p udp --dport 443 ! -d "$SERVER_IP" -j REJECT --reject-with icmp-port-unreachable 2>/dev/null || true
        else
            iptables -A OUTPUT -p tcp --dport 80 -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -A OUTPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -A OUTPUT -p udp --dport 443 -j REJECT --reject-with icmp-port-unreachable 2>/dev/null || true
        fi
        sleep 3
        if [ -n "$SERVER_IP" ]; then
            iptables -D OUTPUT -p tcp --dport 80 ! -d "$SERVER_IP" -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -D OUTPUT -p tcp --dport 443 ! -d "$SERVER_IP" -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -D OUTPUT -p udp --dport 443 ! -d "$SERVER_IP" -j REJECT --reject-with icmp-port-unreachable 2>/dev/null || true
        else
            iptables -D OUTPUT -p tcp --dport 80 -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -D OUTPUT -p tcp --dport 443 -j REJECT --reject-with tcp-reset 2>/dev/null || true
            iptables -D OUTPUT -p udp --dport 443 -j REJECT --reject-with icmp-port-unreachable 2>/dev/null || true
        fi

        # 7. Setup DNS - force TCP DNS through proxy
        if [ -L /etc/resolv.conf ]; then
            readlink /etc/resolv.conf > "$SYMLINK_FILE"
        fi
        cat /etc/resolv.conf > "$BACKUP_FILE"

        echo "$VPN_MARKER" > "$TEMP_FILE"
        echo "nameserver 8.8.8.8" >> "$TEMP_FILE"
        echo "nameserver 1.1.1.1" >> "$TEMP_FILE"
        echo "options use-vc" >> "$TEMP_FILE"
        cat "$TEMP_FILE" > /etc/resolv.conf
        rm -f "$TEMP_FILE"

        # 8. Create authorization flag
        touch /etc/swapmap-vpn-authorized

        echo "VPN setup completed successfully"
        ;;

    cleanup)
        # Remove NAT rules
        iptables -t nat -F OUTPUT 2>/dev/null || true
        ip6tables -t nat -F OUTPUT 2>/dev/null || true

        # Remove filter rules
        iptables -F OUTPUT 2>/dev/null || true
        ip6tables -F OUTPUT 2>/dev/null || true

        # Restore DNS
        if [ -f "$BACKUP_FILE" ]; then
            if [ -f "$SYMLINK_FILE" ]; then
                saved_target=$(cat "$SYMLINK_FILE")
                if [ -L /etc/resolv.conf ]; then
                    actual_target=$(readlink -f /etc/resolv.conf)
                    cat "$BACKUP_FILE" > "$actual_target"
                else
                    rm -f /etc/resolv.conf
                    ln -s "$saved_target" /etc/resolv.conf
                    actual_target=$(readlink -f /etc/resolv.conf)
                    cat "$BACKUP_FILE" > "$actual_target"
                fi
                rm -f "$SYMLINK_FILE"
            else
                cat "$BACKUP_FILE" > /etc/resolv.conf
            fi
            rm -f "$BACKUP_FILE"
            echo "DNS restored successfully"
        else
            echo "Warning: backup file missing, DNS not restored" >&2
        fi

        # Remove authorization flag
        rm -f /etc/swapmap-vpn-authorized

        echo "VPN cleanup completed successfully"
        ;;

    *)
        echo "Error: unknown command '$COMMAND'" >&2
        echo "Usage: $0 {setup|cleanup} [proxy-port] [server-ip]" >&2
        exit 1
        ;;
esac
