#!/bin/sh
# SecuBox mitmproxy manager - LXC container support with transparent mode
# Copyright (C) 2024-2025 CyberMind.fr

CONFIG="mitmproxy"
LXC_NAME="mitmproxy"
OPKG_UPDATED=0
NFT_TABLE="mitmproxy"
NFT_TABLE_WAN="mitmproxy_wan"

# Paths
LXC_PATH="/srv/lxc"
LXC_ROOTFS="$LXC_PATH/$LXC_NAME/rootfs"
LXC_CONFIG="$LXC_PATH/$LXC_NAME/config"
ADDON_PATH="/etc/mitmproxy/addons"

usage() {
	cat <<'EOF'
Usage: mitmproxyctl <command>

Commands:
  install         Install prerequisites and create LXC container
  check           Run prerequisite checks
  update          Update mitmproxy in container
  status          Show container status
  logs            Show mitmproxy logs (use -f to follow)
  shell           Open shell in container
  cert            Show CA certificate info / export path
  firewall-setup  Setup nftables rules for transparent mode
  firewall-clear  Remove nftables transparent mode rules
  wan-setup       Setup WAN protection mode (incoming traffic)
  wan-clear       Remove WAN protection mode rules
  sync-routes     Sync HAProxy backends to mitmproxy routes
  haproxy-enable  Enable HAProxy backend inspection mode
  haproxy-disable Disable HAProxy backend inspection mode
  process-autoban Process auto-ban requests from WAF (run via cron)
  reload-autoban  Reload auto-ban config after UCI changes
  service-run     Internal: run container under procd
  service-stop    Stop container

Auto-ban Sensitivity Levels:
  aggressive    - Ban immediately on first critical threat
  moderate      - Ban after repeated attempts (default: 3 in 5 min)
  permissive    - Ban after persistent attempts (default: 5 in 1 hour)

  Configure with: uci set mitmproxy.autoban.sensitivity='moderate'

Modes (configure in /etc/config/mitmproxy):
  regular      - Standard HTTP/HTTPS proxy (default)
  transparent  - Transparent proxy (auto-configures nftables)
  upstream     - Forward to upstream proxy
  reverse      - Reverse proxy mode

WAN Protection Mode:
  Intercept incoming WAN traffic for threat detection (WAF mode).
  Detects bot scanners, attacks, and feeds to CrowdSec.
  Use 'mitmproxyctl wan-setup' to enable.

HAProxy Integration:
  When enabled, HAProxy backends route through mitmproxy for
  threat detection. Use 'mitmproxyctl haproxy-enable' to setup.

Web Interface: http://<router-ip>:8082
Proxy Port: 8888
HAProxy Port: 8889
EOF
}

require_root() { [ "$(id -u)" -eq 0 ] || { echo "Root required" >&2; exit 1; }; }

log_info() { echo "[INFO] $*"; }
log_warn() { echo "[WARN] $*" >&2; }
log_error() { echo "[ERROR] $*" >&2; }

uci_get() { uci -q get ${CONFIG}.$1; }
uci_set() { uci set ${CONFIG}.$1="$2" && uci commit ${CONFIG}; }
uci_get_list() { uci -q get ${CONFIG}.$1 2>/dev/null; }

# Write autoban config to JSON for container to read
write_autoban_config() {
	load_config

	local autoban_enabled=$(uci_get autoban.enabled || echo 0)
	local ban_duration=$(uci_get autoban.ban_duration || echo "4h")
	local min_severity=$(uci_get autoban.min_severity || echo "critical")
	local ban_cve=$(uci_get autoban.ban_cve_exploits || echo 1)
	local ban_sqli=$(uci_get autoban.ban_sqli || echo 1)
	local ban_cmdi=$(uci_get autoban.ban_cmdi || echo 1)
	local ban_traversal=$(uci_get autoban.ban_traversal || echo 1)
	local ban_scanners=$(uci_get autoban.ban_scanners || echo 1)
	local ban_rate_limit=$(uci_get autoban.ban_rate_limit || echo 0)
	local whitelist=$(uci_get autoban.whitelist || echo "")
	local sensitivity=$(uci_get autoban.sensitivity || echo "moderate")
	local moderate_threshold=$(uci_get autoban.moderate_threshold || echo 3)
	local moderate_window=$(uci_get autoban.moderate_window || echo 300)
	local permissive_threshold=$(uci_get autoban.permissive_threshold || echo 5)
	local permissive_window=$(uci_get autoban.permissive_window || echo 3600)

	# Convert 0/1 to true/false for JSON
	local enabled_json="false"
	[ "$autoban_enabled" = "1" ] && enabled_json="true"
	local cve_json="false"
	[ "$ban_cve" = "1" ] && cve_json="true"
	local sqli_json="false"
	[ "$ban_sqli" = "1" ] && sqli_json="true"
	local cmdi_json="false"
	[ "$ban_cmdi" = "1" ] && cmdi_json="true"
	local traversal_json="false"
	[ "$ban_traversal" = "1" ] && traversal_json="true"
	local scanners_json="false"
	[ "$ban_scanners" = "1" ] && scanners_json="true"
	local rate_json="false"
	[ "$ban_rate_limit" = "1" ] && rate_json="true"

	# Write JSON config
	cat > "$data_path/autoban.json" << EOF
{
  "enabled": $enabled_json,
  "ban_duration": "$ban_duration",
  "min_severity": "$min_severity",
  "ban_cve_exploits": $cve_json,
  "ban_sqli": $sqli_json,
  "ban_cmdi": $cmdi_json,
  "ban_traversal": $traversal_json,
  "ban_scanners": $scanners_json,
  "ban_rate_limit": $rate_json,
  "whitelist": "$whitelist",
  "sensitivity": "$sensitivity",
  "moderate_threshold": $moderate_threshold,
  "moderate_window": $moderate_window,
  "permissive_threshold": $permissive_threshold,
  "permissive_window": $permissive_window
}
EOF
	chmod 644 "$data_path/autoban.json"
}

