#!/bin/sh
# RPCD backend for Network Tweaks

. /lib/functions.sh
. /usr/share/libubox/jshn.sh

CONFIG="network_tweaks"
PLUGINS_CATALOG="/usr/share/secubox/plugins/catalog"

# Helper Functions for Component Discovery

# Check if a manifest has network relevance
check_network_relevance() {
	local manifest="$1"

	# Check for network.inbound_ports[]
	local ports=$(jsonfilter -i "$manifest" -e '@.network.inbound_ports[*]' 2>/dev/null)
	[ -n "$ports" ] && return 0

	# Check for network.protocols[]
	local protocols=$(jsonfilter -i "$manifest" -e '@.network.protocols[*]' 2>/dev/null)
	[ -n "$protocols" ] && return 0

	# Check for network-related capabilities
	local caps=$(jsonfilter -i "$manifest" -e '@.capabilities[*]' 2>/dev/null)
	for cap in $caps; do
		case "$cap" in
			vhost-publish|dns-filtering|proxy|firewall|vpn|network-service)
				return 0
				;;
		esac
	done

	return 1
}

# Query package install state
query_install_state() {
	local manifest="$1"
	local packages=$(jsonfilter -i "$manifest" -e '@.packages[*]' 2>/dev/null)

	[ -z "$packages" ] && echo "n/a" && return

	local total=0 installed=0
	for pkg in $packages; do
		total=$((total + 1))
		if opkg status "$pkg" >/dev/null 2>&1 || apk info -e "$pkg" >/dev/null 2>&1; then
			installed=$((installed + 1))
		fi
	done

	if [ "$installed" -eq 0 ]; then
		echo "available"
	elif [ "$installed" -eq "$total" ]; then
		echo "installed"
	else
		echo "partial"
	fi
}

# Query service runtime state
query_service_state() {
	local id="$1"
	local manifest="$2"
	local runtime=$(jsonfilter -i "$manifest" -e '@.runtime' 2>/dev/null)

	case "$runtime" in
		docker)
			# Query Docker container state
			if command -v docker >/dev/null 2>&1; then
				local container=$(docker ps --filter "name=$id" --format '{{.Status}}' 2>/dev/null)
				[ -n "$container" ] && echo "running" || echo "stopped"
			else
				echo "n/a"
			fi
			;;
		native)
			# Check init.d service
			if [ -x "/etc/init.d/$id" ]; then
				/etc/init.d/$id running >/dev/null 2>&1 && echo "running" || echo "stopped"
			else
				echo "n/a"
			fi
			;;
		*)
			echo "n/a"
			;;
	esac
}

# Discover VHost associations for an app
discover_vhost_associations() {
	local app_id="$1"
	local result=""

	# Load vhosts config
	config_load vhosts

	local vhost_list=""
	collect_app_vhost() {
		local section="$1"
		local domain backend enabled tls_mode
		config_get domain "$section" domain
		config_get backend "$section" backend
		config_get_bool enabled "$section" enabled 1
		config_get tls_mode "$section" tls_mode "off"

		# Simple heuristic: if domain contains app_id or backend references common ports
		# This is a simplified version - in production, use template associations
		if echo "$domain" | grep -qi "$app_id" || echo "$section" | grep -qi "$app_id"; then
			vhost_list="$vhost_list $section"
		fi
	}
	config_foreach collect_app_vhost vhost

	echo "$vhost_list"
}

# Calculate network impact for a component
calculate_network_impact() {
	local id="$1"
	local manifest="$2"

	# Count DNS entries from sync files
	local dns_count=0
	if [ -f /tmp/dnsmasq.d/50-vhosts.conf ]; then
		dns_count=$(grep -c "$id" /tmp/dnsmasq.d/50-vhosts.conf 2>/dev/null || echo 0)
	fi

	# Count hosts entries
	local hosts_count=0
	if [ -f /tmp/hosts.vhosts ]; then
		hosts_count=$(grep -c "$id" /tmp/hosts.vhosts 2>/dev/null || echo 0)
	fi

	# Get ports from manifest
	local ports=$(jsonfilter -i "$manifest" -e '@.network.inbound_ports[*]' 2>/dev/null | wc -w)

	# Get VHost count
	local vhosts=$(discover_vhost_associations "$id" | wc -w)

	echo "$dns_count $hosts_count $ports $vhosts"
}

