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

lock_file="/tmp/lock/wdoc-warp.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-warp
config_get LOG main log 0
config_get CHECK_INET1 main check_inet1
config_get CHECK_INET2 main check_inet2
config_get CHECK_DELAY main check_delay 0
config_get DELAY_AVG main delay_avg

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

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

ping_interface() {
	local iface="$1"
	local ip1="$2"
	local ip2="$3"
	local last_fail=""

	ping_test() {
		local iface="$1"
		local ip="$2"
		local avg avg_int delay_limit

		ping_out=$(/bin/ping -I "$iface" -c 4 "$ip" 2>/dev/null) || {
			last_fail="$ip unreachable"
			return 1
		}

		[ "$CHECK_DELAY" != "1" ] && {
			log_wdoc_warp "$iface: $ip reachable"
			return 0
		}

		avg=$(echo "$ping_out" | sed -n 's/.*min\/avg\/max[^=]*=[^\/]*\/\([^\/]*\)\/.*/\1/p')
		[ -z "$avg" ] && {
			last_fail="$ip avg rtt parse error"
			return 1
		}

		avg_int=${avg%%.*}
		delay_limit=${DELAY_AVG:-500}

		if [ "$avg_int" -le "$delay_limit" ]; then
			log_wdoc_warp "$iface: $ip avg RTT ${avg}ms"
			return 0
		else
			last_fail="$ip avg RTT too high (${avg}ms > ${delay_limit}ms)"
			return 1
		fi
	}

	if [ -n "$ip1" ] && ping_test "$iface" "$ip1"; then
		return 0
	elif [ -n "$ip2" ] && ping_test "$iface" "$ip2"; then
		return 0
	else
		log_wdoc_warp "$iface: ${last_fail:-$ip1 and $ip2 unreachable}"
		return 1
	fi
}

get_wg_section() {
	local iface="$1"
	local sec

	sec=$(uci show network | grep "=amneziawg" | grep "$iface" | awk -F= '{print $1}')
	[ -n "$sec" ] && echo "$sec" && return 0

	sec=$(uci show network | grep "=wireguard" | grep "$iface" | awk -F= '{print $1}')
	[ -n "$sec" ] && echo "$sec" && return 0

	return 1
}

random_endpoint() {
	local attempt="$1"

	local endpoints="162.159.192.10 162.159.192.2 162.159.192.9 188.114.97.115 188.114.96.241 188.114.96.15 188.114.96.243 188.114.96.131 188.114.96.61 engage.cloudflareclient.com"
	local ports="500 2408 1701 4500"

	local ep_count=0 ep_addr count idx
	for ep in $endpoints; do ep_count=$((ep_count+1)); done
	idx=$((attempt % ep_count))
	count=0
	for ep in $endpoints; do
		if [ "$count" -eq "$idx" ]; then
			ep_addr="$ep"
			break
		fi
		count=$((count+1))
	done

	local port_count=0 ep_port
	for p in $ports; do port_count=$((port_count+1)); done
	idx=$((RANDOM % port_count))
	count=0
	for p in $ports; do
		if [ "$count" -eq "$idx" ]; then
			ep_port="$p"
			break
		fi
		count=$((count+1))
	done

	echo "${ep_addr}:${ep_port}"
}

process_section() {
	local iface="$1"
	local ip1="$2"
	local ip2="$3"
	local attempts="$4"

	local wg_sec
	wg_sec=$(get_wg_section "$iface")
	[ -z "$wg_sec" ] && { log_wdoc_warp "No wireguard/amneziawg section found for $iface, skip"; return 1; }

	local attempt=0
	while [ "$attempt" -lt "$attempts" ]; do
		if ping_interface "$iface" "$ip1" "$ip2"; then
			return 0
		fi

		ep=$(random_endpoint "$attempt")
		ep_host=${ep%%:*}
		ep_port=${ep##*:}

		log_wdoc_warp "Attempt $((attempt+1))/$attempts: setting $iface endpoint $ep_host:$ep_port"
		uci -q set "$wg_sec.endpoint_host=$ep_host"
		uci -q set "$wg_sec.endpoint_port=$ep_port"
		uci commit network

		ifdown "$iface"
		sleep 2
		ifup "$iface"
		sleep 5

		attempt=$((attempt+1))
	done

	log_wdoc_warp "$iface: all attempts exhausted, interface still unreachable"
	return 1
}

if ! check_internet; then
	exit 0
fi

for section in $(uci show wdoc-warp | awk -F= '$2=="interface"{print $1}' | sed 's/^wdoc-warp\.//'); do
	iface=$(uci -q get wdoc-warp.$section.iface)
	[ -z "$iface" ] && continue

	ip1=$(uci -q get wdoc-warp.$section.check_ip1)
	ip2=$(uci -q get wdoc-warp.$section.check_ip2)
	attempts=$(uci -q get wdoc-warp.$section.attempts)
	[ -z "$attempts" ] && attempts=5

	process_section "$iface" "$ip1" "$ip2" "$attempts"
done

log_wdoc_warp "All interfaces processed."

exit 0