# Load configuration with defaults
load_config() {
	# Main settings
	proxy_port="$(uci_get main.proxy_port || echo 8888)"
	web_port="$(uci_get main.web_port || echo 8081)"
	web_host="$(uci_get main.web_host || echo 0.0.0.0)"
	data_path="$(uci_get main.data_path || echo /srv/mitmproxy)"
	memory_limit="$(uci_get main.memory_limit || echo 256M)"
	mode="$(uci_get main.mode || echo regular)"
	upstream_proxy="$(uci_get main.upstream_proxy || echo '')"
	reverse_target="$(uci_get main.reverse_target || echo '')"
	ssl_insecure="$(uci_get main.ssl_insecure || echo 0)"
	anticache="$(uci_get main.anticache || echo 0)"
	anticomp="$(uci_get main.anticomp || echo 0)"
	flow_detail="$(uci_get main.flow_detail || echo 1)"

	# WAN protection mode settings
	wan_protection_enabled="$(uci_get wan_protection.enabled || echo 0)"
	wan_interface="$(uci_get wan_protection.wan_interface || echo wan)"
	wan_http_port="$(uci_get wan_protection.wan_http_port || echo 80)"
	wan_https_port="$(uci_get wan_protection.wan_https_port || echo 443)"
	crowdsec_feed="$(uci_get wan_protection.crowdsec_feed || echo 1)"
	block_bots="$(uci_get wan_protection.block_bots || echo 0)"
	rate_limit="$(uci_get wan_protection.rate_limit || echo 0)"

	# Transparent mode settings (LAN)
	transparent_enabled="$(uci_get transparent.enabled || echo 0)"
	transparent_iface="$(uci_get transparent.interface || echo br-lan)"
	redirect_http="$(uci_get transparent.redirect_http || echo 1)"
	redirect_https="$(uci_get transparent.redirect_https || echo 1)"
	http_port="$(uci_get transparent.http_port || echo 80)"
	https_port="$(uci_get transparent.https_port || echo 443)"

	# DPI mirror settings
	dpi_mirror_enabled="$(uci_get dpi_mirror.enabled || echo 0)"
	dpi_interface="$(uci_get dpi_mirror.dpi_interface || echo br-lan)"
	mirror_wan="$(uci_get dpi_mirror.mirror_wan || echo 0)"
	mirror_lan="$(uci_get dpi_mirror.mirror_lan || echo 0)"

	# Whitelist settings
	whitelist_enabled="$(uci_get whitelist.enabled || echo 1)"

	# Filtering settings
	filtering_enabled="$(uci_get filtering.enabled || echo 0)"
	log_requests="$(uci_get filtering.log_requests || echo 1)"
	filter_cdn="$(uci_get filtering.filter_cdn || echo 0)"
	filter_media="$(uci_get filtering.filter_media || echo 0)"
	block_ads="$(uci_get filtering.block_ads || echo 0)"
	addon_script="$(uci_get filtering.addon_script || echo /data/addons/secubox_analytics.py)"

	# HAProxy router settings
	haproxy_router_enabled="$(uci_get haproxy_router.enabled || echo 0)"
	haproxy_listen_port="$(uci_get haproxy_router.listen_port || echo 8889)"
	haproxy_threat_detection="$(uci_get haproxy_router.threat_detection || echo 1)"
	haproxy_routes_file="$(uci_get haproxy_router.routes_file || echo /srv/mitmproxy/haproxy-routes.json)"
}

ensure_dir() { [ -d "$1" ] || mkdir -p "$1"; }

has_lxc() {
	command -v lxc-start >/dev/null 2>&1 && \
	command -v lxc-stop >/dev/null 2>&1
}

has_nft() {
	command -v nft >/dev/null 2>&1
}

# Ensure required packages are installed
ensure_packages() {
	require_root
	for pkg in "$@"; do
		if ! opkg list-installed | grep -q "^$pkg "; then
			if [ "$OPKG_UPDATED" -eq 0 ]; then
				opkg update || return 1
				OPKG_UPDATED=1
			fi
			opkg install "$pkg" || return 1
		fi
	done
}

# =============================================================================
# NFTABLES TRANSPARENT MODE FUNCTIONS
# =============================================================================

nft_setup() {
	load_config
	require_root

	if ! has_nft; then
		log_error "nftables not available"
		return 1
	fi

	if [ "$mode" != "transparent" ]; then
		log_warn "Proxy mode is '$mode', not 'transparent'. Firewall rules not needed."
		return 0
	fi

	# Check if LAN transparent mode is enabled
	if [ "$transparent_enabled" != "1" ]; then
		log_warn "LAN transparent mode is disabled. Enable with: uci set mitmproxy.transparent.enabled='1'"
		log_warn "Note: HTTPS interception requires clients to trust the mitmproxy CA certificate."
		return 0
	fi

	log_info "Setting up nftables for LAN transparent proxy..."
	log_warn "Warning: HTTPS sites may show certificate errors until clients trust the CA."

	# Enable IP forwarding (required for transparent proxying)
	log_info "Enabling IP forwarding..."
	sysctl -w net.ipv4.ip_forward=1 >/dev/null 2>&1
	sysctl -w net.ipv6.conf.all.forwarding=1 >/dev/null 2>&1

	# Create mitmproxy table
	nft add table inet $NFT_TABLE 2>/dev/null || true

	# Create chains
	nft add chain inet $NFT_TABLE prerouting { type nat hook prerouting priority -100 \; } 2>/dev/null || true
	nft add chain inet $NFT_TABLE output { type nat hook output priority -100 \; } 2>/dev/null || true

	# Create bypass set for whitelisted IPs
	nft add set inet $NFT_TABLE bypass_ipv4 { type ipv4_addr \; flags interval \; } 2>/dev/null || true
	nft add set inet $NFT_TABLE bypass_ipv6 { type ipv6_addr \; flags interval \; } 2>/dev/null || true

	# Load whitelist IPs into bypass set
	if [ "$whitelist_enabled" = "1" ]; then
		local bypass_ips=$(uci_get_list whitelist.bypass_ip 2>/dev/null)
		for ip in $bypass_ips; do
			case "$ip" in
				*:*) nft add element inet $NFT_TABLE bypass_ipv6 { $ip } 2>/dev/null || true ;;
				*) nft add element inet $NFT_TABLE bypass_ipv4 { $ip } 2>/dev/null || true ;;
			esac
		done
		log_info "Loaded whitelist bypass IPs"
	fi

	# Get interface index if specified
	local iif_match=""
	if [ -n "$transparent_iface" ]; then
		iif_match="iifname \"$transparent_iface\""
	fi

	# Flush existing rules in our chains
	nft flush chain inet $NFT_TABLE prerouting 2>/dev/null || true
	nft flush chain inet $NFT_TABLE output 2>/dev/null || true

	# Add bypass rules first (before redirect)
	nft add rule inet $NFT_TABLE prerouting ip daddr @bypass_ipv4 return 2>/dev/null || true
	nft add rule inet $NFT_TABLE prerouting ip6 daddr @bypass_ipv6 return 2>/dev/null || true

	# Don't intercept traffic destined for the router itself (local services)
	local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")
	nft add rule inet $NFT_TABLE prerouting ip daddr "$router_ip" return 2>/dev/null || true

	# Redirect HTTP traffic
	if [ "$redirect_http" = "1" ]; then
		if [ -n "$iif_match" ]; then
			nft add rule inet $NFT_TABLE prerouting $iif_match tcp dport $http_port redirect to :$proxy_port
		else
			nft add rule inet $NFT_TABLE prerouting tcp dport $http_port redirect to :$proxy_port
		fi
		log_info "HTTP redirect: port $http_port -> $proxy_port"
	fi

	# Redirect HTTPS traffic
	if [ "$redirect_https" = "1" ]; then
		if [ -n "$iif_match" ]; then
			nft add rule inet $NFT_TABLE prerouting $iif_match tcp dport $https_port redirect to :$proxy_port
		else
			nft add rule inet $NFT_TABLE prerouting tcp dport $https_port redirect to :$proxy_port
		fi
		log_info "HTTPS redirect: port $https_port -> $proxy_port"
	fi

	log_info "nftables transparent mode rules applied"
	log_info "Table: inet $NFT_TABLE"
}