# Discover all network-relevant components
discover_network_components() {
	[ ! -d "$PLUGINS_CATALOG" ] && return

	for manifest_file in "$PLUGINS_CATALOG"/*.json; do
		[ ! -f "$manifest_file" ] && continue

		# Check network relevance
		check_network_relevance "$manifest_file" || continue

		# Extract component metadata
		local id=$(jsonfilter -i "$manifest_file" -e '@.id' 2>/dev/null)
		local name=$(jsonfilter -i "$manifest_file" -e '@.name' 2>/dev/null)
		local category=$(jsonfilter -i "$manifest_file" -e '@.category' 2>/dev/null)
		local capabilities=$(jsonfilter -i "$manifest_file" -e '@.capabilities[*]' 2>/dev/null)

		[ -z "$id" ] && continue

		# Query states
		local install_state=$(query_install_state "$manifest_file")
		local service_state=$(query_service_state "$id" "$manifest_file")

		# Calculate impact
		local impact=$(calculate_network_impact "$id" "$manifest_file")
		set -- $impact
		local dns_entries=$1 hosts_entries=$2 ports=$3 vhost_count=$4

		# Output component JSON object
		json_add_object
			json_add_string "id" "$id"
			json_add_string "name" "${name:-$id}"
			json_add_string "category" "${category:-unknown}"
			json_add_string "install_state" "$install_state"
			json_add_string "service_state" "$service_state"

			json_add_object "network_impact"
				json_add_int "dns_entries" "${dns_entries:-0}"
				json_add_int "vhosts" "${vhost_count:-0}"
				json_add_int "ports" "${ports:-0}"
			json_close_object

			json_add_object "cumulative_contribution"
				json_add_int "dnsmasq_entries" "${dns_entries:-0}"
				json_add_int "hosts_entries" "${hosts_entries:-0}"
				json_add_int "ports_opened" "${ports:-0}"
			json_close_object

			json_add_array "capabilities"
			for cap in $capabilities; do
				json_add_string "" "$cap"
			done
			json_close_array
		json_close_object
	done
}

# Calculate cumulative impact summary
calculate_cumulative_impact() {
	local total_components=0
	local active_components=0
	local total_dns=0
	local total_vhosts=0
	local total_ports=0

	# 1. Count from plugins catalog if exists
	if [ -d "$PLUGINS_CATALOG" ]; then
		for manifest_file in "$PLUGINS_CATALOG"/*.json; do
			[ ! -f "$manifest_file" ] && continue
			check_network_relevance "$manifest_file" || continue

			local id=$(jsonfilter -i "$manifest_file" -e '@.id' 2>/dev/null)
			[ -z "$id" ] && continue

			total_components=$((total_components + 1))

			local service_state=$(query_service_state "$id" "$manifest_file")
			if [ "$service_state" = "running" ]; then
				active_components=$((active_components + 1))

				local impact=$(calculate_network_impact "$id" "$manifest_file")
				set -- $impact
				total_dns=$((total_dns + ${1:-0}))
				total_vhosts=$((total_vhosts + ${4:-0}))
				total_ports=$((total_ports + ${3:-0}))
			fi
		done
	fi

	# 2. Count HAProxy vhosts directly
	local haproxy_vhosts=0
	if uci -q show haproxy 2>/dev/null | grep -q "=vhost$"; then
		haproxy_vhosts=$(uci show haproxy 2>/dev/null | grep -c "=vhost$" || echo 0)
		total_vhosts=$((total_vhosts + haproxy_vhosts))
	fi

	# 3. Count DNS entries from dnsmasq config
	if [ -f /tmp/dnsmasq.d/50-vhosts.conf ]; then
		local dnsmasq_dns=$(grep -c '^address=' /tmp/dnsmasq.d/50-vhosts.conf 2>/dev/null || echo 0)
		total_dns=$((total_dns + dnsmasq_dns))
	fi

	# 4. Count active LXC containers as components
	local lxc_running=0
	if command -v lxc-ls >/dev/null 2>&1; then
		lxc_running=$(lxc-ls --running 2>/dev/null | wc -w)
		active_components=$((active_components + lxc_running))
		total_components=$((total_components + lxc_running))
	fi

	# 5. Count exposed ports (firewall rules allowing WAN access)
	local i=0
	while uci -q get firewall.@rule[$i] >/dev/null 2>&1; do
		local src=$(uci -q get firewall.@rule[$i].src)
		local target=$(uci -q get firewall.@rule[$i].target)
		local enabled=$(uci -q get firewall.@rule[$i].enabled)
		local dest_port=$(uci -q get firewall.@rule[$i].dest_port)
		if [ "$src" = "wan" ] && [ "$target" = "ACCEPT" ] && [ "$enabled" != "0" ] && [ -n "$dest_port" ]; then
			total_ports=$((total_ports + 1))
		fi
		i=$((i + 1))
	done

	# 6. Count Docker containers as components
	if command -v docker >/dev/null 2>&1; then
		local docker_running=$(docker ps -q 2>/dev/null | wc -l)
		active_components=$((active_components + docker_running))
		total_components=$((total_components + docker_running))
	fi

	json_add_int "total_components" "$total_components"
	json_add_int "active_components" "$active_components"
	json_add_int "total_dns_entries" "$total_dns"
	json_add_int "total_vhosts" "$total_vhosts"
	json_add_int "total_ports_exposed" "$total_ports"
}

# Get network mode status (if network-modes installed)
get_network_mode_status() {
	local current_mode="unknown"
	local mode_name="Unknown"
	local tweaks_enabled=1

	# Try to read network-modes config
	if [ -f /etc/config/network-modes ]; then
		config_load network-modes
		config_get current_mode config current_mode "router"

		# Get mode name
		config_get mode_name "$current_mode" name "$current_mode"

		# Get network-tweaks settings for this mode
		config_get tweaks_enabled "$current_mode" network_tweaks_enabled "1"
	fi

	json_add_string "current_mode" "$current_mode"
	json_add_string "mode_name" "$mode_name"
	json_add_boolean "sync_enabled" "${tweaks_enabled:-1}"
}

case "$1" in
	list)
		json_init
		json_add_object "getStatus"
		json_close_object
		json_add_object "syncNow"
		json_close_object
		json_add_object "getConfig"
		json_close_object
		json_add_object "setConfig"
			json_add_string "enabled" "boolean"
			json_add_string "auto_sync" "boolean"
			json_add_string "sync_hosts" "boolean"
			json_add_string "sync_dnsmasq" "boolean"
			json_add_string "lan_interface" "string"
			json_add_string "default_ip" "string"
		json_close_object
		json_add_object "getNetworkComponents"
		json_close_object
		json_add_object "getCumulativeImpact"
		json_close_object
		json_add_object "setComponentEnabled"
			json_add_string "app_id" "string"
			json_add_string "enabled" "boolean"
		json_close_object
		json_add_object "getWpadStatus"
		json_close_object
		json_add_object "setWpadEnabled"
			json_add_string "enabled" "boolean"
		json_close_object
		json_add_object "getProxyStatus"
		json_close_object
		json_add_object "setAdGuardEnabled"
			json_add_string "enabled" "boolean"
		json_close_object
		json_add_object "getOpkgSettings"
		json_close_object
		json_add_object "setOpkgIpv4"
			json_add_string "enabled" "boolean"
		json_close_object
		json_add_object "testUrl"
			json_add_string "url" "string"
			json_add_string "timeout" "integer"
		json_close_object
		json_dump
		;;

	call)
		case "$2" in
			getStatus)
				# Get current status and statistics
				json_init
				json_add_boolean "success" 1

				# Read config
				config_load "$CONFIG"
				config_get enabled global enabled "1"
				config_get auto_sync global auto_sync "1"
				config_get sync_hosts global sync_hosts "1"
				config_get sync_dnsmasq global sync_dnsmasq "1"
				config_get lan_interface global lan_interface "lan"
				config_get default_ip global default_ip ""

				json_add_object "config"
					json_add_boolean "enabled" "${enabled:-1}"
					json_add_boolean "auto_sync" "${auto_sync:-1}"
					json_add_boolean "sync_hosts" "${sync_hosts:-1}"
					json_add_boolean "sync_dnsmasq" "${sync_dnsmasq:-1}"
					json_add_string "lan_interface" "${lan_interface:-lan}"
					json_add_string "default_ip" "$default_ip"
				json_close_object

				# Count enabled vhosts
				vhost_count=0
				config_load vhosts
				count_vhost() {
					local enabled
					config_get_bool enabled "$1" enabled 1
					[ "$enabled" = "1" ] && vhost_count=$((vhost_count + 1))
				}
				config_foreach count_vhost vhost

				# Check if files exist
				dnsmasq_exists=0
				hosts_exists=0
				[ -f /tmp/dnsmasq.d/50-vhosts.conf ] && dnsmasq_exists=1
				[ -f /tmp/hosts.vhosts ] && hosts_exists=1

				dnsmasq_entries=0
				hosts_entries=0
				# Count entries
				if [ -f /tmp/dnsmasq.d/50-vhosts.conf ]; then
					dnsmasq_entries=$(grep -c '^address=' /tmp/dnsmasq.d/50-vhosts.conf 2>/dev/null || echo 0)
				fi
				if [ -f /tmp/hosts.vhosts ]; then
					hosts_entries=$(grep -cv '^#' /tmp/hosts.vhosts 2>/dev/null || echo 0)
				fi

				json_add_object "stats"
					json_add_int "vhosts_enabled" "$vhost_count"
					json_add_int "dnsmasq_entries" "$dnsmasq_entries"
					json_add_int "hosts_entries" "$hosts_entries"
					json_add_boolean "dnsmasq_file_exists" "$dnsmasq_exists"
					json_add_boolean "hosts_file_exists" "$hosts_exists"
				json_close_object

				json_dump
				;;

			syncNow)
				# Trigger immediate synchronization
				/usr/sbin/network-tweaks-sync sync >/dev/null 2>&1 &

				json_init
				json_add_boolean "success" 1
				json_add_string "message" "Synchronization triggered"
				json_dump
				;;

			getConfig)
				# Get configuration
				json_init
				json_add_boolean "success" 1

				config_load "$CONFIG"
				config_get enabled global enabled "1"
				config_get auto_sync global auto_sync "1"
				config_get sync_hosts global sync_hosts "1"
				config_get sync_dnsmasq global sync_dnsmasq "1"
				config_get lan_interface global lan_interface "lan"
				config_get default_ip global default_ip ""

				json_add_object "config"
					json_add_boolean "enabled" "${enabled:-1}"
					json_add_boolean "auto_sync" "${auto_sync:-1}"
					json_add_boolean "sync_hosts" "${sync_hosts:-1}"
					json_add_boolean "sync_dnsmasq" "${sync_dnsmasq:-1}"
					json_add_string "lan_interface" "${lan_interface:-lan}"
					json_add_string "default_ip" "$default_ip"
				json_close_object

				json_dump
				;;

			setConfig)
				# Update configuration
				read input
				json_load "$input"

				json_get_var enabled enabled
				json_get_var auto_sync auto_sync
				json_get_var sync_hosts sync_hosts
				json_get_var sync_dnsmasq sync_dnsmasq
				json_get_var lan_interface lan_interface
				json_get_var default_ip default_ip

				[ -n "$enabled" ] && uci set ${CONFIG}.global.enabled="$enabled"
				[ -n "$auto_sync" ] && uci set ${CONFIG}.global.auto_sync="$auto_sync"
				[ -n "$sync_hosts" ] && uci set ${CONFIG}.global.sync_hosts="$sync_hosts"
				[ -n "$sync_dnsmasq" ] && uci set ${CONFIG}.global.sync_dnsmasq="$sync_dnsmasq"
				[ -n "$lan_interface" ] && uci set ${CONFIG}.global.lan_interface="$lan_interface"
				[ -n "$default_ip" ] && uci set ${CONFIG}.global.default_ip="$default_ip"

				uci commit "$CONFIG"

				# Trigger sync
				/etc/init.d/network-tweaks reload >/dev/null 2>&1 &

				json_init
				json_add_boolean "success" 1
				json_add_string "message" "Configuration updated"
				json_dump
				;;

			getNetworkComponents)
				# Get all network-relevant components with aggregated data
				json_init
				json_add_boolean "success" 1

				# Discover all components
				json_add_array "components"
				discover_network_components
				json_close_array

				# Add cumulative summary
				json_add_object "cumulative_summary"
				calculate_cumulative_impact
				json_close_object

				# Add network mode info
				json_add_object "network_mode"
				get_network_mode_status
				json_close_object

				json_dump
				;;

			getCumulativeImpact)
				# Get cumulative network impact summary
				json_init
				json_add_boolean "success" 1

				calculate_cumulative_impact

				json_dump
				;;

			setComponentEnabled)
				# Enable/disable component network features
				read input
				json_load "$input"

				json_get_var app_id app_id
				json_get_var enabled enabled

				# TODO: Implement component-specific enable/disable logic
				# For now, just trigger a sync
				/usr/sbin/network-tweaks-sync sync >/dev/null 2>&1 &

				json_init
				json_add_boolean "success" 1
				json_add_string "message" "Component network features updated"
				json_dump
				;;

			getWpadStatus)
				# Get WPAD/PAC file status
				json_init
				json_add_boolean "success" 1

				# Check if WPAD file exists
				wpad_enabled=0
				wpad_file=""
				if [ -f /www/wpad.dat ]; then
					wpad_enabled=1
					wpad_file="/www/wpad.dat"
				fi

				# Check DHCP option 252 configuration
				dhcp_wpad_enabled=0
				config_load dhcp
				check_dhcp_option() {
					local value
					config_get value "$1" "252"
					[ -n "$value" ] && dhcp_wpad_enabled=1
				}
				config_foreach check_dhcp_option dhcp

				# Check dnsmasq wpad entry
				dns_wpad_enabled=0
				if grep -q "wpad" /etc/hosts 2>/dev/null || \
				   grep -q "wpad" /tmp/hosts.vhosts 2>/dev/null; then
					dns_wpad_enabled=1
				fi

				json_add_object "wpad"
					json_add_boolean "enabled" "$wpad_enabled"
					json_add_string "file" "$wpad_file"
					json_add_boolean "dhcp_configured" "$dhcp_wpad_enabled"
					json_add_boolean "dns_configured" "$dns_wpad_enabled"
				json_close_object

				json_dump
				;;

			setWpadEnabled)
				# Enable/disable WPAD
				read input
				json_load "$input"

				json_get_var enabled enabled

				if [ "$enabled" = "1" ] || [ "$enabled" = "true" ]; then
					# Get LAN IP
					lan_ip=$(uci get network.lan.ipaddr 2>/dev/null | cut -d'/' -f1)
					[ -z "$lan_ip" ] && lan_ip="192.168.255.1"

					# Create WPAD/PAC file
					cat > /www/wpad.dat << EOF
function FindProxyForURL(url, host) {
    // Direct access for local network
    if (isInNet(host, "192.168.0.0", "255.255.0.0") ||
        isInNet(host, "10.0.0.0", "255.0.0.0") ||
        isInNet(host, "172.16.0.0", "255.240.0.0") ||
        shExpMatch(host, "*.local") ||
        shExpMatch(host, "*.lan")) {
        return "DIRECT";
    }
    // Use CDN Cache proxy for everything else
    return "PROXY ${lan_ip}:3128; DIRECT";
}
EOF
					chmod 644 /www/wpad.dat

					# Add DHCP option 252 for WPAD discovery
					uci set dhcp.lan.dhcp_option_force="252,http://${lan_ip}/wpad.dat"
					uci commit dhcp

					# Add wpad DNS entry
					if ! grep -q "wpad" /etc/hosts 2>/dev/null; then
						echo "${lan_ip} wpad wpad.lan" >> /etc/hosts
					fi

					# Restart dnsmasq
					/etc/init.d/dnsmasq reload >/dev/null 2>&1

					json_init
					json_add_boolean "success" 1
					json_add_string "message" "WPAD enabled"
				else
					# Remove WPAD file
					rm -f /www/wpad.dat

					# Remove DHCP option
					uci delete dhcp.lan.dhcp_option_force 2>/dev/null
					uci commit dhcp

					# Remove wpad DNS entry
					sed -i '/wpad/d' /etc/hosts 2>/dev/null

					# Restart dnsmasq
					/etc/init.d/dnsmasq reload >/dev/null 2>&1

					json_init
					json_add_boolean "success" 1
					json_add_string "message" "WPAD disabled"
				fi

				json_dump
				;;

			getProxyStatus)
				# Get comprehensive proxy status (CDN Cache + WPAD + AdGuard Home)
				json_init
				json_add_boolean "success" 1

				# AdGuard Home status (Docker container)
				adguard_installed=0
				adguard_enabled=0
				adguard_running=0
				adguard_port=3000
				adguard_dns_port=53

				if [ -x /usr/sbin/adguardhomectl ]; then
					adguard_installed=1
					adguard_enabled=$(uci -q get adguardhome.main.enabled || echo 0)
					adguard_port=$(uci -q get adguardhome.main.port || echo 3000)
					adguard_dns_port=$(uci -q get adguardhome.main.dns_port || echo 53)

					# Check if container is running
					if command -v docker >/dev/null 2>&1; then
						docker ps --filter "name=secbx-adguardhome" --format "{{.Status}}" 2>/dev/null | grep -q "Up" && adguard_running=1
					fi
				fi

				json_add_object "adguard_home"
					json_add_boolean "installed" "$adguard_installed"
					json_add_boolean "enabled" "$adguard_enabled"
					json_add_boolean "running" "$adguard_running"
					json_add_int "port" "$adguard_port"
					json_add_int "dns_port" "$adguard_dns_port"
				json_close_object

				# CDN Cache status
				cdn_running=0
				cdn_enabled=0
				cdn_port=3128

				if [ -x /etc/init.d/cdn-cache ]; then
					/etc/init.d/cdn-cache running >/dev/null 2>&1 && cdn_running=1
					cdn_enabled=$(uci get cdn-cache.main.enabled 2>/dev/null)
					[ -z "$cdn_enabled" ] && cdn_enabled=0
					cdn_port=$(uci get cdn-cache.main.listen_port 2>/dev/null)
					[ -z "$cdn_port" ] && cdn_port=3128
				fi

				# Check if port is actually listening
				cdn_listening=0
				if netstat -tln 2>/dev/null | grep -q ":${cdn_port}"; then
					cdn_listening=1
				fi

				json_add_object "cdn_cache"
					json_add_boolean "installed" "$([ -x /etc/init.d/cdn-cache ] && echo 1 || echo 0)"
					json_add_boolean "enabled" "$cdn_enabled"
					json_add_boolean "running" "$cdn_running"
					json_add_boolean "listening" "$cdn_listening"
					json_add_int "port" "$cdn_port"
				json_close_object

				# WPAD status
				wpad_enabled=0
				[ -f /www/wpad.dat ] && wpad_enabled=1

				dhcp_wpad=0
				wpad_url=""
				config_load dhcp
				wpad_opt=$(uci get dhcp.lan.dhcp_option_force 2>/dev/null)
				if echo "$wpad_opt" | grep -q "252"; then
					dhcp_wpad=1
					wpad_url=$(echo "$wpad_opt" | sed 's/252,//')
				fi

				json_add_object "wpad"
					json_add_boolean "enabled" "$wpad_enabled"
					json_add_boolean "dhcp_configured" "$dhcp_wpad"
					json_add_string "url" "$wpad_url"
				json_close_object

				json_dump
				;;

			setAdGuardEnabled)
				# Enable/disable AdGuard Home
				read input
				json_load "$input"

				json_get_var enabled enabled

				if [ ! -x /usr/sbin/adguardhomectl ]; then
					json_init
					json_add_boolean "success" 0
					json_add_string "error" "AdGuard Home not installed"
					json_dump
					exit 0
				fi

				if [ "$enabled" = "1" ] || [ "$enabled" = "true" ]; then
					uci set adguardhome.main.enabled='1'
					uci commit adguardhome
					/etc/init.d/adguardhome enable >/dev/null 2>&1
					/etc/init.d/adguardhome start >/dev/null 2>&1 &

					json_init
					json_add_boolean "success" 1
					json_add_string "message" "AdGuard Home enabled and starting"
				else
					/etc/init.d/adguardhome stop >/dev/null 2>&1
					/etc/init.d/adguardhome disable >/dev/null 2>&1
					uci set adguardhome.main.enabled='0'
					uci commit adguardhome

					json_init
					json_add_boolean "success" 1
					json_add_string "message" "AdGuard Home disabled"
				fi

				json_dump
				;;

			getOpkgSettings)
				# Get opkg network settings
				json_init
				json_add_boolean "success" 1

				# Check if IPv4 is forced (via profile alias)
				ipv4_forced=0
				if [ -f /etc/profile.d/opkg_ipv4.sh ]; then
					grep -q "opkg.*-4\|force.*ipv4\|ipv4.*only" /etc/profile.d/opkg_ipv4.sh 2>/dev/null && ipv4_forced=1
				fi

				json_add_object "opkg"
					json_add_boolean "ipv4_only" "$ipv4_forced"
				json_close_object

				json_dump
				;;

			setOpkgIpv4)
				# Enable/disable IPv4-only mode for opkg
				read input
				json_load "$input"

				json_get_var enabled enabled

				if [ "$enabled" = "1" ] || [ "$enabled" = "true" ]; then
					# Create profile script to force IPv4 for opkg
					cat > /etc/profile.d/opkg_ipv4.sh << 'OPKG_EOF'
# Force opkg to use IPv4 only (uclient-fetch -4)
# Useful when IPv6 connectivity is broken
alias opkg='/bin/opkg'
export UCLIENT_FETCH_OPTS="-4"
OPKG_EOF
					chmod +x /etc/profile.d/opkg_ipv4.sh

					json_init
					json_add_boolean "success" 1
					json_add_string "message" "opkg IPv4-only mode enabled"
				else
					# Remove IPv4 forcing
					rm -f /etc/profile.d/opkg_ipv4.sh

					json_init
					json_add_boolean "success" 1
					json_add_string "message" "opkg IPv4-only mode disabled"
				fi

				json_dump
				;;

			testUrl)
				# Test URL connectivity (for network diagnostics)
				read input
				json_load "$input"

				json_get_var url url
				json_get_var timeout timeout
				[ -z "$timeout" ] && timeout=5

				json_init

				if [ -z "$url" ]; then
					json_add_boolean "success" 0
					json_add_string "error" "URL is required"
					json_dump
					exit 0
				fi

				# Test URL with wget --spider (more reliable than uclient-fetch)
				status_msg=""
				start_time=$(date +%s)

				# Use wget with timeout and spider mode
				if wget -4 --spider -q -T "$timeout" --no-check-certificate "$url" 2>/dev/null; then
					status_msg="reachable"
				else
					status_msg="unreachable"
				fi

				end_time=$(date +%s)
				response_time=$((end_time - start_time))

				json_add_boolean "success" 1
				json_add_object "result"
					json_add_string "url" "$url"
					json_add_string "status" "$status_msg"
					json_add_int "response_time_s" "$response_time"
				json_close_object

				json_dump
				;;

			*)
				json_init
				json_add_boolean "success" 0
				json_add_string "error" "Unknown method"
				json_dump
				;;
		esac
		;;
esac
