#!/bin/sh
#
# RPCD backend for mitmproxy LuCI interface
# Copyright (C) 2025 CyberMind.fr (SecuBox)
#

. /lib/functions.sh

DATA_DIR=$(uci -q get mitmproxy.main.data_path || echo "/srv/mitmproxy")
LXC_NAME="mitmproxy"
CONF_DIR="$DATA_DIR"
LOG_FILE="$DATA_DIR/requests.log"
FLOW_FILE="$DATA_DIR/flows.bin"

# Get service status
get_status() {
	local running=0
	local pid=""
	local mode="unknown"
	local web_url=""
	local lxc_state=""
	local nft_active="false"

	# Check LXC container status
	if command -v lxc-info >/dev/null 2>&1; then
		lxc_state=$(lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -oE 'RUNNING|STOPPED' || echo "UNKNOWN")
		if [ "$lxc_state" = "RUNNING" ]; then
			running=1
			mode="mitmweb"
			pid=$(lxc-info -n "$LXC_NAME" -p 2>/dev/null | grep -oE '[0-9]+' || echo "0")
		fi
	fi

	# Fallback: check for direct process
	if [ "$running" = "0" ]; then
		if pgrep mitmweb >/dev/null 2>&1; then
			running=1
			pid=$(pgrep mitmweb | head -1)
			mode="mitmweb"
		elif pgrep mitmdump >/dev/null 2>&1; then
			running=1
			pid=$(pgrep mitmdump | head -1)
			mode="mitmdump"
		fi
	fi

	# Check nftables rules
	if command -v nft >/dev/null 2>&1; then
		nft list table inet mitmproxy >/dev/null 2>&1 && nft_active="true"
	fi

	local enabled=$(uci -q get mitmproxy.main.enabled || echo "0")
	local proxy_port=$(uci -q get mitmproxy.main.proxy_port || echo "8080")
	local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081")
	local proxy_mode=$(uci -q get mitmproxy.main.mode || echo "regular")
	local filtering_enabled=$(uci -q get mitmproxy.filtering.enabled || echo "0")
	local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")

	[ "$running" = "1" ] && [ "$mode" = "mitmweb" ] && web_url="http://${router_ip}:${web_port}"

	cat <<EOF
{
	"running": $([ "$running" = "1" ] && echo "true" || echo "false"),
	"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
	"pid": ${pid:-0},
	"mode": "$mode",
	"proxy_mode": "$proxy_mode",
	"lxc_state": "$lxc_state",
	"proxy_port": $proxy_port,
	"web_port": $web_port,
	"web_url": "$web_url",
	"ca_installed": $([ -f "$CONF_DIR/mitmproxy-ca-cert.pem" ] && echo "true" || echo "false"),
	"nft_active": $nft_active,
	"filtering_enabled": $([ "$filtering_enabled" = "1" ] && echo "true" || echo "false")
}
EOF
}

# Get main configuration
get_config() {
	local enabled=$(uci -q get mitmproxy.main.enabled || echo "0")
	local mode=$(uci -q get mitmproxy.main.mode || echo "regular")
	local proxy_port=$(uci -q get mitmproxy.main.proxy_port || echo "8080")
	local web_host=$(uci -q get mitmproxy.main.web_host || echo "0.0.0.0")
	local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081")
	local data_path=$(uci -q get mitmproxy.main.data_path || echo "/srv/mitmproxy")
	local memory_limit=$(uci -q get mitmproxy.main.memory_limit || echo "256M")
	local ssl_insecure=$(uci -q get mitmproxy.main.ssl_insecure || echo "0")
	local anticache=$(uci -q get mitmproxy.main.anticache || echo "0")
	local anticomp=$(uci -q get mitmproxy.main.anticomp || echo "0")
	local flow_detail=$(uci -q get mitmproxy.main.flow_detail || echo "1")

	cat <<EOF
{
	"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
	"mode": "$mode",
	"proxy_port": $proxy_port,
	"web_host": "$web_host",
	"web_port": $web_port,
	"data_path": "$data_path",
	"memory_limit": "$memory_limit",
	"ssl_insecure": $([ "$ssl_insecure" = "1" ] && echo "true" || echo "false"),
	"anticache": $([ "$anticache" = "1" ] && echo "true" || echo "false"),
	"anticomp": $([ "$anticomp" = "1" ] && echo "true" || echo "false"),
	"flow_detail": $flow_detail
}
EOF
}