nft_teardown() {
	require_root

	if ! has_nft; then
		return 0
	fi

	log_info "Removing nftables transparent mode rules..."

	# Delete the entire table (removes all chains and rules)
	nft delete table inet $NFT_TABLE 2>/dev/null || true

	log_info "nftables rules removed"
}

nft_status() {
	if ! has_nft; then
		echo "nftables not available"
		return 1
	fi

	echo "=== mitmproxy nftables rules ==="
	if nft list table inet $NFT_TABLE 2>/dev/null; then
		echo ""
		echo "Bypass IPv4 set:"
		nft list set inet $NFT_TABLE bypass_ipv4 2>/dev/null || echo "  (empty or not created)"
		echo ""
		echo "Bypass IPv6 set:"
		nft list set inet $NFT_TABLE bypass_ipv6 2>/dev/null || echo "  (empty or not created)"
	else
		echo "No mitmproxy LAN transparent rules configured"
	fi

	echo ""
	echo "=== WAN protection rules ==="
	if nft list table inet $NFT_TABLE_WAN 2>/dev/null; then
		echo "WAN protection mode active"
	else
		echo "No WAN protection rules configured"
	fi
}

# =============================================================================
# WAN PROTECTION MODE FUNCTIONS
# =============================================================================

# Get the actual network interface name from UCI interface name
get_wan_device() {
	local iface="$1"
	local device=""

	# Try to get device from network config
	device=$(uci -q get network.${iface}.device)
	[ -n "$device" ] && { echo "$device"; return 0; }

	# Try ifname (older OpenWrt)
	device=$(uci -q get network.${iface}.ifname)
	[ -n "$device" ] && { echo "$device"; return 0; }

	# Fallback: check if interface exists directly
	if ip link show "$iface" >/dev/null 2>&1; then
		echo "$iface"
		return 0
	fi

	# Common WAN interface names
	for dev in eth1 eth0.2 wan pppoe-wan; do
		if ip link show "$dev" >/dev/null 2>&1; then
			echo "$dev"
			return 0
		fi
	done

	return 1
}

nft_wan_setup() {
	load_config
	require_root

	if ! has_nft; then
		log_error "nftables not available"
		return 1
	fi

	if [ "$wan_protection_enabled" != "1" ]; then
		log_warn "WAN protection mode is disabled. Enable with: uci set mitmproxy.wan_protection.enabled='1'"
		return 0
	fi

	log_info "Setting up nftables for WAN protection mode..."

	# Get actual WAN device name
	local wan_dev=$(get_wan_device "$wan_interface")
	if [ -z "$wan_dev" ]; then
		log_error "Could not determine WAN device for interface '$wan_interface'"
		return 1
	fi
	log_info "WAN device: $wan_dev (from interface: $wan_interface)"

	# Create WAN protection table
	nft add table inet $NFT_TABLE_WAN 2>/dev/null || true

	# Create prerouting chain for incoming WAN traffic
	nft add chain inet $NFT_TABLE_WAN prerouting { type nat hook prerouting priority -100 \; } 2>/dev/null || true

	# Flush existing rules
	nft flush chain inet $NFT_TABLE_WAN prerouting 2>/dev/null || true

	# Don't redirect traffic destined to router itself (management)
	local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")
	nft add rule inet $NFT_TABLE_WAN prerouting ip daddr "$router_ip" return 2>/dev/null || true

	# Skip private/local destinations (not exposed to WAN)
	nft add rule inet $NFT_TABLE_WAN prerouting ip daddr 10.0.0.0/8 return 2>/dev/null || true
	nft add rule inet $NFT_TABLE_WAN prerouting ip daddr 172.16.0.0/12 return 2>/dev/null || true
	nft add rule inet $NFT_TABLE_WAN prerouting ip daddr 192.168.0.0/16 return 2>/dev/null || true
	nft add rule inet $NFT_TABLE_WAN prerouting ip daddr 127.0.0.0/8 return 2>/dev/null || true

	# Redirect WAN incoming HTTP to mitmproxy
	if [ "$wan_http_port" != "0" ]; then
		nft add rule inet $NFT_TABLE_WAN prerouting iifname "$wan_dev" tcp dport "$wan_http_port" redirect to :$proxy_port
		log_info "WAN HTTP redirect: $wan_dev:$wan_http_port -> mitmproxy:$proxy_port"
	fi

	# Redirect WAN incoming HTTPS to mitmproxy
	if [ "$wan_https_port" != "0" ]; then
		nft add rule inet $NFT_TABLE_WAN prerouting iifname "$wan_dev" tcp dport "$wan_https_port" redirect to :$proxy_port
		log_info "WAN HTTPS redirect: $wan_dev:$wan_https_port -> mitmproxy:$proxy_port"
	fi

	# Optional: Add rate limiting if configured
	if [ "$rate_limit" -gt 0 ] 2>/dev/null; then
		log_info "Rate limiting: $rate_limit requests/minute per IP"
		# Note: Rate limiting in nftables requires meter/limit
		# This is a basic implementation - can be enhanced
		nft add chain inet $NFT_TABLE_WAN ratelimit 2>/dev/null || true
	fi

	log_info "WAN protection mode rules applied"
	log_info "Table: inet $NFT_TABLE_WAN"
	log_info ""
	log_info "Incoming WAN traffic on ports $wan_http_port/$wan_https_port will be"
	log_info "inspected by mitmproxy for threats before reaching backend services."
}

nft_wan_teardown() {
	require_root

	if ! has_nft; then
		return 0
	fi

	log_info "Removing WAN protection mode rules..."

	# Delete the WAN protection table
	nft delete table inet $NFT_TABLE_WAN 2>/dev/null || true

	log_info "WAN protection rules removed"
}

# =============================================================================
# LXC CONTAINER FUNCTIONS
# =============================================================================

lxc_check_prereqs() {
	log_info "Checking LXC prerequisites..."
	ensure_packages lxc lxc-common lxc-attach lxc-start lxc-stop lxc-destroy || return 1

	if [ ! -d /sys/fs/cgroup ]; then
		log_error "cgroups not mounted at /sys/fs/cgroup"
		return 1
	fi

	log_info "LXC ready"
}

lxc_create_rootfs() {
	load_config

	if [ -d "$LXC_ROOTFS" ] && [ -x "$LXC_ROOTFS/usr/bin/mitmproxy" ]; then
		log_info "LXC rootfs already exists with mitmproxy"
		return 0
	fi

	log_info "Creating LXC rootfs for mitmproxy..."
	ensure_dir "$LXC_PATH/$LXC_NAME"

	lxc_create_docker_rootfs || return 1
	lxc_create_config || return 1

	log_info "LXC rootfs created successfully"
}

