#!/bin/sh /etc/rc.common

lock_file="/tmp/lock/wdoc-wg.lock"

if [ -e "$lock_file" ]; then
	old_pid=$(cat "$lock_file" 2>/dev/null)
	if [ -n "$old_pid" ] && kill -0 "$old_pid" 2>/dev/null; then
		exit 0
	fi
fi

echo "$$" > "$lock_file"
trap 'rm -f "$lock_file"' EXIT INT TERM

config_load wdoc-wg
config_get LOG  main log 1
config_get DNS1 main dns1
config_get DNS2 main dns2

log_wdoc_wg() {
	[ "$LOG" != "1" ] && return 0
	local TEXT="$1"
	[ -n "$TEXT" ] && logger -p daemon.info -t wdoc_wg "$TEXT"
}

check_internet() {
	if [ -n "$DNS1" ] && /bin/ping -4 -c 4 "$DNS1" &>/dev/null; then
		log_wdoc_wg "Internet is available, $DNS1 is responding"
		return 0
	elif [ -n "$DNS2" ] && /bin/ping -4 -c 4 "$DNS2" &>/dev/null; then
		log_wdoc_wg "Internet is available, $DNS2 is responding"
		return 0
	else
		log_wdoc_wg "No Internet through $DNS1 and $DNS2 check."
		return 1
	fi
}

wireguard_restart() {
	local iface="$1"
	log_wdoc_wg "Restarting the $iface interface..."
	ifdown "$iface"
	ifup "$iface"
}

ping_server() {
	local server_ip="$1"
	local iface="$2"
	if /bin/ping -4 -c 4 -I "$iface" "$server_ip" &>/dev/null; then
		log_wdoc_wg "Server $server_ip reachable on $iface"
		return 0
	else
		log_wdoc_wg "No connection to $server_ip on $iface"
		return 1
	fi
}

ping_endpoint_name() {
	local endpoint_name="$1"
	if /bin/ping -4 -c 4 "$endpoint_name" &>/dev/null; then
		log_wdoc_wg "Check ping $endpoint_name - OK"
		return 0
	else
		log_wdoc_wg "Check ping $endpoint_name - Error"
		return 1
	fi
}

endpoint_ip() {
	local endpoint_name="$1"
	local ip
	ip=$(nslookup "$endpoint_name" "$DNS1" 2>/dev/null | awk '/^Address: /{print $2}' | tail -n1)
	[ -z "$ip" ] && ip=$(nslookup "$endpoint_name" "$DNS2" 2>/dev/null | awk '/^Address: /{print $2}' | tail -n1)
	echo "$ip"
}

is_ip() {
    # Returns 0 if argument is a simple IPv4 address, 1 otherwise
    local ip="$1"
    [ -z "$ip" ] && return 1
    # Basic IPv4 format check
    if printf '%s' "$ip" | grep -Eq '^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$'; then
        return 0
    fi
    return 1
}

get_endpoint_name() {
	local iface="$1"
	local ep

	sec=$(uci show network | grep "=amneziawg" | grep "$iface" | awk -F= '{print $1}')
	if [ -n "$sec" ]; then
		ep=$(uci -q get "$sec".endpoint_host)
		[ -n "$ep" ] && echo "$ep" && return 0
	fi

	sec=$(uci show network | grep "=wireguard" | grep "$iface" | awk -F= '{print $1}')
	if [ -n "$sec" ]; then
		ep=$(uci -q get "$sec".endpoint_host)
		[ -n "$ep" ] && echo "$ep" && return 0
	fi

	return 1
}

process_section() {
	local iface_name="$1"
	local server_ip="$2"
	local check_inet="$3"
	local endpoint_name="$4"

	log_wdoc_wg "Check interface: $iface_name"

	if [ "$check_inet" = "1" ]; then
		log_wdoc_wg "Check internet..."
		if ! check_internet; then
			log_wdoc_wg "Internet unavailable, skipping $iface_name"
			return
		fi
	fi

	log_wdoc_wg "Check connection to server $server_ip..."
	if ping_server "$server_ip" "$iface_name"; then
		return
	fi

	wireguard_restart "$iface_name"
	sleep 20
	if ping_server "$server_ip" "$iface_name"; then
		return
	fi

	log_wdoc_wg "Check endpoint $endpoint_name..."
	if ping_endpoint_name "$endpoint_name"; then
		log_wdoc_wg "Endpoint reachable, restart WireGuard..."
		wireguard_restart "$iface_name"
		sleep 20
		ping_server "$server_ip" "$iface_name"
		return
	fi

	if is_ip "$endpoint_name"; then
		log_wdoc_wg "$endpoint_name is an IP address — skipping DNS resolution."
	else
		log_wdoc_wg "Endpoint unreachable, try resolving IP..."
		local resolved_ip
		resolved_ip=$(endpoint_ip "$endpoint_name")
		if [ -n "$resolved_ip" ]; then
			log_wdoc_wg "$endpoint_name → $resolved_ip"
			sed -i "s,$endpoint_name,$resolved_ip,g" /etc/config/network
			wireguard_restart "$iface_name"
			sed -i "s,$resolved_ip,$endpoint_name,g" /etc/config/network
			sleep 20
			ping_server "$server_ip" "$iface_name"
		else
			log_wdoc_wg "Failed to resolve $endpoint_name"
		fi
	fi
}

for section in $(uci show wdoc-wg | awk -F= '$2=="interface"{print $1}' | sed 's/^wdoc-wg\.//' | sort -u); do
	iface_name=$(uci -q get wdoc-wg.$section.iface)
	server_ip=$(uci -q get wdoc-wg.$section.ip)
	check_inet=$(uci -q get wdoc-wg.$section.check_inet)
	[ -z "$iface_name" ] || [ -z "$server_ip" ] && continue
	endpoint_name=$(get_endpoint_name "$iface_name")
	[ -z "$endpoint_name" ] && { log_wdoc_wg "No endpoint found for $iface_name, skip."; continue; }

	process_section "$iface_name" "$server_ip" "$check_inet" "$endpoint_name"
done

log_wdoc_wg "All interfaces checked."

exit 0