# Get transparent mode configuration
get_transparent_config() {
	local enabled=$(uci -q get mitmproxy.transparent.enabled || echo "0")
	local interface=$(uci -q get mitmproxy.transparent.interface || echo "br-lan")
	local redirect_http=$(uci -q get mitmproxy.transparent.redirect_http || echo "1")
	local redirect_https=$(uci -q get mitmproxy.transparent.redirect_https || echo "1")
	local http_port=$(uci -q get mitmproxy.transparent.http_port || echo "80")
	local https_port=$(uci -q get mitmproxy.transparent.https_port || echo "443")

	cat <<EOF
{
	"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
	"interface": "$interface",
	"redirect_http": $([ "$redirect_http" = "1" ] && echo "true" || echo "false"),
	"redirect_https": $([ "$redirect_https" = "1" ] && echo "true" || echo "false"),
	"http_port": $http_port,
	"https_port": $https_port
}
EOF
}

# Get whitelist configuration
get_whitelist_config() {
	local enabled=$(uci -q get mitmproxy.whitelist.enabled || echo "1")

	# Get bypass_ip list
	local bypass_ips=$(uci -q get mitmproxy.whitelist.bypass_ip 2>/dev/null | tr ' ' '\n' | while read ip; do
		[ -n "$ip" ] && printf '"%s",' "$ip"
	done | sed 's/,$//')

	# Get bypass_domain list
	local bypass_domains=$(uci -q get mitmproxy.whitelist.bypass_domain 2>/dev/null | tr ' ' '\n' | while read domain; do
		[ -n "$domain" ] && printf '"%s",' "$domain"
	done | sed 's/,$//')

	cat <<EOF
{
	"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
	"bypass_ip": [${bypass_ips}],
	"bypass_domain": [${bypass_domains}]
}
EOF
}

# Get filtering configuration
get_filtering_config() {
	local enabled=$(uci -q get mitmproxy.filtering.enabled || echo "0")
	local log_requests=$(uci -q get mitmproxy.filtering.log_requests || echo "1")
	local filter_cdn=$(uci -q get mitmproxy.filtering.filter_cdn || echo "0")
	local filter_media=$(uci -q get mitmproxy.filtering.filter_media || echo "0")
	local block_ads=$(uci -q get mitmproxy.filtering.block_ads || echo "0")
	local addon_script=$(uci -q get mitmproxy.filtering.addon_script || echo "/etc/mitmproxy/addons/secubox_filter.py")

	cat <<EOF
{
	"enabled": $([ "$enabled" = "1" ] && echo "true" || echo "false"),
	"log_requests": $([ "$log_requests" = "1" ] && echo "true" || echo "false"),
	"filter_cdn": $([ "$filter_cdn" = "1" ] && echo "true" || echo "false"),
	"filter_media": $([ "$filter_media" = "1" ] && echo "true" || echo "false"),
	"block_ads": $([ "$block_ads" = "1" ] && echo "true" || echo "false"),
	"addon_script": "$addon_script"
}
EOF
}

# Get all configuration in one call
get_all_config() {
	cat <<EOF
{
	"main": $(get_config),
	"transparent": $(get_transparent_config),
	"whitelist": $(get_whitelist_config),
	"filtering": $(get_filtering_config)
}
EOF
}

# Get statistics
get_stats() {
	local total_requests=0
	local unique_hosts=0
	local flow_size="0"
	local cdn_requests=0
	local media_requests=0
	local blocked_ads=0

	if [ -f "$LOG_FILE" ]; then
		total_requests=$(wc -l < "$LOG_FILE" 2>/dev/null || echo "0")
		# Use jsonfilter for parsing (OpenWrt native)
		if command -v jsonfilter >/dev/null 2>&1; then
			unique_hosts=$(cat "$LOG_FILE" 2>/dev/null | while read line; do
				echo "$line" | jsonfilter -e '@.request.host' 2>/dev/null
			done | sort -u | wc -l)
			cdn_requests=$(grep -c '"category":"cdn"' "$LOG_FILE" 2>/dev/null || echo "0")
			media_requests=$(grep -c '"category":"media"' "$LOG_FILE" 2>/dev/null || echo "0")
			blocked_ads=$(grep -c '"category":"blocked_ad"' "$LOG_FILE" 2>/dev/null || echo "0")
		fi
	fi

	if [ -f "$FLOW_FILE" ]; then
		flow_size=$(ls -l "$FLOW_FILE" 2>/dev/null | awk '{print $5}' || echo "0")
	fi

	cat <<EOF
{
	"total_requests": $total_requests,
	"unique_hosts": $unique_hosts,
	"flow_file_size": $flow_size,
	"cdn_requests": $cdn_requests,
	"media_requests": $media_requests,
	"blocked_ads": $blocked_ads
}
EOF
}