lxc_create_docker_rootfs() {
	local rootfs="$LXC_ROOTFS"
	local image="mitmproxy/mitmproxy"
	local tag="latest"
	local registry="registry-1.docker.io"
	local arch

	# Detect architecture for Docker manifest
	case "$(uname -m)" in
		x86_64) arch="amd64" ;;
		aarch64) arch="arm64" ;;
		armv7l) arch="arm" ;;
		*) arch="amd64" ;;
	esac

	log_info "Extracting mitmproxy Docker image ($arch)..."
	ensure_dir "$rootfs"

	# Get Docker Hub token
	local token=$(wget -q -O - "https://auth.docker.io/token?service=registry.docker.io&scope=repository:$image:pull" | jsonfilter -e '@.token')
	[ -z "$token" ] && { log_error "Failed to get Docker Hub token"; return 1; }

	# Get manifest list
	local manifest=$(wget -q -O - --header="Authorization: Bearer $token" \
		--header="Accept: application/vnd.docker.distribution.manifest.list.v2+json" \
		"https://$registry/v2/$image/manifests/$tag")

	# Find digest for our architecture
	local digest=$(echo "$manifest" | jsonfilter -e "@.manifests[@.platform.architecture='$arch'].digest")
	[ -z "$digest" ] && { log_error "No manifest found for $arch"; return 1; }

	# Get image manifest
	local img_manifest=$(wget -q -O - --header="Authorization: Bearer $token" \
		--header="Accept: application/vnd.docker.distribution.manifest.v2+json" \
		"https://$registry/v2/$image/manifests/$digest")

	# Extract layers and download them
	log_info "Downloading and extracting layers..."
	local layers=$(echo "$img_manifest" | jsonfilter -e '@.layers[*].digest')

	for layer_digest in $layers; do
		log_info "  Layer: ${layer_digest:7:12}..."
		wget -q -O - --header="Authorization: Bearer $token" \
			"https://$registry/v2/$image/blobs/$layer_digest" | \
			tar xzf - -C "$rootfs" 2>&1 | grep -v "Cannot change ownership" || true
	done

	# Configure container
	echo "nameserver 8.8.8.8" > "$rootfs/etc/resolv.conf"
	mkdir -p "$rootfs/data" "$rootfs/var/log/mitmproxy" "$rootfs/etc/mitmproxy/addons" "$rootfs/tmp"

	# Ensure proper shell setup - Docker image is Python slim (Debian-based)
	# python:slim uses dash as /bin/sh but symlinks may not extract properly
	log_info "Checking shell availability..."
	ls -la "$rootfs/bin/" 2>/dev/null | head -20 || true

	# Ensure /bin/sh exists - critical for script execution
	if [ ! -x "$rootfs/bin/sh" ]; then
		log_warn "/bin/sh not found or not executable, attempting to fix..."
		# Check for available shells
		if [ -x "$rootfs/bin/dash" ]; then
			ln -sf dash "$rootfs/bin/sh"
			log_info "Created /bin/sh -> dash"
		elif [ -x "$rootfs/bin/bash" ]; then
			ln -sf bash "$rootfs/bin/sh"
			log_info "Created /bin/sh -> bash"
		elif [ -x "$rootfs/usr/bin/dash" ]; then
			mkdir -p "$rootfs/bin"
			ln -sf /usr/bin/dash "$rootfs/bin/sh"
			log_info "Created /bin/sh -> /usr/bin/dash"
		else
			# Last resort: copy busybox sh from host if available
			log_error "No shell found in container! Container may not start properly."
		fi
	fi

	# Verify shell is now available
	if [ -x "$rootfs/bin/sh" ]; then
		log_info "Shell ready: $(ls -la "$rootfs/bin/sh")"
	else
		log_error "Shell setup failed!"
	fi

	# Create startup script for mitmweb (POSIX-compliant for dash)
	cat > "$rootfs/opt/start-mitmproxy.sh" << 'START'
#!/bin/sh
export PATH="/usr/local/bin:/usr/bin:/bin:$PATH"
export PYTHONUNBUFFERED=1
cd /data

# Read environment variables
MODE="${MITMPROXY_MODE:-regular}"
PROXY_PORT="${MITMPROXY_PROXY_PORT:-8888}"
WEB_PORT="${MITMPROXY_WEB_PORT:-8081}"
WEB_HOST="${MITMPROXY_WEB_HOST:-0.0.0.0}"
ADDON_SCRIPT="${MITMPROXY_ADDON_SCRIPT:-}"
FILTERING_ENABLED="${MITMPROXY_FILTERING_ENABLED:-0}"

# HAProxy router mode
HAPROXY_ROUTER_ENABLED="${MITMPROXY_HAPROXY_ROUTER_ENABLED:-0}"
HAPROXY_LISTEN_PORT="${MITMPROXY_HAPROXY_LISTEN_PORT:-8889}"
HAPROXY_ROUTES_FILE="${MITMPROXY_HAPROXY_ROUTES_FILE:-/data/haproxy-routes.json}"

# Build args
ARGS="--listen-host 0.0.0.0 --listen-port $PROXY_PORT --set confdir=/data"
ARGS="$ARGS --web-host $WEB_HOST --web-port $WEB_PORT --no-web-open-browser"

# Configure mode
case "$MODE" in
    transparent) ARGS="$ARGS --mode transparent" ;;
    upstream) [ -n "$UPSTREAM_PROXY" ] && ARGS="$ARGS --mode upstream:$UPSTREAM_PROXY" ;;
    reverse) [ -n "$REVERSE_TARGET" ] && ARGS="$ARGS --mode reverse:$REVERSE_TARGET" ;;
esac

# HAProxy router mode: add additional listening port for HAProxy traffic
if [ "$HAPROXY_ROUTER_ENABLED" = "1" ]; then
    ARGS="$ARGS --mode regular@$HAPROXY_LISTEN_PORT"
    echo "HAProxy router mode: listening on port $HAPROXY_LISTEN_PORT"

    # Load HAProxy router addon
    if [ -f "/data/addons/haproxy_router.py" ]; then
        ARGS="$ARGS -s /data/addons/haproxy_router.py"
        echo "Loading HAProxy router addon"
    fi
fi

[ "$SSL_INSECURE" = "1" ] && ARGS="$ARGS --ssl-insecure"
[ "$ANTICACHE" = "1" ] && ARGS="$ARGS --anticache"
[ "$ANTICOMP" = "1" ] && ARGS="$ARGS --anticomp"

# Load analytics addon if filtering is enabled
if [ "$FILTERING_ENABLED" = "1" ] && [ -n "$ADDON_SCRIPT" ] && [ -f "$ADDON_SCRIPT" ]; then
    ARGS="$ARGS -s $ADDON_SCRIPT"
    echo "Loading addon: $ADDON_SCRIPT"
fi

rm -f /data/.mitmproxy_token /tmp/mitmweb.log

echo "Starting mitmweb..."
echo "Command: mitmweb $ARGS"

# Start mitmweb in background, output to log file
/usr/local/bin/mitmweb $ARGS 2>&1 | tee /tmp/mitmweb.log &
MITMWEB_PID=$!

