#!/bin/bash

# Exit immediately if a command exits with a non-zero status
set -e

export DEBIAN_FRONTEND=noninteractive

# Text colors for console output
GREEN='\033[0;32m'
CYAN='\033[0;36m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

# Helper function to read input interactively even when script is executed via curl pipe
prompt_read() {
    local prompt_text="$1"
    local var_name="$2"
    if [ -t 0 ]; then
        read -r -p "$prompt_text" "$var_name"
    elif [ -e /dev/tty ]; then
        read -r -p "$prompt_text" "$var_name" < /dev/tty
    else
        read -r -p "$prompt_text" "$var_name"
    fi
}

echo -e "${CYAN}======================================================${NC}"
echo -e "${CYAN}    Oracle Cloud Native WireGuard VPN Installer       ${NC}"
echo -e "${CYAN}======================================================${NC}"
echo ""

# 1. Root Check
if [[ $EUID -ne 0 ]]; then
   echo -e "${RED}[ERROR] This script must be run as root or with sudo.${NC}"
   exit 1
fi

# 2. Network Discovery
echo -e "${YELLOW}Gathering network information...${NC}"
DETECTED_IP=$(curl -s ifconfig.me || wget -qO- ifconfig.me)
prompt_read "Enter your server's Public IP address [$DETECTED_IP]: " PUBLIC_IP
PUBLIC_IP=${PUBLIC_IP:-$DETECTED_IP}

DETECTED_IFACE=$(ip -4 route show default 2>/dev/null | awk '{for(i=1;i<=NF;i++) if($i=="dev") print $(i+1)}' | head -n 1)
prompt_read "Enter your primary network interface [$DETECTED_IFACE]: " IFACE
IFACE=${IFACE:-$DETECTED_IFACE}

echo -e "${GREEN}[OK] Public IP: $PUBLIC_IP${NC}"
echo -e "${GREEN}[OK] Interface: $IFACE${NC}"
echo ""

# 3. Install Dependencies
echo -e "${YELLOW}Installing system utilities and firewall packages...${NC}"
# Preseed debconf so iptables-persistent install does not prompt interactively
echo iptables-persistent iptables-persistent/autosave_v4 boolean true | debconf-set-selections
echo iptables-persistent iptables-persistent/autosave_v6 boolean true | debconf-set-selections
apt-get update -y
DEBIAN_FRONTEND=noninteractive apt-get install -y wireguard qrencode netcat-openbsd iptables iptables-persistent netfilter-persistent
echo -e "${GREEN}[OK] Dependencies installed.${NC}"
echo ""

# 4. Firewall Configuration (iptables)
echo -e "${YELLOW}Applying Firewall Rules...${NC}"

# Clear any duplicate INPUT rules for WireGuard port from previous attempts
while iptables -C INPUT -p udp --dport 51820 -j ACCEPT 2>/dev/null; do
    iptables -D INPUT -p udp --dport 51820 -j ACCEPT
done
# CRITICAL: Force rule to Position 1 in INPUT chain to bypass default REJECT lines
iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT

# Clean up any existing duplicate WireGuard FORWARD rules
while iptables -C FORWARD -i wg0 -o "${IFACE}" -j ACCEPT 2>/dev/null; do
    iptables -D FORWARD -i wg0 -o "${IFACE}" -j ACCEPT
done
while iptables -C FORWARD -i "${IFACE}" -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2>/dev/null; do
    iptables -D FORWARD -i "${IFACE}" -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
done
while iptables -C FORWARD -i wg0 -o wg0 -j ACCEPT 2>/dev/null; do
    iptables -D FORWARD -i wg0 -o wg0 -j ACCEPT
done

# CRITICAL FORWARDING RULES: Insert at top of FORWARD chain to bypass default DROP/REJECT
# 1) Forward VPN client outgoing traffic to Internet via WAN interface
iptables -I FORWARD 1 -i wg0 -o "${IFACE}" -j ACCEPT
# 2) Forward return established/related traffic from Internet back to VPN client
iptables -I FORWARD 2 -i "${IFACE}" -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT
# 3) Forward traffic between VPN clients if needed
iptables -I FORWARD 3 -i wg0 -o wg0 -j ACCEPT

# NAT Masquerading: Ensure traffic exiting WAN interface gets masqueraded
while iptables -t nat -C POSTROUTING -o "${IFACE}" -j MASQUERADE 2>/dev/null; do
    iptables -t nat -D POSTROUTING -o "${IFACE}" -j MASQUERADE
done
iptables -t nat -I POSTROUTING 1 -o "${IFACE}" -j MASQUERADE

# TCP MSS Clamping: Prevent MTU packet black holes for VPN clients
while iptables -t mangle -C POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null; do
    iptables -t mangle -D POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
done
iptables -t mangle -I POSTROUTING 1 -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu

echo -e "${GREEN}[OK] Firewall rules applied.${NC}"
echo ""

# 5. Kernel Packet Forwarding
echo -e "${YELLOW}Enabling kernel packet forwarding...${NC}"
sysctl -w net.ipv4.ip_forward=1
sed -i 's/#net.ipv4.ip_forward=1/net.ipv4.ip_forward=1/' /etc/sysctl.conf
if ! grep -q "net.ipv4.ip_forward=1" /etc/sysctl.conf; then
    echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