# Get recent requests
get_requests() {
	local limit="${1:-50}"
	local category="${2:-}"

	if [ ! -f "$LOG_FILE" ]; then
		echo '{"requests":[]}'
		return
	fi

	# Filter by category if specified
	if [ -n "$category" ] && [ "$category" != "all" ]; then
		echo '{"requests":['
		grep "\"category\":\"$category\"" "$LOG_FILE" 2>/dev/null | tail -"$limit" | \
			awk 'BEGIN{first=1}{if(!first)printf ",";first=0;print}' 2>/dev/null || echo ""
		echo ']}'
	else
		echo '{"requests":['
		tail -"$limit" "$LOG_FILE" 2>/dev/null | \
			awk 'BEGIN{first=1}{if(!first)printf ",";first=0;print}' 2>/dev/null || echo ""
		echo ']}'
	fi
}

# Get top hosts
get_top_hosts() {
	local limit="${1:-20}"

	if [ ! -f "$LOG_FILE" ]; then
		echo '{"hosts":[]}'
		return
	fi

	echo '{"hosts":['
	# Parse JSON using grep/sed for compatibility
	grep -o '"host":"[^"]*"' "$LOG_FILE" 2>/dev/null | \
		sed 's/"host":"//;s/"$//' | \
		sort | uniq -c | sort -rn | head -"$limit" | \
		awk 'BEGIN{first=1} {
			if(!first) printf ",";
			first=0;
			gsub(/"/, "\\\"", $2);
			printf "{\"host\":\"%s\",\"count\":%d}", $2, $1
		}'
	echo ']}'
}

# Service control
service_start() {
	/etc/init.d/mitmproxy start >/dev/null 2>&1
	sleep 2
	get_status
}

service_stop() {
	/etc/init.d/mitmproxy stop >/dev/null 2>&1
	sleep 1
	get_status
}

service_restart() {
	/etc/init.d/mitmproxy restart >/dev/null 2>&1
	sleep 2
	get_status
}

# Setup firewall rules
firewall_setup() {
	/usr/sbin/mitmproxyctl firewall-setup 2>&1
	local result=$?
	if [ $result -eq 0 ]; then
		echo '{"success":true,"message":"Firewall rules applied"}'
	else
		echo '{"success":false,"message":"Failed to apply firewall rules"}'
	fi
}

# Clear firewall rules
firewall_clear() {
	/usr/sbin/mitmproxyctl firewall-clear 2>&1
	local result=$?
	if [ $result -eq 0 ]; then
		echo '{"success":true,"message":"Firewall rules cleared"}'
	else
		echo '{"success":false,"message":"Failed to clear firewall rules"}'
	fi
}

# Set configuration
set_config() {
	local key="$1"
	local value="$2"
	local section="main"

	case "$key" in
		save_flows|capture_*)
			section="capture"
			;;
		redirect_*|interface|http_port|https_port)
			section="transparent"
			;;
		bypass_ip|bypass_domain)
			section="whitelist"
			;;
		filter_*|log_requests|block_ads|addon_script)
			section="filtering"
			;;
	esac

	# Handle boolean conversion
	case "$value" in
		true) value="1" ;;
		false) value="0" ;;
	esac

	uci set "mitmproxy.$section.$key=$value"
	uci commit mitmproxy
	echo '{"success":true}'
}

# Add to list (for bypass_ip, bypass_domain)
add_to_list() {
	local key="$1"
	local value="$2"
	local section="whitelist"

	uci add_list "mitmproxy.$section.$key=$value"
	uci commit mitmproxy
	echo '{"success":true}'
}

# Remove from list
remove_from_list() {
	local key="$1"
	local value="$2"
	local section="whitelist"

	uci del_list "mitmproxy.$section.$key=$value"
	uci commit mitmproxy
	echo '{"success":true}'
}