# Wait for token to appear in log (with timeout)
echo "Waiting for authentication token..."
ATTEMPTS=0
MAX_ATTEMPTS=30
while [ $ATTEMPTS -lt $MAX_ATTEMPTS ]; do
    sleep 1
    ATTEMPTS=$((ATTEMPTS + 1))

    if [ -f /tmp/mitmweb.log ]; then
        # Extract token from log - mitmweb outputs: "Web server listening at http://x.x.x.x:8081/?token=XXXXX"
        # Token can be alphanumeric, not just hex
        TOKEN=$(grep -o 'token=[a-zA-Z0-9_-]*' /tmp/mitmweb.log 2>/dev/null | head -1 | cut -d= -f2)
        if [ -n "$TOKEN" ]; then
            echo "$TOKEN" > /data/.mitmproxy_token
            chmod 644 /data/.mitmproxy_token
            echo "Token captured: $(echo "$TOKEN" | cut -c1-8)..."
            echo "Web UI: http://$WEB_HOST:$WEB_PORT/?token=$TOKEN"
            break
        fi
    fi
done

if [ ! -f /data/.mitmproxy_token ]; then
    echo "Warning: Could not capture authentication token after ${MAX_ATTEMPTS}s"
    echo "Check /tmp/mitmweb.log for details"
fi

# Wait for mitmweb process to keep container running
wait $MITMWEB_PID
START
	chmod +x "$rootfs/opt/start-mitmproxy.sh"

	log_info "mitmproxy Docker image extracted successfully"

	# Install the SecuBox filter addon
	install_addon_script
}

install_addon_script() {
	load_config
	ensure_dir "$ADDON_PATH"
	ensure_dir "$LXC_ROOTFS/etc/mitmproxy/addons"

	# Create the SecuBox filter addon
	cat > "$ADDON_PATH/secubox_filter.py" << 'ADDON'
"""
SecuBox mitmproxy Filter Addon
CDN/MediaFlow filtering and request logging
"""
import json
import os
import re
from datetime import datetime
from mitmproxy import http, ctx

# CDN domains to track
CDN_DOMAINS = [
    r'\.cloudflare\.com$',
    r'\.cloudflareinsights\.com$',
    r'\.akamai\.net$',
    r'\.akamaized\.net$',
    r'\.fastly\.net$',
    r'\.cloudfront\.net$',
    r'\.azureedge\.net$',
    r'\.jsdelivr\.net$',
    r'\.unpkg\.com$',
    r'\.cdnjs\.cloudflare\.com$',
]

# Media streaming domains
MEDIA_DOMAINS = [
    r'\.googlevideo\.com$',
    r'\.youtube\.com$',
    r'\.ytimg\.com$',
    r'\.netflix\.com$',
    r'\.nflxvideo\.net$',
    r'\.spotify\.com$',
    r'\.scdn\.co$',
    r'\.twitch\.tv$',
    r'\.ttvnw\.net$',
]

# Ad/Tracker domains to block
AD_DOMAINS = [
    r'\.doubleclick\.net$',
    r'\.googlesyndication\.com$',
    r'\.googleadservices\.com$',
    r'\.facebook\.net$',
    r'\.analytics\.google\.com$',
    r'\.google-analytics\.com$',
    r'\.hotjar\.com$',
    r'\.segment\.io$',
    r'\.mixpanel\.com$',
    r'\.amplitude\.com$',
]

class SecuBoxFilter:
    def __init__(self):
        self.log_file = os.environ.get('MITMPROXY_LOG_FILE', '/data/requests.log')
        self.filter_cdn = os.environ.get('MITMPROXY_FILTER_CDN', '0') == '1'
        self.filter_media = os.environ.get('MITMPROXY_FILTER_MEDIA', '0') == '1'
        self.block_ads = os.environ.get('MITMPROXY_BLOCK_ADS', '0') == '1'
        self.log_requests = os.environ.get('MITMPROXY_LOG_REQUESTS', '1') == '1'

        ctx.log.info(f"SecuBox Filter initialized")
        ctx.log.info(f"  Log requests: {self.log_requests}")
        ctx.log.info(f"  Filter CDN: {self.filter_cdn}")
        ctx.log.info(f"  Filter Media: {self.filter_media}")
        ctx.log.info(f"  Block Ads: {self.block_ads}")

    def _match_domain(self, host, patterns):
        """Check if host matches any pattern"""
        for pattern in patterns:
            if re.search(pattern, host, re.IGNORECASE):
                return True
        return False

    def _log_request(self, flow: http.HTTPFlow, category: str = "normal"):
        """Log request to JSON file"""
        if not self.log_requests:
            return

        try:
            entry = {
                "timestamp": datetime.now().isoformat(),
                "category": category,
                "request": {
                    "method": flow.request.method,
                    "host": flow.request.host,
                    "port": flow.request.port,
                    "path": flow.request.path,
                    "scheme": flow.request.scheme,
                },
            }

            if flow.response:
                entry["response"] = {
                    "status_code": flow.response.status_code,
                    "content_type": flow.response.headers.get("content-type", ""),
                    "content_length": len(flow.response.content) if flow.response.content else 0,
                }

            with open(self.log_file, 'a') as f:
                f.write(json.dumps(entry) + '\n')
        except Exception as e:
            ctx.log.error(f"Failed to log request: {e}")

    def request(self, flow: http.HTTPFlow):
        """Process incoming request"""
        host = flow.request.host

        # Check for ad/tracker domains
        if self.block_ads and self._match_domain(host, AD_DOMAINS):
            ctx.log.info(f"Blocked ad/tracker: {host}")
            flow.response = http.Response.make(
                403,
                b"Blocked by SecuBox",
                {"Content-Type": "text/plain"}
            )
            self._log_request(flow, "blocked_ad")
            return

        # Track CDN requests
        if self._match_domain(host, CDN_DOMAINS):
            self._log_request(flow, "cdn")
            if self.filter_cdn:
                ctx.log.info(f"CDN request: {host}{flow.request.path[:50]}")
            return

        # Track media requests
        if self._match_domain(host, MEDIA_DOMAINS):
            self._log_request(flow, "media")
            if self.filter_media:
                ctx.log.info(f"Media request: {host}{flow.request.path[:50]}")
            return

        # Log normal request
        self._log_request(flow, "normal")

    def response(self, flow: http.HTTPFlow):
        """Process response - update log entry if needed"""
        pass

addons = [SecuBoxFilter()]
ADDON

	# Copy to container rootfs
	cp "$ADDON_PATH/secubox_filter.py" "$LXC_ROOTFS/etc/mitmproxy/addons/" 2>/dev/null || true

	log_info "Addon script installed: $ADDON_PATH/secubox_filter.py"
}

