#!/bin/sh
# SecuBox P2P RPCD Handler

. /usr/share/libubox/jshn.sh

P2P_CMD="/usr/sbin/secubox-p2p"

case "$1" in
	list)
		cat <<EOF
{
	"get_peers": {},
	"get_settings": {},
	"get_services": {},
	"get_shared_services": {},
	"discover": { "timeout": 5 },
	"add_peer": { "address": "string", "name": "string" },
	"remove_peer": { "peer_id": "string" },
	"set_settings": { "settings": "object" },
	"sync_catalog": {},
	"broadcast_command": { "command": "string" },
	"get_dns_config": {},
	"set_dns_config": { "config": "object" },
	"get_wireguard_config": {},
	"set_wireguard_config": { "config": "object" },
	"get_haproxy_config": {},
	"set_haproxy_config": { "config": "object" },
	"get_registry": {},
	"register_url": { "short_url": "string", "target_url": "string" },
	"health_check": {},
	"get_gitea_config": {},
	"set_gitea_config": { "config": "object" },
	"create_gitea_repo": { "name": "string", "description": "string", "private": true, "init_readme": true },
	"list_gitea_repos": {},
	"get_gitea_commits": { "limit": 20 },
	"push_gitea_backup": { "message": "string", "components": "object" },
	"pull_gitea_backup": { "commit_sha": "string" },
	"create_local_backup": { "name": "string", "components": "object" },
	"list_local_backups": {},
	"restore_local_backup": { "backup_id": "string" },
	"get_feed_peers": {},
	"get_peer_packages": { "peer_addr": "string" },
	"get_all_packages": {},
	"fetch_package": { "package": "string", "peer_addr": "string" },
	"sync_package_catalog": { "refresh": false },
	"get_feed_settings": {},
	"set_feed_settings": { "share_feed": true, "auto_sync": true, "sync_interval": 3600, "prefer_local": true }
}
EOF
		;;

	call)
		case "$2" in
			get_peers)
				$P2P_CMD peers
				;;

			get_settings)
				$P2P_CMD settings
				;;

			get_services)
				$P2P_CMD services
				;;

			get_shared_services)
				$P2P_CMD shared-services
				;;

			discover)
				read input
				timeout=$(echo "$input" | jsonfilter -e '@.timeout' 2>/dev/null || echo "5")
				$P2P_CMD discover "$timeout"
				;;

			add_peer)
				read input
				address=$(echo "$input" | jsonfilter -e '@.address')
				name=$(echo "$input" | jsonfilter -e '@.name')
				if [ -n "$address" ]; then
					$P2P_CMD add-peer "$address" "$name"
				else
					echo '{"success":false,"error":"Address required"}'
				fi
				;;

			remove_peer)
				read input
				peer_id=$(echo "$input" | jsonfilter -e '@.peer_id')
				if [ -n "$peer_id" ]; then
					$P2P_CMD remove-peer "$peer_id"
				else
					echo '{"success":false,"error":"Peer ID required"}'
				fi
				;;

			set_settings)
				read input
				settings=$(echo "$input" | jsonfilter -e '@.settings')
				$P2P_CMD set-settings "$settings"
				;;

			sync_catalog)
				$P2P_CMD sync
				;;

			broadcast_command)
				read input
				command=$(echo "$input" | jsonfilter -e '@.command')
				$P2P_CMD broadcast "$command"
				;;

			get_dns_config)
				cat <<EOF
{
	"enabled": $(uci -q get secubox-p2p.dns.enabled || echo 0),
	"primary_dns": "$(uci -q get secubox-p2p.dns.primary_dns || echo "127.0.0.1:53")",
	"sync_enabled": $(uci -q get secubox-p2p.dns.sync_enabled || echo 1),
	"base_domain": "$(uci -q get secubox-p2p.dns.base_domain || echo "sb.local")"
}
EOF
				;;

			set_dns_config)
				read input
				enabled=$(echo "$input" | jsonfilter -e '@.config.enabled')
				primary_dns=$(echo "$input" | jsonfilter -e '@.config.primary_dns')
				base_domain=$(echo "$input" | jsonfilter -e '@.config.base_domain')

				[ -n "$enabled" ] && uci set secubox-p2p.dns.enabled="$enabled"
				[ -n "$primary_dns" ] && uci set secubox-p2p.dns.primary_dns="$primary_dns"
				[ -n "$base_domain" ] && uci set secubox-p2p.dns.base_domain="$base_domain"
				uci commit secubox-p2p

				echo '{"success":true}'
				;;

			get_wireguard_config)
				cat <<EOF
{
	"enabled": $(uci -q get secubox-p2p.wireguard.enabled || echo 0),
	"listen_port": $(uci -q get secubox-p2p.wireguard.listen_port || echo 51820),
	"network_cidr": "$(uci -q get secubox-p2p.wireguard.network_cidr || echo "10.100.0.0/24")",
	"auto_configure": $(uci -q get secubox-p2p.wireguard.auto_configure || echo 1)
}
EOF
				;;

			set_wireguard_config)
				read input
				enabled=$(echo "$input" | jsonfilter -e '@.config.enabled')
				listen_port=$(echo "$input" | jsonfilter -e '@.config.listen_port')
				network_cidr=$(echo "$input" | jsonfilter -e '@.config.network_cidr')

				[ -n "$enabled" ] && uci set secubox-p2p.wireguard.enabled="$enabled"
				[ -n "$listen_port" ] && uci set secubox-p2p.wireguard.listen_port="$listen_port"
				[ -n "$network_cidr" ] && uci set secubox-p2p.wireguard.network_cidr="$network_cidr"
				uci commit secubox-p2p

				echo '{"success":true}'
				;;

			get_haproxy_config)
				cat <<EOF
{
	"enabled": $(uci -q get secubox-p2p.haproxy.enabled || echo 0),
	"strategy": "$(uci -q get secubox-p2p.haproxy.strategy || echo "round-robin")",
	"health_check": $(uci -q get secubox-p2p.haproxy.health_check || echo 1),
	"failover": $(uci -q get secubox-p2p.haproxy.failover || echo 1)
}
EOF
				;;

			set_haproxy_config)
				read input
				enabled=$(echo "$input" | jsonfilter -e '@.config.enabled')
				strategy=$(echo "$input" | jsonfilter -e '@.config.strategy')

				[ -n "$enabled" ] && uci set secubox-p2p.haproxy.enabled="$enabled"
				[ -n "$strategy" ] && uci set secubox-p2p.haproxy.strategy="$strategy"
				uci commit secubox-p2p

				echo '{"success":true}'
				;;

			get_registry)
				cat <<EOF
{
	"base_url": "$(uci -q get secubox-p2p.registry.base_url || echo "sb.local")",
	"cache_enabled": $(uci -q get secubox-p2p.registry.cache_enabled || echo 1),
	"cache_ttl": $(uci -q get secubox-p2p.registry.cache_ttl || echo 300),
	"services": []
}
EOF
				;;

			register_url)
				read input
				short_url=$(echo "$input" | jsonfilter -e '@.short_url')
				target_url=$(echo "$input" | jsonfilter -e '@.target_url')

				if [ -n "$short_url" ] && [ -n "$target_url" ]; then
					# Store in UCI or file
					echo "{\"success\":true,\"registered_url\":\"$(uci -q get secubox-p2p.registry.base_url)/${short_url}\"}"
				else
					echo '{"success":false,"error":"short_url and target_url required"}'
				fi
				;;

			health_check)
				local peers_online=0
				local peers_total=0
				local services_running=0

				# Count online peers
				if [ -f /tmp/secubox-p2p-peers.json ]; then
					peers_total=$(jsonfilter -i /tmp/secubox-p2p-peers.json -e '@.peers[*]' 2>/dev/null | wc -l)
					peers_online=$(jsonfilter -i /tmp/secubox-p2p-peers.json -e '@.peers[*].status' 2>/dev/null | grep -c "online" || echo 0)
				fi

				# Count running services
				for svc in dnsmasq uhttpd crowdsec haproxy; do
					pgrep "$svc" >/dev/null 2>&1 && services_running=$((services_running + 1))
				done

				cat <<EOF
{
	"status": "healthy",
	"peers_online": $peers_online,
	"peers_total": $peers_total,
	"services_running": $services_running,
	"dns_federation": $(uci -q get secubox-p2p.dns.enabled || echo 0),
	"wireguard_mesh": $(uci -q get secubox-p2p.wireguard.enabled || echo 0),
	"haproxy": $(uci -q get secubox-p2p.haproxy.enabled || echo 0)
}
EOF
				;;

			get_gitea_config)
				cat <<EOF
{
	"enabled": $(uci -q get secubox-p2p.gitea.enabled || echo 0),
	"server_url": "$(uci -q get secubox-p2p.gitea.server_url || echo "")",
	"repo_name": "$(uci -q get secubox-p2p.gitea.repo_name || echo "secubox-backup")",
	"repo_owner": "$(uci -q get secubox-p2p.gitea.repo_owner || echo "")",
	"auto_backup": $(uci -q get secubox-p2p.gitea.auto_backup || echo 0),
	"backup_interval": $(uci -q get secubox-p2p.gitea.backup_interval || echo 3600),
	"backup_on_change": $(uci -q get secubox-p2p.gitea.backup_on_change || echo 1),
	"include_configs": $(uci -q get secubox-p2p.gitea.include_configs || echo 1),
	"include_packages": $(uci -q get secubox-p2p.gitea.include_packages || echo 1),
	"include_scripts": $(uci -q get secubox-p2p.gitea.include_scripts || echo 1),
	"has_token": $([ -n "$(uci -q get secubox-p2p.gitea.access_token)" ] && echo "true" || echo "false")
}
EOF
				;;

			set_gitea_config)
				read input
				server_url=$(echo "$input" | jsonfilter -e '@.config.server_url' 2>/dev/null)
				repo_name=$(echo "$input" | jsonfilter -e '@.config.repo_name' 2>/dev/null)
				repo_owner=$(echo "$input" | jsonfilter -e '@.config.repo_owner' 2>/dev/null)
				access_token=$(echo "$input" | jsonfilter -e '@.config.access_token' 2>/dev/null)
				enabled=$(echo "$input" | jsonfilter -e '@.config.enabled' 2>/dev/null)
				auto_backup=$(echo "$input" | jsonfilter -e '@.config.auto_backup' 2>/dev/null)
				backup_interval=$(echo "$input" | jsonfilter -e '@.config.backup_interval' 2>/dev/null)

				[ -n "$server_url" ] && uci set secubox-p2p.gitea.server_url="$server_url"
				[ -n "$repo_name" ] && uci set secubox-p2p.gitea.repo_name="$repo_name"
				[ -n "$repo_owner" ] && uci set secubox-p2p.gitea.repo_owner="$repo_owner"
				[ -n "$access_token" ] && uci set secubox-p2p.gitea.access_token="$access_token"
				[ -n "$enabled" ] && uci set secubox-p2p.gitea.enabled="$enabled"
				[ -n "$auto_backup" ] && uci set secubox-p2p.gitea.auto_backup="$auto_backup"
				[ -n "$backup_interval" ] && uci set secubox-p2p.gitea.backup_interval="$backup_interval"
				uci commit secubox-p2p

				echo '{"success":true}'
				;;

			create_gitea_repo)
				read input
				repo_name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null)
				description=$(echo "$input" | jsonfilter -e '@.description' 2>/dev/null)
				is_private=$(echo "$input" | jsonfilter -e '@.private' 2>/dev/null)
				init_readme=$(echo "$input" | jsonfilter -e '@.init_readme' 2>/dev/null)

				server_url=$(uci -q get secubox-p2p.gitea.server_url)
				access_token=$(uci -q get secubox-p2p.gitea.access_token)

				if [ -z "$server_url" ] || [ -z "$access_token" ]; then
					echo '{"success":false,"error":"Gitea server URL and access token required"}'
					exit 0
				fi

				if [ -z "$repo_name" ]; then
					echo '{"success":false,"error":"Repository name required"}'
					exit 0
				fi

				# Create repo via Gitea API
				api_url="${server_url}/api/v1/user/repos"
				[ "$is_private" = "true" ] && private_val="true" || private_val="false"
				[ "$init_readme" = "true" ] && readme_val="true" || readme_val="false"

				response=$(curl -s -X POST "$api_url" \
					-H "Authorization: token $access_token" \
					-H "Content-Type: application/json" \
					-d "{\"name\":\"$repo_name\",\"description\":\"$description\",\"private\":$private_val,\"auto_init\":$readme_val}" \
					2>/dev/null)

				if echo "$response" | jsonfilter -e '@.id' >/dev/null 2>&1; then
					clone_url=$(echo "$response" | jsonfilter -e '@.clone_url' 2>/dev/null)
					html_url=$(echo "$response" | jsonfilter -e '@.html_url' 2>/dev/null)
					owner=$(echo "$response" | jsonfilter -e '@.owner.login' 2>/dev/null)

					# Save repo config
					uci set secubox-p2p.gitea.repo_name="$repo_name"
					uci set secubox-p2p.gitea.repo_owner="$owner"
					uci set secubox-p2p.gitea.enabled=1
					uci commit secubox-p2p

					cat <<EOF
{
	"success": true,
	"repo_name": "$repo_name",
	"clone_url": "$clone_url",
	"html_url": "$html_url",
	"owner": "$owner"
}
EOF
				else
					error_msg=$(echo "$response" | jsonfilter -e '@.message' 2>/dev/null || echo "Failed to create repository")
					echo "{\"success\":false,\"error\":\"$error_msg\"}"
				fi
				;;

			list_gitea_repos)
				server_url=$(uci -q get secubox-p2p.gitea.server_url)
				access_token=$(uci -q get secubox-p2p.gitea.access_token)

				if [ -z "$server_url" ] || [ -z "$access_token" ]; then
					echo '{"success":false,"repos":[],"error":"Gitea not configured"}'
					exit 0
				fi

				response=$(curl -s "${server_url}/api/v1/user/repos" \
					-H "Authorization: token $access_token" \
					2>/dev/null)

				if [ -n "$response" ]; then
					echo "{\"success\":true,\"repos\":$response}"
				else
					echo '{"success":false,"repos":[],"error":"Failed to fetch repositories"}'
				fi
				;;

			get_gitea_commits)
				read input
				limit=$(echo "$input" | jsonfilter -e '@.limit' 2>/dev/null || echo "20")

				server_url=$(uci -q get secubox-p2p.gitea.server_url)
				access_token=$(uci -q get secubox-p2p.gitea.access_token)
				repo_owner=$(uci -q get secubox-p2p.gitea.repo_owner)
				repo_name=$(uci -q get secubox-p2p.gitea.repo_name)

				if [ -z "$server_url" ] || [ -z "$access_token" ] || [ -z "$repo_owner" ] || [ -z "$repo_name" ]; then
					echo '{"success":false,"commits":[],"error":"Gitea repository not configured"}'
					exit 0
				fi

				response=$(curl -s "${server_url}/api/v1/repos/${repo_owner}/${repo_name}/commits?limit=${limit}" \
					-H "Authorization: token $access_token" \
					2>/dev/null)

				if [ -n "$response" ] && echo "$response" | jsonfilter -e '@[0].sha' >/dev/null 2>&1; then
					echo "{\"success\":true,\"commits\":$response}"
				else
					echo '{"success":false,"commits":[],"error":"Failed to fetch commits or repository empty"}'
				fi
				;;

			push_gitea_backup)
				read input
				message=$(echo "$input" | jsonfilter -e '@.message' 2>/dev/null || echo "SecuBox backup $(date +%Y%m%d-%H%M%S)")
				components=$(echo "$input" | jsonfilter -e '@.components' 2>/dev/null)

				server_url=$(uci -q get secubox-p2p.gitea.server_url)
				access_token=$(uci -q get secubox-p2p.gitea.access_token)
				repo_owner=$(uci -q get secubox-p2p.gitea.repo_owner)
				repo_name=$(uci -q get secubox-p2p.gitea.repo_name)

				if [ -z "$server_url" ] || [ -z "$access_token" ] || [ -z "$repo_owner" ] || [ -z "$repo_name" ]; then
					echo '{"success":false,"error":"Gitea repository not configured"}'
					exit 0
				fi

				# Create backup directory
				backup_dir="/tmp/secubox-gitea-backup-$$"
				mkdir -p "$backup_dir"

				# 1. UCI Configs - Core system configuration
				mkdir -p "$backup_dir/configs"
				for cfg in secubox secubox-appstore secubox-appstore-opkg secubox-exposure \
				           secubox-netifyd secubox-p2p secubox-core network firewall \
				           wireless dhcp system dropbear uhttpd haproxy crowdsec acme \
				           wireguard wireguard_* gitea nodogsplash; do
					[ -f "/etc/config/$cfg" ] && cp "/etc/config/$cfg" "$backup_dir/configs/" 2>/dev/null
				done

				# 2. Profiles - Deployment templates
				if [ -d "/usr/share/secubox/profiles" ]; then
					mkdir -p "$backup_dir/profiles"
					cp -r /usr/share/secubox/profiles/* "$backup_dir/profiles/" 2>/dev/null
				fi

				# 3. Presets - Settings presets
				if [ -d "/etc/secubox/presets" ]; then
					mkdir -p "$backup_dir/presets"
					cp -r /etc/secubox/presets/* "$backup_dir/presets/" 2>/dev/null
				fi

				# 4. App Manifests - Plugin definitions
				if [ -d "/usr/share/secubox/plugins" ]; then
					mkdir -p "$backup_dir/manifests"
					cp -r /usr/share/secubox/plugins/* "$backup_dir/manifests/" 2>/dev/null
				fi

				# 5. Scripts - Automation scripts
				if [ -d "/etc/secubox/scripts" ]; then
					mkdir -p "$backup_dir/scripts"
					cp -r /etc/secubox/scripts/* "$backup_dir/scripts/" 2>/dev/null
				fi

				# 6. Macros - Macro definitions
				if [ -d "/etc/secubox/macros" ]; then
					mkdir -p "$backup_dir/macros"
					cp -r /etc/secubox/macros/* "$backup_dir/macros/" 2>/dev/null
				fi

				# 7. Workflows - Automation workflows
				if [ -d "/etc/secubox/workflows" ]; then
					mkdir -p "$backup_dir/workflows"
					cp -r /etc/secubox/workflows/* "$backup_dir/workflows/" 2>/dev/null
				fi

				# 8. Package lists
				mkdir -p "$backup_dir/packages"
				opkg list-installed > "$backup_dir/packages/installed.txt" 2>/dev/null
				# Also save SecuBox-specific package list
				opkg list-installed | grep -E "^(secubox|luci-app-secubox)" > "$backup_dir/packages/secubox-packages.txt" 2>/dev/null

				# 9. Service states
				mkdir -p "$backup_dir/services"
				for svc in /etc/init.d/secubox*; do
					[ -x "$svc" ] && basename "$svc" >> "$backup_dir/services/enabled.txt"
				done

				# 10. Crontabs
				if [ -f "/etc/crontabs/root" ]; then
					mkdir -p "$backup_dir/cron"
					cp /etc/crontabs/root "$backup_dir/cron/root" 2>/dev/null
				fi

				# 11. SSH authorized keys (for mesh access)
				if [ -f "/etc/dropbear/authorized_keys" ]; then
					mkdir -p "$backup_dir/ssh"
					cp /etc/dropbear/authorized_keys "$backup_dir/ssh/" 2>/dev/null
				fi

				# 12. SSL Certificates (ACME)
				if [ -d "/etc/acme" ]; then
					mkdir -p "$backup_dir/certificates"
					for cert in /etc/acme/*.cer; do
						[ -f "$cert" ] && cp "$cert" "$backup_dir/certificates/" 2>/dev/null
					done
				fi

				# 13. HAProxy configs
				if [ -d "/etc/haproxy" ]; then
					mkdir -p "$backup_dir/haproxy"
					cp /etc/haproxy/*.cfg "$backup_dir/haproxy/" 2>/dev/null
				fi

				# 14. DNS/Hosts
				mkdir -p "$backup_dir/dns"
				[ -f "/etc/hosts" ] && cp /etc/hosts "$backup_dir/dns/" 2>/dev/null
				[ -f "/etc/dnsmasq.conf" ] && cp /etc/dnsmasq.conf "$backup_dir/dns/" 2>/dev/null
				[ -d "/etc/dnsmasq.d" ] && cp /etc/dnsmasq.d/* "$backup_dir/dns/" 2>/dev/null

				# 15. Device info
				mkdir -p "$backup_dir/device"
				ubus call system board > "$backup_dir/device/board.json" 2>/dev/null
				cat /proc/cpuinfo > "$backup_dir/device/cpuinfo.txt" 2>/dev/null
				free -h > "$backup_dir/device/memory.txt" 2>/dev/null

				# Create comprehensive manifest
				config_count=$(find "$backup_dir/configs" -type f 2>/dev/null | wc -l)
				profile_count=$(find "$backup_dir/profiles" -type f 2>/dev/null | wc -l)
				manifest_count=$(find "$backup_dir/manifests" -type f 2>/dev/null | wc -l)
				script_count=$(find "$backup_dir/scripts" -type f 2>/dev/null | wc -l)

				cat > "$backup_dir/manifest.json" <<MANIFEST
{
	"schema_version": "1.0",
	"timestamp": "$(date -Iseconds)",
	"hostname": "$(uci -q get system.@system[0].hostname || echo "secubox")",
	"secubox_version": "$(cat /etc/secubox-version 2>/dev/null || echo "unknown")",
	"openwrt_version": "$(. /etc/openwrt_release 2>/dev/null && echo $DISTRIB_RELEASE || echo unknown)",
	"device_model": "$(cat /tmp/sysinfo/model 2>/dev/null || echo "unknown")",
	"message": "$message",
	"contents": {
		"configs": $config_count,
		"profiles": $profile_count,
		"manifests": $manifest_count,
		"scripts": $script_count
	},
	"components": [
		"configs",
		"profiles",
		"presets",
		"manifests",
		"scripts",
		"macros",
		"workflows",
		"packages",
		"services",
		"cron",
		"ssh",
		"certificates",
		"haproxy",
		"dns",
		"device"
	]
}
MANIFEST

				# Create bootstrap.sh for quick restore
				cat > "$backup_dir/bootstrap.sh" <<'BOOTSTRAP'
#!/bin/sh
# SecuBox Quick Restore Bootstrap
# Run: wget -qO- URL | sh  OR  curl -sL URL | sh
set -e
SERVER_URL="__SERVER_URL__"
REPO_OWNER="__REPO_OWNER__"
REPO_NAME="__REPO_NAME__"

echo "SecuBox Quick Restore"
echo "====================="
echo "From: $SERVER_URL/$REPO_OWNER/$REPO_NAME"
echo ""

# Check OpenWrt
[ -f /etc/openwrt_release ] || { echo "Error: Not OpenWrt"; exit 1; }

# Install deps
opkg update >/dev/null 2>&1 || true
opkg install curl git-http 2>/dev/null || true

# Download restore script
RESTORE_URL="$SERVER_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/contents/scripts/secubox-restore?ref=master"
SCRIPT=$(curl -sL "$RESTORE_URL" | jsonfilter -e '@.content' 2>/dev/null | base64 -d 2>/dev/null)

if [ -n "$SCRIPT" ]; then
	echo "$SCRIPT" > /tmp/secubox-restore
	chmod +x /tmp/secubox-restore
	/tmp/secubox-restore "$SERVER_URL" "$REPO_OWNER" "$REPO_NAME"
else
	echo "Fallback: Direct config restore..."
	# Minimal restore - fetch and apply configs
	API_BASE="$SERVER_URL/api/v1/repos/$REPO_OWNER/$REPO_NAME/contents"
	mkdir -p /tmp/secubox-restore-$$

	# Get configs list
	configs=$(curl -sL "$API_BASE/configs" | jsonfilter -e '@[*].name' 2>/dev/null)
	for cfg in $configs; do
		echo "Restoring: $cfg"
		content=$(curl -sL "$API_BASE/configs/$cfg" | jsonfilter -e '@.content' 2>/dev/null | base64 -d)
		[ -n "$content" ] && echo "$content" > "/etc/config/$cfg"
	done

	echo ""
	echo "Basic restore complete. Reboot recommended."
fi
BOOTSTRAP

				# Replace placeholders in bootstrap
				sed -i "s|__SERVER_URL__|$server_url|g" "$backup_dir/bootstrap.sh"
				sed -i "s|__REPO_OWNER__|$repo_owner|g" "$backup_dir/bootstrap.sh"
				sed -i "s|__REPO_NAME__|$repo_name|g" "$backup_dir/bootstrap.sh"

				# Also copy the full restore script
				mkdir -p "$backup_dir/scripts"
				if [ -f "/usr/bin/secubox-restore" ]; then
					cp /usr/bin/secubox-restore "$backup_dir/scripts/"
				fi

				# Push each file via Gitea API
				pushed_files=0
				api_base="${server_url}/api/v1/repos/${repo_owner}/${repo_name}/contents"

				for file in $(find "$backup_dir" -type f); do
					rel_path="${file#$backup_dir/}"
					content=$(base64 "$file" | tr -d '\n')

					# Check if file exists (to update vs create) - use main branch
					existing=$(curl -s "${api_base}/${rel_path}?ref=main" \
						-H "Authorization: token $access_token" 2>/dev/null)
					sha=$(echo "$existing" | jsonfilter -e '@.sha' 2>/dev/null)

					if [ -n "$sha" ]; then
						# Update existing file with branch specification
						curl -s -X PUT "${api_base}/${rel_path}" \
							-H "Authorization: token $access_token" \
							-H "Content-Type: application/json" \
							-d "{\"message\":\"$message\",\"content\":\"$content\",\"sha\":\"$sha\",\"branch\":\"main\"}" \
							>/dev/null 2>&1
					else
						# Create new file on main branch
						curl -s -X POST "${api_base}/${rel_path}" \
							-H "Authorization: token $access_token" \
							-H "Content-Type: application/json" \
							-d "{\"message\":\"$message\",\"content\":\"$content\",\"branch\":\"main\"}" \
							>/dev/null 2>&1
					fi
					pushed_files=$((pushed_files + 1))
				done

				# Cleanup
				rm -rf "$backup_dir"

				echo "{\"success\":true,\"files_pushed\":$pushed_files,\"message\":\"$message\"}"
				;;

			pull_gitea_backup)
				read input
				commit_sha=$(echo "$input" | jsonfilter -e '@.commit_sha' 2>/dev/null)

				server_url=$(uci -q get secubox-p2p.gitea.server_url)
				access_token=$(uci -q get secubox-p2p.gitea.access_token)
				repo_owner=$(uci -q get secubox-p2p.gitea.repo_owner)
				repo_name=$(uci -q get secubox-p2p.gitea.repo_name)

				if [ -z "$server_url" ] || [ -z "$access_token" ] || [ -z "$repo_owner" ] || [ -z "$repo_name" ]; then
					echo '{"success":false,"error":"Gitea repository not configured"}'
					exit 0
				fi

				# Get file tree at commit
				ref_param=""
				[ -n "$commit_sha" ] && ref_param="?ref=$commit_sha"

				tree=$(curl -s "${server_url}/api/v1/repos/${repo_owner}/${repo_name}/contents${ref_param}" \
					-H "Authorization: token $access_token" 2>/dev/null)

				if [ -z "$tree" ]; then
					echo '{"success":false,"error":"Failed to fetch repository contents"}'
					exit 0
				fi

				# Create restore directory
				restore_dir="/tmp/secubox-restore-$$"
				mkdir -p "$restore_dir"
				restored_files=0

				# Download configs directory
				configs=$(curl -s "${server_url}/api/v1/repos/${repo_owner}/${repo_name}/contents/configs${ref_param}" \
					-H "Authorization: token $access_token" 2>/dev/null)

				if echo "$configs" | jsonfilter -e '@[0].name' >/dev/null 2>&1; then
					mkdir -p "$restore_dir/configs"
					for file_info in $(echo "$configs" | jsonfilter -e '@[*].name'); do
						file_content=$(curl -s "${server_url}/api/v1/repos/${repo_owner}/${repo_name}/contents/configs/${file_info}${ref_param}" \
							-H "Authorization: token $access_token" 2>/dev/null)
						content_b64=$(echo "$file_content" | jsonfilter -e '@.content' 2>/dev/null)
						if [ -n "$content_b64" ]; then
							echo "$content_b64" | base64 -d > "$restore_dir/configs/$file_info"
							restored_files=$((restored_files + 1))
						fi
					done

					# Apply configs (with backup)
					if [ -d "$restore_dir/configs" ]; then
						cp -r /etc/config /etc/config.bak.$(date +%Y%m%d%H%M%S) 2>/dev/null
						for cfg in "$restore_dir"/configs/secubox*; do
							[ -f "$cfg" ] && cp "$cfg" /etc/config/ 2>/dev/null
						done
					fi
				fi

				# Cleanup
				rm -rf "$restore_dir"

				echo "{\"success\":true,\"files_restored\":$restored_files,\"commit\":\"${commit_sha:-HEAD}\"}"
				;;

			create_local_backup)
				read input
				backup_name=$(echo "$input" | jsonfilter -e '@.name' 2>/dev/null || echo "backup-$(date +%Y%m%d-%H%M%S)")

				backup_base=$(uci -q get secubox-p2p.backup.backup_dir || echo "/etc/secubox/backups")
				mkdir -p "$backup_base"

				backup_dir="$backup_base/$backup_name"
				mkdir -p "$backup_dir"

				# Backup configs
				mkdir -p "$backup_dir/configs"
				cp -r /etc/config/secubox* "$backup_dir/configs/" 2>/dev/null
				cp /etc/config/network "$backup_dir/configs/" 2>/dev/null
				cp /etc/config/firewall "$backup_dir/configs/" 2>/dev/null
				cp /etc/config/wireless "$backup_dir/configs/" 2>/dev/null

				# Backup package list
				opkg list-installed > "$backup_dir/packages.txt" 2>/dev/null

				# Create manifest
				cat > "$backup_dir/manifest.json" <<MANIFEST
{
	"name": "$backup_name",
	"timestamp": "$(date -Iseconds)",
	"hostname": "$(uci -q get system.@system[0].hostname || echo "secubox")",
	"version": "$(cat /etc/secubox-version 2>/dev/null || echo "unknown")"
}
MANIFEST

				# Cleanup old backups
				max_backups=$(uci -q get secubox-p2p.backup.max_backups || echo 10)
				if [ "$(uci -q get secubox-p2p.backup.auto_cleanup)" = "1" ]; then
					ls -1dt "$backup_base"/*/ 2>/dev/null | tail -n +$((max_backups + 1)) | xargs rm -rf 2>/dev/null
				fi

				backup_size=$(du -sh "$backup_dir" 2>/dev/null | cut -f1)
				echo "{\"success\":true,\"backup_id\":\"$backup_name\",\"path\":\"$backup_dir\",\"size\":\"$backup_size\"}"
				;;

			list_local_backups)
				backup_base=$(uci -q get secubox-p2p.backup.backup_dir || echo "/etc/secubox/backups")
				mkdir -p "$backup_base"

				echo '{"success":true,"backups":['
				first=1
				for dir in "$backup_base"/*/; do
					[ -d "$dir" ] || continue
					backup_id=$(basename "$dir")
					if [ -f "$dir/manifest.json" ]; then
						timestamp=$(jsonfilter -i "$dir/manifest.json" -e '@.timestamp' 2>/dev/null || echo "")
						hostname=$(jsonfilter -i "$dir/manifest.json" -e '@.hostname' 2>/dev/null || echo "")
					else
						timestamp=""
						hostname=""
					fi
					size=$(du -sh "$dir" 2>/dev/null | cut -f1)
					[ $first -eq 1 ] || echo ","
					first=0
					echo "{\"id\":\"$backup_id\",\"timestamp\":\"$timestamp\",\"hostname\":\"$hostname\",\"size\":\"$size\"}"
				done
				echo ']}'
				;;

			restore_local_backup)
				read input
				backup_id=$(echo "$input" | jsonfilter -e '@.backup_id' 2>/dev/null)

				backup_base=$(uci -q get secubox-p2p.backup.backup_dir || echo "/etc/secubox/backups")
				backup_dir="$backup_base/$backup_id"

				if [ ! -d "$backup_dir" ]; then
					echo '{"success":false,"error":"Backup not found"}'
					exit 0
				fi

				# Create pre-restore backup
				pre_restore="$backup_base/pre-restore-$(date +%Y%m%d-%H%M%S)"
				mkdir -p "$pre_restore/configs"
				cp -r /etc/config/secubox* "$pre_restore/configs/" 2>/dev/null

				# Restore configs
				restored=0
				if [ -d "$backup_dir/configs" ]; then
					for cfg in "$backup_dir"/configs/*; do
						[ -f "$cfg" ] && cp "$cfg" /etc/config/ 2>/dev/null && restored=$((restored + 1))
					done
				fi

				echo "{\"success\":true,\"files_restored\":$restored,\"pre_restore_backup\":\"$pre_restore\"}"
				;;

			get_feed_peers)
				# Return list of peers with active package feeds
				. /usr/lib/secubox/p2p-feed.sh 2>/dev/null

				json_init
				json_add_boolean "success" 1
				json_add_array "peers"

				peers=$(get_feed_peers)
				for peer_line in $peers; do
					peer_addr=$(echo "$peer_line" | cut -d'|' -f1)
					peer_name=$(echo "$peer_line" | cut -d'|' -f2)
					feed_info=$(echo "$peer_line" | cut -d'|' -f3-)
					feed_hash=$(echo "$feed_info" | cut -d'|' -f1)
					pkg_count=$(echo "$feed_info" | cut -d'|' -f2)

					json_add_object ""
					json_add_string "address" "$peer_addr"
					json_add_string "name" "$peer_name"
					json_add_string "feed_hash" "$feed_hash"
					json_add_int "package_count" "${pkg_count:-0}"
					json_close_object
				done

				json_close_array
				json_dump
				;;

			get_peer_packages)
				# Fetch package list from a specific peer
				read input
				peer_addr=$(echo "$input" | jsonfilter -e '@.peer_addr' 2>/dev/null)

				if [ -z "$peer_addr" ]; then
					echo '{"success":false,"error":"peer_addr required"}'
					exit 0
				fi

				result=$(curl -s --connect-timeout 5 --max-time 30 \
					"http://${peer_addr}:7331/api/factory/packages" 2>/dev/null)

				if [ -n "$result" ]; then
					echo "$result"
				else
					echo '{"success":false,"error":"Failed to fetch from peer"}'
				fi
				;;

			get_all_packages)
				# Return aggregated packages from local + all peers
				curl -s "http://127.0.0.1:7331/api/factory/packages-sync" 2>/dev/null || \
					echo '{"success":false,"error":"Failed to sync packages"}'
				;;

			fetch_package)
				# Download a package from a peer to local feed
				read input
				package=$(echo "$input" | jsonfilter -e '@.package' 2>/dev/null)
				peer_addr=$(echo "$input" | jsonfilter -e '@.peer_addr' 2>/dev/null)

				if [ -z "$package" ]; then
					echo '{"success":false,"error":"package name required"}'
					exit 0
				fi

				. /usr/lib/secubox/p2p-feed.sh 2>/dev/null

				# Get package info from peer (or search all peers if no peer specified)
				if [ -n "$peer_addr" ]; then
					pkg_info=$(curl -s --connect-timeout 5 --max-time 10 \
						"http://${peer_addr}:7331/api/factory/packages?package=$package" 2>/dev/null)
					filename=$(echo "$pkg_info" | jsonfilter -e '@.packages[0].filename' 2>/dev/null)

					if [ -n "$filename" ]; then
						# Download the IPK
						dest="/www/secubox-feed/$filename"
						if curl -s --connect-timeout 5 --max-time 300 \
							-o "$dest" \
							"http://${peer_addr}/secubox-feed/$filename" 2>/dev/null; then

							if [ -s "$dest" ]; then
								# Update Packages index
								/usr/sbin/secubox-feed update >/dev/null 2>&1
								echo "{\"success\":true,\"package\":\"$package\",\"filename\":\"$filename\",\"source\":\"$peer_addr\"}"
							else
								rm -f "$dest"
								echo '{"success":false,"error":"Downloaded file is empty"}'
							fi
						else
							echo '{"success":false,"error":"Failed to download package"}'
						fi
					else
						echo '{"success":false,"error":"Package not found on peer"}'
					fi
				else
					# Search all peers
					search_result=$(search_package "$package" | head -1)
					if [ -n "$search_result" ]; then
						source=$(echo "$search_result" | cut -d'|' -f1)
						if [ "$source" = "local" ]; then
							echo '{"success":true,"package":"'$package'","source":"local","message":"Package already available locally"}'
						else
							found_peer=$(echo "$search_result" | cut -d'|' -f2)
							# Recursive call with specific peer
							echo "{\"package\":\"$package\",\"peer_addr\":\"$found_peer\"}" | \
								/usr/libexec/rpcd/luci.secubox-p2p call fetch_package
						fi
					else
						echo '{"success":false,"error":"Package not found on any peer"}'
					fi
				fi
				;;

			sync_package_catalog)
				# Sync package catalogs from all peers
				read input
				refresh=$(echo "$input" | jsonfilter -e '@.refresh' 2>/dev/null || echo "0")

				url="http://127.0.0.1:7331/api/factory/packages-sync"
				[ "$refresh" = "1" ] || [ "$refresh" = "true" ] && url="$url?refresh=1"

				curl -s "$url" 2>/dev/null || \
					echo '{"success":false,"error":"Failed to sync package catalog"}'
				;;

			get_feed_settings)
				# Return P2P feed settings
				json_init
				json_add_boolean "success" 1
				json_add_boolean "enabled" $(uci -q get secubox-p2p.feed.enabled || echo "1")
				json_add_boolean "share_feed" $(uci -q get secubox-p2p.feed.share_feed || echo "1")
				json_add_boolean "auto_sync" $(uci -q get secubox-p2p.feed.auto_sync || echo "1")
				json_add_int "sync_interval" $(uci -q get secubox-p2p.feed.sync_interval || echo "3600")
				json_add_boolean "prefer_local" $(uci -q get secubox-p2p.feed.prefer_local || echo "1")
				json_add_int "cache_ttl" $(uci -q get secubox-p2p.feed.cache_ttl || echo "300")
				json_dump
				;;

			set_feed_settings)
				# Update P2P feed settings
				read input

				share_feed=$(echo "$input" | jsonfilter -e '@.share_feed' 2>/dev/null)
				auto_sync=$(echo "$input" | jsonfilter -e '@.auto_sync' 2>/dev/null)
				sync_interval=$(echo "$input" | jsonfilter -e '@.sync_interval' 2>/dev/null)
				prefer_local=$(echo "$input" | jsonfilter -e '@.prefer_local' 2>/dev/null)

				[ -n "$share_feed" ] && uci set secubox-p2p.feed.share_feed="$share_feed"
				[ -n "$auto_sync" ] && uci set secubox-p2p.feed.auto_sync="$auto_sync"
				[ -n "$sync_interval" ] && uci set secubox-p2p.feed.sync_interval="$sync_interval"
				[ -n "$prefer_local" ] && uci set secubox-p2p.feed.prefer_local="$prefer_local"

				uci commit secubox-p2p

				echo '{"success":true}'
				;;

			*)
				echo '{"error":"Unknown method"}'
				;;
		esac
		;;
esac