# Clear captured data
clear_data() {
	rm -f "$DATA_DIR"/*.log "$DATA_DIR"/*.bin 2>/dev/null
	echo '{"success":true,"message":"Captured data cleared"}'
}

# Get CA certificate info
get_ca_info() {
	local cert="$CONF_DIR/mitmproxy-ca-cert.pem"
	local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")
	local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081")

	if [ -f "$cert" ]; then
		local subject=$(openssl x509 -in "$cert" -noout -subject 2>/dev/null | sed 's/subject=//')
		local expires=$(openssl x509 -in "$cert" -noout -enddate 2>/dev/null | sed 's/notAfter=//')

		cat <<EOF
{
	"installed": true,
	"path": "$cert",
	"subject": "$subject",
	"expires": "$expires",
	"download_url": "http://$router_ip:$web_port/cert"
}
EOF
	else
		cat <<EOF
{
	"installed": false,
	"path": "$cert",
	"download_url": ""
}
EOF
	fi
}

get_web_token() {
	# Token is written to /data/.mitmproxy_token inside container
	# /data is bind-mounted to DATA_DIR on host
	local token_file="$DATA_DIR/.mitmproxy_token"
	local router_ip=$(uci -q get network.lan.ipaddr || echo "192.168.1.1")
	local web_port=$(uci -q get mitmproxy.main.web_port || echo "8081")
	local token=""

	# Try reading token from host-mounted path
	if [ -f "$token_file" ]; then
		token=$(cat "$token_file" 2>/dev/null | tr -d '\n\r')
	fi

	# Fallback: read token directly from container if host file is missing/empty
	if [ -z "$token" ] && command -v lxc-attach >/dev/null 2>&1; then
		if lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then
			token=$(lxc-attach -n "$LXC_NAME" -- cat /data/.mitmproxy_token 2>/dev/null | tr -d '\n\r')
		fi
	fi

	# Second fallback: parse token from mitmweb log inside container
	if [ -z "$token" ] && command -v lxc-attach >/dev/null 2>&1; then
		if lxc-info -n "$LXC_NAME" -s 2>/dev/null | grep -q "RUNNING"; then
			token=$(lxc-attach -n "$LXC_NAME" -- grep -o 'token=[a-zA-Z0-9_-]*' /tmp/mitmweb.log 2>/dev/null | head -1 | cut -d= -f2)
		fi
	fi

	# Construct URL - only add token parameter if token exists
	local web_url="http://$router_ip:$web_port"
	local web_url_with_token="$web_url"
	if [ -n "$token" ]; then
		web_url_with_token="$web_url/?token=$token"
	fi

	cat <<EOF
{
	"token": "$token",
	"web_url": "$web_url",
	"web_url_with_token": "$web_url_with_token"
}
EOF
}

# RPCD list method
case "$1" in
	list)
		cat <<EOF
{
	"get_status": {},
	"get_config": {},
	"get_transparent_config": {},
	"get_whitelist_config": {},
	"get_filtering_config": {},
	"get_all_config": {},
	"get_stats": {},
	"get_requests": {"limit": 50, "category": "all"},
	"get_top_hosts": {"limit": 20},
	"get_ca_info": {},
	"get_web_token": {},
	"service_start": {},
	"service_stop": {},
	"service_restart": {},
	"firewall_setup": {},
	"firewall_clear": {},
	"set_config": {"key": "string", "value": "string"},
	"add_to_list": {"key": "string", "value": "string"},
	"remove_from_list": {"key": "string", "value": "string"},
	"clear_data": {}
}
EOF
		;;
	call)
		case "$2" in
			get_status)
				get_status
				;;
			get_config)
				get_config
				;;
			get_transparent_config)
				get_transparent_config
				;;
			get_whitelist_config)
				get_whitelist_config
				;;
			get_filtering_config)
				get_filtering_config
				;;
			get_all_config)
				get_all_config
				;;
			get_stats)
				get_stats
				;;
			get_requests)
				read -r input
				limit=$(echo "$input" | jsonfilter -e '@.limit' 2>/dev/null || echo "50")
				category=$(echo "$input" | jsonfilter -e '@.category' 2>/dev/null || echo "all")
				get_requests "$limit" "$category"
				;;
			get_top_hosts)
				read -r input
				limit=$(echo "$input" | jsonfilter -e '@.limit' 2>/dev/null || echo "20")
				get_top_hosts "$limit"
				;;
			get_ca_info)
				get_ca_info
				;;
			get_web_token)
				get_web_token
				;;
			service_start)
				service_start
				;;
			service_stop)
				service_stop
				;;
			service_restart)
				service_restart
				;;
			firewall_setup)
				firewall_setup
				;;
			firewall_clear)
				firewall_clear
				;;
			set_config)
				read -r input
				key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null)
				value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null)
				set_config "$key" "$value"
				;;
			add_to_list)
				read -r input
				key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null)
				value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null)
				add_to_list "$key" "$value"
				;;
			remove_from_list)
				read -r input
				key=$(echo "$input" | jsonfilter -e '@.key' 2>/dev/null)
				value=$(echo "$input" | jsonfilter -e '@.value' 2>/dev/null)
				remove_from_list "$key" "$value"
				;;
			clear_data)
				clear_data
				;;
			*)
				echo '{"error":"Unknown method"}'
				;;
		esac
		;;
	*)
		echo '{"error":"Unknown command"}'
		;;
esac