lxc_create_config() {
	load_config

	# Build addon path for container
	local container_addon=""
	if [ "$filtering_enabled" = "1" ] && [ -f "$LXC_ROOTFS$addon_script" ]; then
		container_addon="$addon_script"
	fi

	cat > "$LXC_CONFIG" << EOF
# mitmproxy LXC Configuration
lxc.uts.name = $LXC_NAME

# Root filesystem
lxc.rootfs.path = dir:$LXC_ROOTFS

# Network - use host network for simplicity
lxc.net.0.type = none

# Mounts
lxc.mount.auto = proc:mixed sys:ro cgroup:mixed
lxc.mount.entry = $data_path data none bind,create=dir 0 0
lxc.mount.entry = $ADDON_PATH etc/mitmproxy/addons none bind,create=dir 0 0

# Environment variables for configuration
lxc.environment = MITMPROXY_MODE=$mode
lxc.environment = MITMPROXY_PROXY_PORT=$proxy_port
lxc.environment = MITMPROXY_WEB_PORT=$web_port
lxc.environment = MITMPROXY_WEB_HOST=$web_host
lxc.environment = UPSTREAM_PROXY=$upstream_proxy
lxc.environment = REVERSE_TARGET=$reverse_target
lxc.environment = SSL_INSECURE=$ssl_insecure
lxc.environment = ANTICACHE=$anticache
lxc.environment = ANTICOMP=$anticomp
lxc.environment = FLOW_DETAIL=$flow_detail
lxc.environment = MITMPROXY_FILTERING_ENABLED=$filtering_enabled
lxc.environment = MITMPROXY_ADDON_SCRIPT=$addon_script
lxc.environment = MITMPROXY_LOG_REQUESTS=$log_requests
lxc.environment = MITMPROXY_FILTER_CDN=$filter_cdn
lxc.environment = MITMPROXY_FILTER_MEDIA=$filter_media
lxc.environment = MITMPROXY_BLOCK_ADS=$block_ads
lxc.environment = MITMPROXY_LOG_FILE=/data/requests.log

# HAProxy router mode
lxc.environment = MITMPROXY_HAPROXY_ROUTER_ENABLED=$haproxy_router_enabled
lxc.environment = MITMPROXY_HAPROXY_LISTEN_PORT=$haproxy_listen_port
lxc.environment = MITMPROXY_HAPROXY_ROUTES_FILE=/data/haproxy-routes.json

# Capabilities - drop dangerous ones (sys_admin needed for some ops)
lxc.cap.drop = sys_module mac_admin mac_override sys_time

# Disable seccomp for cgroup v2 compatibility
lxc.seccomp.profile =

# Console/TTY (cgroup v2 compatible)
lxc.tty.max = 0
lxc.pty.max = 256

# cgroup v2 limits (NOT v1 syntax)
lxc.cgroup2.memory.max = $memory_limit_bytes

# Init
lxc.init.cmd = /opt/start-mitmproxy.sh
EOF

	log_info "LXC config created at $LXC_CONFIG"
}

lxc_stop() {
	if lxc-info -n "$LXC_NAME" >/dev/null 2>&1; then
		lxc-stop -n "$LXC_NAME" -k >/dev/null 2>&1 || true
	fi
}

lxc_run() {
	load_config
	lxc_stop

	if [ ! -f "$LXC_CONFIG" ]; then
		log_error "LXC not configured. Run 'mitmproxyctl install' first."
		return 1
	fi

	# Regenerate config to pick up any UCI changes
	lxc_create_config

	# Ensure mount points exist
	ensure_dir "$data_path"
	ensure_dir "$ADDON_PATH"

	# Write autoban config for container
	write_autoban_config

	# Setup LAN transparent firewall rules if both mode=transparent AND transparent.enabled=1
	if [ "$mode" = "transparent" ] && [ "$transparent_enabled" = "1" ]; then
		nft_setup
	fi

	# Setup WAN protection rules if enabled
	if [ "$wan_protection_enabled" = "1" ]; then
		nft_wan_setup
	fi

	log_info "Starting mitmproxy LXC container..."
	log_info "Mode: $mode"
	log_info "Web interface: http://0.0.0.0:$web_port"
	log_info "Proxy port: $proxy_port"
	[ "$filtering_enabled" = "1" ] && log_info "Filtering: enabled"
	[ "$wan_protection_enabled" = "1" ] && log_info "WAN Protection: enabled (interface: $wan_interface)"
	exec lxc-start -n "$LXC_NAME" -F -f "$LXC_CONFIG"
}

lxc_status() {
	load_config
	echo "=== mitmproxy Status ==="
	echo ""

	if lxc-info -n "$LXC_NAME" >/dev/null 2>&1; then
		lxc-info -n "$LXC_NAME"
	else
		echo "LXC container '$LXC_NAME' not found or not configured"
	fi

	echo ""
	echo "=== Configuration ==="
	echo "Mode: $mode"
	echo "Proxy port: $proxy_port"
	echo "Web port: $web_port"
	echo "Data path: $data_path"
	echo "Filtering: $([ "$filtering_enabled" = "1" ] && echo "enabled" || echo "disabled")"

	echo ""
	echo "=== WAN Protection ==="
	echo "Enabled: $([ "$wan_protection_enabled" = "1" ] && echo "yes" || echo "no")"
	if [ "$wan_protection_enabled" = "1" ]; then
		echo "WAN Interface: $wan_interface"
		echo "HTTP Port: $wan_http_port"
		echo "HTTPS Port: $wan_https_port"
		echo "CrowdSec Feed: $([ "$crowdsec_feed" = "1" ] && echo "yes" || echo "no")"
		echo "Block Bots: $([ "$block_bots" = "1" ] && echo "yes" || echo "no")"
	fi

	if [ "$mode" = "transparent" ] || [ "$wan_protection_enabled" = "1" ]; then
		echo ""
		nft_status
	fi
}

lxc_logs() {
	load_config
	local logfile="$LXC_ROOTFS/var/log/mitmproxy/mitmproxy.log"

	if lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then
		# For mitmweb, logs go to stderr which procd captures
		if [ "$1" = "-f" ]; then
			logread -f -e mitmproxy
		else
			logread -e mitmproxy | tail -100
		fi
	elif [ -f "$logfile" ]; then
		if [ "$1" = "-f" ]; then
			tail -f "$logfile"
		else
			tail -100 "$logfile"
		fi
	else
		log_warn "Container not running. Try: logread -e mitmproxy"
	fi
}

lxc_shell() {
	lxc-attach -n "$LXC_NAME" -- /bin/sh
}

lxc_destroy() {
	lxc_stop
	if [ -d "$LXC_PATH/$LXC_NAME" ]; then
		rm -rf "$LXC_PATH/$LXC_NAME"
		log_info "LXC container destroyed"
	fi
}

# =============================================================================
# COMMANDS
# =============================================================================

cmd_install() {
	require_root
	load_config

	if ! has_lxc; then
		log_error "LXC not available. Install lxc packages first."
		exit 1
	fi

	log_info "Installing mitmproxy..."

	# Create directories
	ensure_dir "$data_path"
	ensure_dir "$ADDON_PATH"

	lxc_check_prereqs || exit 1
	lxc_create_rootfs || exit 1

	uci_set main.enabled '1'
	/etc/init.d/mitmproxy enable

	log_info "mitmproxy installed."
	log_info "Start with: /etc/init.d/mitmproxy start"
	log_info "Web interface: http://<router-ip>:$web_port"
	log_info "Proxy port: $proxy_port"
}