fi
echo "net.ipv4.ip_forward=1" > /etc/sysctl.d/99-wireguard-forwarding.conf
sysctl --system 2>/dev/null || sysctl -p
echo -e "${GREEN}[OK] Kernel forwarding enabled.${NC}"
echo ""

# 6. Keys Generation
echo -e "${YELLOW}Generating cryptographic key pairs...${NC}"
mkdir -p /etc/wireguard/keys
chmod 700 /etc/wireguard/keys
cd /etc/wireguard/keys

wg genkey | tee server_private.key | wg pubkey > server_public.key
wg genkey | tee client_private.key | wg pubkey > client_public.key

SERVER_PRIV=$(cat server_private.key)
SERVER_PUB=$(cat server_public.key)
CLIENT_PRIV=$(cat client_private.key)
CLIENT_PUB=$(cat client_public.key)
echo -e "${GREEN}[OK] Key pairs generated.${NC}"
echo ""

# 7. Write Server Config
echo -e "${YELLOW}Writing server configuration (/etc/wireguard/wg0.conf)...${NC}"
cat <<EOF > /etc/wireguard/wg0.conf
[Interface]
Address = 10.0.0.1/24
SaveConfig = false
ListenPort = 51820
PrivateKey = ${SERVER_PRIV}

PostUp = iptables -I INPUT 1 -p udp --dport 51820 -j ACCEPT; iptables -I FORWARD 1 -i wg0 -o ${IFACE} -j ACCEPT; iptables -I FORWARD 2 -i ${IFACE} -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT; iptables -t nat -A POSTROUTING -o ${IFACE} -j MASQUERADE; iptables -t mangle -A POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu
PostDown = iptables -D INPUT -p udp --dport 51820 -j ACCEPT 2>/dev/null || true; iptables -D FORWARD -i wg0 -o ${IFACE} -j ACCEPT 2>/dev/null || true; iptables -D FORWARD -i ${IFACE} -o wg0 -m conntrack --ctstate ESTABLISHED,RELATED -j ACCEPT 2>/dev/null || true; iptables -t nat -D POSTROUTING -o ${IFACE} -j MASQUERADE 2>/dev/null || true; iptables -t mangle -D POSTROUTING -p tcp --tcp-flags SYN,RST SYN -j TCPMSS --clamp-mss-to-pmtu 2>/dev/null || true

[Peer]
PublicKey = ${CLIENT_PUB}
AllowedIPs = 10.0.0.2/32
EOF
chmod 600 /etc/wireguard/wg0.conf
echo -e "${GREEN}[OK] Server configuration saved.${NC}"
echo ""

# 8. Write Client Config
echo -e "${YELLOW}Writing client configuration (android-client.conf)...${NC}"
cat <<EOF > /etc/wireguard/android-client.conf
[Interface]
Address = 10.0.0.2/24
PrivateKey = ${CLIENT_PRIV}
DNS = 1.1.1.1, 1.0.0.1

[Peer]
PublicKey = ${SERVER_PUB}
Endpoint = ${PUBLIC_IP}:51820
AllowedIPs = 0.0.0.0/0
PersistentKeepalive = 25
EOF
echo -e "${GREEN}[OK] Client configuration saved.${NC}"
echo ""

# 9. Start WireGuard Service and Save Persistent Firewall Rules
echo -e "${YELLOW}Starting WireGuard service...${NC}"
systemctl enable --now wg-quick@wg0
systemctl restart wg-quick@wg0
echo -e "${GREEN}[OK] WireGuard service started.${NC}"
echo ""

echo -e "${YELLOW}Saving persistent iptables rules across reboots...${NC}"
mkdir -p /etc/iptables
iptables-save | tee /etc/iptables/rules.v4 > /dev/null
if command -v ip6tables-save >/dev/null 2>&1; then
    ip6tables-save | tee /etc/iptables/rules.v6 > /dev/null
fi
netfilter-persistent save
systemctl enable netfilter-persistent
echo -e "${GREEN}[OK] iptables-persistent rules saved and enabled.${NC}"
echo ""

# 10. Compact QR Code Output
echo -e "${CYAN}======================================================${NC}"
echo -e "${CYAN}    Deployment Stable! Scan QR Code via WireGuard App ${NC}"
echo -e "${CYAN}======================================================${NC}"
echo ""
qrencode -t ansiutf8 -l L -m 1 < /etc/wireguard/android-client.conf
echo ""
echo -e "${YELLOW}To view runtime statistics and handshakes, execute:${NC}"
echo -e "${CYAN}sudo wg show${NC}"
echo ""

# 11. Cloud Firewall Reminder (at the very end)
echo -e "${CYAN}------------------------------------------------------${NC}"
echo -e "${YELLOW}[REMINDER] OCI / Cloud Console Ingress Rule Required:${NC}"
echo -e "Ensure your Cloud Provider VCN Ingress Rules allow:"
echo -e "  - Source: ${GREEN}0.0.0.0/0${NC}"
echo -e "  - Protocol: ${GREEN}UDP${NC}"
echo -e "  - Destination Port: ${GREEN}51820${NC}"
echo -e "${CYAN}------------------------------------------------------${NC}"