cmd_check() {
	load_config

	log_info "Checking prerequisites..."
	if has_lxc; then
		log_info "LXC: available"
		lxc_check_prereqs
	else
		log_warn "LXC: not available"
	fi

	if has_nft; then
		log_info "nftables: available"
	else
		log_warn "nftables: not available (needed for transparent mode)"
	fi
}

cmd_update() {
	require_root
	load_config

	log_info "Updating mitmproxy..."
	lxc_destroy
	lxc_create_rootfs || exit 1

	if /etc/init.d/mitmproxy enabled >/dev/null 2>&1; then
		/etc/init.d/mitmproxy restart
	else
		log_info "Update complete. Restart manually to apply."
	fi
}

cmd_status() {
	lxc_status
}

cmd_logs() {
	lxc_logs "$@"
}

cmd_shell() {
	lxc_shell
}

cmd_cert() {
	load_config

	local cert_path="$data_path/mitmproxy-ca-cert.pem"

	if [ -f "$cert_path" ]; then
		log_info "CA Certificate location: $cert_path"
		log_info ""
		log_info "To install on clients:"
		log_info "  1. Download from: http://<router-ip>:$web_port/cert/pem"
		log_info "  2. Or copy: $cert_path"
		log_info ""
		log_info "Certificate info:"
		openssl x509 -in "$cert_path" -noout -subject -dates 2>/dev/null || \
			cat "$cert_path"
	else
		log_warn "CA certificate not yet generated."
		log_info "Start mitmproxy first: /etc/init.d/mitmproxy start"
		log_info "Then access: http://<router-ip>:$web_port/cert"
	fi
}

cmd_firewall_setup() {
	nft_setup
}

cmd_firewall_clear() {
	nft_teardown
}

cmd_service_run() {
	require_root
	load_config

	if ! has_lxc; then
		log_error "LXC not available"
		exit 1
	fi

	lxc_check_prereqs || exit 1
	lxc_run
}

cmd_service_stop() {
	require_root
	load_config

	# Remove firewall rules
	if [ "$mode" = "transparent" ]; then
		nft_teardown
	fi

	# Remove WAN protection rules
	nft_wan_teardown 2>/dev/null || true

	lxc_stop
}

cmd_wan_setup() {
	nft_wan_setup
}

cmd_wan_clear() {
	nft_wan_teardown
}

# =============================================================================
# HAPROXY BACKEND INSPECTION
# =============================================================================

cmd_sync_routes() {
	load_config

	log_info "Syncing HAProxy backends to mitmproxy routes..."

	local routes_file="$data_path/haproxy-routes.json"
	local tmp_file="/tmp/haproxy-routes.tmp"
	local count=0

	# Start JSON
	echo "{" > "$tmp_file"

	# Get all vhosts - avoid subshell by using temp file
	local vhosts_file="/tmp/haproxy-vhosts.tmp"
	uci show haproxy 2>/dev/null | grep "=vhost" | cut -d'=' -f1 | cut -d'.' -f2 > "$vhosts_file"

	while read vhost; do
		[ -z "$vhost" ] && continue

		local domain=$(uci -q get haproxy.$vhost.domain)
		local backend=$(uci -q get haproxy.$vhost.backend)

		# If currently using mitmproxy_inspector, use the stored original backend
		if [ "$backend" = "mitmproxy_inspector" ]; then
			backend=$(uci -q get haproxy.$vhost.original_backend)
		fi

		# Skip fallback, luci, and mitmproxy backends
		case "$backend" in
			fallback|luci|luci_default|mitmproxy_inspector|"") continue ;;
		esac

		if [ -n "$domain" ] && [ -n "$backend" ]; then
			local ip=""
			local port=""

			# Method 1: Check for inline server field (old style)
			local server=$(uci -q get haproxy.$backend.server)
			if [ -n "$server" ]; then
				# Parse server spec: "name ip:port check [options]"
				local addr=$(echo "$server" | awk '{print $2}')
				ip=$(echo "$addr" | cut -d':' -f1)
				port=$(echo "$addr" | cut -d':' -f2)
				# Handle backends without explicit port
				[ "$ip" = "$port" ] && port="80"
			fi

			# Method 2: Check for separate server section (new style)
			if [ -z "$ip" ]; then
				# Find server section that references this backend
				local server_section=$(uci show haproxy 2>/dev/null | grep "\.backend='$backend'" | grep "=server" | head -1 | cut -d'=' -f1 | cut -d'.' -f2)
				if [ -z "$server_section" ]; then
					# Try pattern: backend_name_servername=server
					server_section=$(uci show haproxy 2>/dev/null | grep "^haproxy\.${backend}_.*=server" | head -1 | cut -d'=' -f1 | cut -d'.' -f2)
				fi

				if [ -n "$server_section" ]; then
					ip=$(uci -q get haproxy.$server_section.address)
					port=$(uci -q get haproxy.$server_section.port)
				fi
			fi

			# Only add route if we found valid ip:port
			if [ -n "$ip" ] && [ -n "$port" ]; then
				if [ $count -gt 0 ]; then
					echo "," >> "$tmp_file"
				fi
				count=$((count + 1))

				printf '  "%s": ["%s", %s]' "$domain" "$ip" "$port" >> "$tmp_file"
				log_info "  $domain -> $ip:$port (backend: $backend)"
			else
				log_warn "  $domain: could not resolve backend '$backend'"
			fi
		fi
	done < "$vhosts_file"

	rm -f "$vhosts_file"

	# Close JSON
	echo "" >> "$tmp_file"
	echo "}" >> "$tmp_file"

	# Move to final location
	mv "$tmp_file" "$routes_file"
	chmod 644 "$routes_file"

	log_info "Generated $routes_file with $count routes"

	# Copy to container data path if container is running
	if lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then
		cp "$routes_file" "$data_path/haproxy-routes.json"
		log_info "Routes synced to container"
	fi
}

cmd_haproxy_enable() {
	require_root
	load_config

	log_info "Enabling HAProxy backend inspection..."

	# 1. Enable HAProxy router in config
	uci set mitmproxy.haproxy_router.enabled='1'
	uci commit mitmproxy

	# 2. Sync routes from HAProxy
	cmd_sync_routes

	# 3. Create HAProxy backend for mitmproxy
	log_info "Configuring HAProxy backend 'mitmproxy_inspector'..."

	# Check if backend already exists
	if ! uci -q get haproxy.mitmproxy_inspector >/dev/null 2>&1; then
		uci set haproxy.mitmproxy_inspector=backend
		uci set haproxy.mitmproxy_inspector.server="mitmproxy 127.0.0.1:$haproxy_listen_port check"
	fi

	# 4. Store original backends and update vhosts to use mitmproxy
	log_info "Updating HAProxy vhosts to route through mitmproxy..."

	local updated=0
	for vhost in $(uci show haproxy 2>/dev/null | grep "=vhost" | cut -d'=' -f1 | cut -d'.' -f2); do
		local current_backend=$(uci -q get haproxy.$vhost.backend)

		# Skip if already using mitmproxy or if it's the fallback
		if [ "$current_backend" = "mitmproxy_inspector" ] || [ "$current_backend" = "fallback" ]; then
			continue
		fi

		# Store original backend
		uci set haproxy.$vhost.original_backend="$current_backend"
		# Set to mitmproxy
		uci set haproxy.$vhost.backend="mitmproxy_inspector"
		updated=$((updated + 1))

		local domain=$(uci -q get haproxy.$vhost.domain)
		log_info "  $domain: $current_backend -> mitmproxy_inspector"
	done

	uci commit haproxy

	log_info "Updated $updated vhosts"

	# 5. Restart services
	log_info "Restarting services..."
	/etc/init.d/mitmproxy restart
	/etc/init.d/haproxy reload 2>/dev/null || /etc/init.d/haproxy restart 2>/dev/null

	log_info ""
	log_info "HAProxy backend inspection ENABLED"
	log_info "All vhost traffic now flows through mitmproxy for threat detection"
	log_info "View threats at: http://<router-ip>/cgi-bin/luci/admin/services/mitmproxy"
}

# =============================================================================
# AUTOBAN PROCESSOR
# =============================================================================

cmd_reload_autoban_config() {
	load_config

	log_info "Reloading auto-ban configuration..."
	write_autoban_config
	log_info "Auto-ban config updated at $data_path/autoban.json"
}

cmd_process_autoban() {
	load_config

	# Refresh config before processing
	write_autoban_config 2>/dev/null || true

	local autoban_enabled=$(uci_get autoban.enabled || echo 0)
	if [ "$autoban_enabled" != "1" ]; then
		return 0
	fi

	local autoban_log="$data_path/autoban-requests.log"
	local processed_log="$data_path/autoban-processed.log"
	local ban_duration=$(uci_get autoban.ban_duration || echo "4h")
	local whitelist=$(uci_get autoban.whitelist || echo "")

	# Check if log exists and has content
	[ ! -f "$autoban_log" ] && return 0
	[ ! -s "$autoban_log" ] && return 0

	# Check if CrowdSec CLI is available
	if ! command -v cscli >/dev/null 2>&1; then
		log_warn "cscli not found - cannot process auto-bans"
		return 1
	fi

	# Process each line in the log
	local processed=0
	local skipped=0

	while IFS= read -r line; do
		[ -z "$line" ] && continue

		# Parse JSON line: {"ip": "x.x.x.x", "reason": "...", "duration": "4h", ...}
		local ip=$(echo "$line" | jsonfilter -e '@.ip' 2>/dev/null)
		local reason=$(echo "$line" | jsonfilter -e '@.reason' 2>/dev/null)
		local req_duration=$(echo "$line" | jsonfilter -e '@.duration' 2>/dev/null)

		[ -z "$ip" ] && continue

		# Use request duration or default
		local duration="${req_duration:-$ban_duration}"

		# Check whitelist
		local skip=0
		if [ -n "$whitelist" ]; then
			for wl_ip in $(echo "$whitelist" | tr ',' ' '); do
				if [ "$ip" = "$wl_ip" ]; then
					log_info "Skipping whitelisted IP: $ip"
					skip=1
					break
				fi
			done
		fi

		if [ "$skip" = "1" ]; then
			skipped=$((skipped + 1))
			continue
		fi

		# Check if IP is already banned
		if cscli decisions list -i "$ip" 2>/dev/null | grep -q "$ip"; then
			log_info "IP already banned: $ip"
			skipped=$((skipped + 1))
			continue
		fi

		# Add ban via CrowdSec
		log_info "Auto-banning IP: $ip for $duration (reason: $reason)"
		if cscli decisions add -i "$ip" -d "$duration" -R "mitmproxy-waf: $reason" -t ban >/dev/null 2>&1; then
			processed=$((processed + 1))
			# Log to processed file
			echo "$(date -Iseconds) BANNED $ip $duration $reason" >> "$processed_log"
		else
			log_error "Failed to ban IP: $ip"
		fi
	done < "$autoban_log"

	# Clear the processed log
	if [ $processed -gt 0 ] || [ $skipped -gt 0 ]; then
		log_info "Processed $processed bans, skipped $skipped"
		: > "$autoban_log"  # Truncate the file
	fi
}

cmd_haproxy_disable() {
	require_root
	load_config

	log_info "Disabling HAProxy backend inspection..."

	# 1. Disable HAProxy router in config
	uci set mitmproxy.haproxy_router.enabled='0'
	uci commit mitmproxy

	# 2. Restore original backends
	log_info "Restoring original HAProxy backends..."

	local restored=0
	for vhost in $(uci show haproxy 2>/dev/null | grep "=vhost" | cut -d'=' -f1 | cut -d'.' -f2); do
		local original_backend=$(uci -q get haproxy.$vhost.original_backend)

		if [ -n "$original_backend" ]; then
			uci set haproxy.$vhost.backend="$original_backend"
			uci delete haproxy.$vhost.original_backend 2>/dev/null
			restored=$((restored + 1))

			local domain=$(uci -q get haproxy.$vhost.domain)
			log_info "  $domain: mitmproxy_inspector -> $original_backend"
		fi
	done

	uci commit haproxy

	log_info "Restored $restored vhosts"

	# 3. Restart services
	log_info "Restarting services..."
	/etc/init.d/haproxy reload 2>/dev/null || /etc/init.d/haproxy restart 2>/dev/null

	log_info ""
	log_info "HAProxy backend inspection DISABLED"
	log_info "Vhosts now route directly to their original backends"
}

# Main Entry Point
case "${1:-}" in
	install) shift; cmd_install "$@" ;;
	check) shift; cmd_check "$@" ;;
	update) shift; cmd_update "$@" ;;
	status) shift; cmd_status "$@" ;;
	logs) shift; cmd_logs "$@" ;;
	shell) shift; cmd_shell "$@" ;;
	cert) shift; cmd_cert "$@" ;;
	firewall-setup) shift; cmd_firewall_setup "$@" ;;
	firewall-clear) shift; cmd_firewall_clear "$@" ;;
	wan-setup) shift; cmd_wan_setup "$@" ;;
	wan-clear) shift; cmd_wan_clear "$@" ;;
	sync-routes) shift; cmd_sync_routes "$@" ;;
	haproxy-enable) shift; cmd_haproxy_enable "$@" ;;
	haproxy-disable) shift; cmd_haproxy_disable "$@" ;;
	process-autoban) shift; cmd_process_autoban "$@" ;;
	reload-autoban) shift; cmd_reload_autoban_config "$@" ;;
	service-run) shift; cmd_service_run "$@" ;;
	service-stop) shift; cmd_service_stop "$@" ;;
	help|--help|-h|'') usage ;;
	*) echo "Unknown command: $1" >&2; usage >&2; exit 1 ;;
esac
