#!/bin/bash
. /lib/functions.sh
. /usr/share/openclash-kejibear/uci.sh

[ -e "/etc/config/ucitrack" ] && {
uci -q delete ucitrack.@openclash_kejibear[-1]
uci -q add ucitrack openclash_kejibear
uci -q set ucitrack.@openclash_kejibear[-1].init=openclash-kejibear
uci -q commit ucitrack
}
uci -q delete firewall.openclash_kejibear
uci -q set firewall.openclash_kejibear=include
uci -q set firewall.openclash_kejibear.type=script
uci -q set firewall.openclash_kejibear.path=/var/etc/openclash-kejibear.include
[ -n "$(command -v fw4)" ] || uci -q set firewall.openclash_kejibear.reload=1
uci -q commit firewall

mkdir -p /etc/openclash-kejibear/config
mkdir -p /etc/openclash-kejibear/proxy_provider
mkdir -p /etc/openclash-kejibear/rule_provider
mkdir -p /etc/openclash-kejibear/core
mkdir -p /etc/openclash-kejibear/history
mkdir -p /usr/share/openclash-kejibear/backup/overwrite

mkdir -p /lib/upgrade/keep.d
cat > "/lib/upgrade/keep.d/luci-app-openclash-kejibear" <<-EOF
/etc/openclash-kejibear/
EOF

#Set Chnroute Format
FW4=$(command -v fw4)
if [ -n "$FW4" ]; then
	#v4
	if [ -z "$(cat "/etc/openclash-kejibear/china_ip_route.ipset" |grep "define china_ip_route")" ]; then
		echo "define china_ip_route = {" >/tmp/china_ip_route.list
		awk '!/^$/&&!/^#/{printf("    %s,'" "'\n",$0)}' /etc/openclash-kejibear/china_ip_route.ipset >>/tmp/china_ip_route.list
		echo "}" >>/tmp/china_ip_route.list
		echo "add set inet fw4 kjx_cnroute { type ipv4_addr; flags interval; auto-merge; }" >>/tmp/china_ip_route.list
		echo 'add element inet fw4 kjx_cnroute $china_ip_route' >>/tmp/china_ip_route.list
	fi
	#v6
	if [ -z "$(cat "/etc/openclash-kejibear/china_ip6_route.ipset" |grep "define china_ip6_route")" ]; then
		echo "define china_ip6_route = {" >/tmp/china_ip6_route.list
		awk '!/^$/&&!/^#/{printf("    %s,'" "'\n",$0)}' /etc/openclash-kejibear/china_ip6_route.ipset >>/tmp/china_ip6_route.list
		echo "}" >>/tmp/china_ip6_route.list
		echo "add set inet fw4 kjx_cnroute6 { type ipv6_addr; flags interval; auto-merge; }" >>/tmp/china_ip6_route.list
		echo 'add element inet fw4 kjx_cnroute6 $china_ip6_route' >>/tmp/china_ip6_route.list
	fi
else
	#v4
	if [ -z "$(cat "/etc/openclash-kejibear/china_ip_route.ipset" |grep "create kjx_cnroute")" ]; then
		echo "create kjx_cnroute hash:net family inet hashsize 1024 maxelem 1000000" >/tmp/china_ip_route.list
		awk '!/^$/&&!/^#/{printf("add kjx_cnroute %s'" "'\n",$0)}' /etc/openclash-kejibear/china_ip_route.ipset >>/tmp/china_ip_route.list
	fi
	#v6
	if [ -z "$(cat "/etc/openclash-kejibear/china_ip6_route.ipset" |grep "create kjx_cnroute6")" ]; then
		echo "create kjx_cnroute6 hash:net family inet6 hashsize 1024 maxelem 1000000" >/tmp/china_ip6_route.list
		awk '!/^$/&&!/^#/{printf("add kjx_cnroute6 %s'" "'\n",$0)}' /etc/openclash-kejibear/china_ip6_route.ipset >>/tmp/china_ip6_route.list
	fi
fi
mv -f /tmp/china_ip_route.list /etc/openclash-kejibear/china_ip_route.ipset >/dev/null 2>&1
mv -f /tmp/china_ip6_route.list /etc/openclash-kejibear/china_ip6_route.ipset >/dev/null 2>&1

#Set Dashboard Secret
if [ -z "$(uci_get_config "dashboard_password")" ]; then
	uci -q set openclash_kejibear.config.dashboard_password="$(tr -cd 'a-zA-Z0-9' </dev/urandom 2>/dev/null| head -c8 || date +%N| md5sum |head -c8)"
fi

#Set Authentication
if [ -z "$(uci -q get openclash_kejibear.@authentication[0])" ]; then
	uci_name_tmp=$(uci -q add openclash_kejibear authentication)
	uci_set="uci -q set openclash_kejibear.$uci_name_tmp."
	${uci_set}enabled="1"
	${uci_set}username="Clash"
	${uci_set}password="$(tr -cd 'a-zA-Z0-9' </dev/urandom 2>/dev/null| head -c8 || date +%N| md5sum |head -c8)"
fi

#Set Core Model
source "/etc/openwrt_release"
case "${DISTRIB_ARCH}" in
	aarch64_*)
		CORE_ARCH="linux-arm64"
		;;
	armeb_*)
		CORE_ARCH="0"
		;;
	arm_cortex-a5|arm_cortex-a5[^0-9]*|arm_cortex-a7|arm_cortex-a7[^0-9]*|arm_cortex-a8*|arm_cortex-a9*|arm_cortex-a12*|arm_cortex-a15*|arm_cortex-a17*)
		CORE_ARCH="linux-armv7"
		;;
	arm_arm1176jzf-s*|arm_arm1136*|arm_mpcore*)
		CORE_ARCH="linux-armv6"
		;;
	arm*)
		CORE_ARCH="linux-armv5"
		;;
	i386_*)
		CORE_ARCH="linux-386"
		;;
	mips64el_*)
		CORE_ARCH="linux-mips64le"
		;;
	mips64_*)
		CORE_ARCH="linux-mips64"
		;;
	mips_*)
		CORE_ARCH="linux-mips-softfloat"
		;;
	mipsel_*)
		CORE_ARCH="linux-mipsle-softfloat"
		;;
	riscv64*)
		CORE_ARCH="linux-riscv64"
		;;
	loongarch64*|loongarch_*)
		CORE_ARCH="linux-loong64-abi2"
		;;
	x86_64)
		CORE_ARCH="linux-amd64-v1"
		;;
	*)
		CORE_ARCH="0"
		;;
esac
uci -q set openclash_kejibear.config.core_version="${CORE_ARCH}"

#Backup Resolvfile
if [ -n "$(uci -q get dhcp.@dnsmasq[0].resolvfile)" ]; then
   uci -q set openclash_kejibear.config.default_resolvfile=$(uci -q get dhcp.@dnsmasq[0].resolvfile)
fi

# Quic-go GSO Disable
current_kernel=$(uname -r | cut -d'-' -f1)
if [ "$(printf '%s\n' "$current_kernel" "6.6" | sort -V | head -n1)" != "$current_kernel" ]; then
   uci -q set openclash_kejibear.config.disable_quic_go_gso=1
fi

uci -q commit openclash_kejibear

#Backup
cp -f "/etc/config/openclash_kejibear" "/usr/share/openclash-kejibear/backup/openclash" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_rules.list" "/usr/share/openclash-kejibear/backup/openclash_custom_rules.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_rules_2.list" "/usr/share/openclash-kejibear/backup/openclash_custom_rules_2.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_hosts.list" "/usr/share/openclash-kejibear/backup/openclash_custom_hosts.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_fake_filter.list" "/usr/share/openclash-kejibear/backup/openclash_custom_fake_filter.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_domain_dns.list" "/usr/share/openclash-kejibear/backup/openclash_custom_domain_dns.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_domain_dns_policy.list" "/usr/share/openclash-kejibear/backup/openclash_custom_domain_dns_policy.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_proxy_server_dns_policy.list" "/usr/share/openclash-kejibear/backup/openclash_custom_proxy_server_dns_policy.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_fallback_filter.yaml" "/usr/share/openclash-kejibear/backup/openclash_custom_fallback_filter.yaml" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_sniffer.yaml" "/usr/share/openclash-kejibear/backup/openclash_custom_sniffer.yaml" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_localnetwork_ipv4.list" "/usr/share/openclash-kejibear/backup/openclash_custom_localnetwork_ipv4.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_localnetwork_ipv6.list" "/usr/share/openclash-kejibear/backup/openclash_custom_localnetwork_ipv6.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_chnroute_pass.list" "/usr/share/openclash-kejibear/backup/openclash_custom_chnroute_pass.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_chnroute6_pass.list" "/usr/share/openclash-kejibear/backup/openclash_custom_chnroute6_pass.list" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_firewall_rules.sh" "/usr/share/openclash-kejibear/backup/openclash_custom_firewall_rules.sh" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/custom/openclash_custom_overwrite.sh" "/usr/share/openclash-kejibear/backup/openclash_custom_overwrite.sh" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/china_ip_route.ipset" "/usr/share/openclash-kejibear/backup/china_ip_route.ipset" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/china_ip6_route.ipset" "/usr/share/openclash-kejibear/backup/china_ip6_route.ipset" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/overwrite/default" "/usr/share/openclash-kejibear/backup/overwrite/default" >/dev/null 2>&1
cp -f "/etc/openclash-kejibear/rule_provider/oc-cn-domain.mrs" "/usr/share/openclash-kejibear/backup/oc-cn-domain.mrs" >/dev/null 2>&1

#Restore
if [ -f "/tmp/openclash-kejibear.bak" ]; then
	#delete old geosite database first
	if [ "/etc/openclash-kejibear/GeoSite.dat" -nt "/tmp/openclash-kejibear/GeoSite.dat" ]; then
		rm -rf "/tmp/openclash-kejibear/GeoSite.dat" >/dev/null 2>&1
	fi
	#delete error china_ip_route first
	if [ -n "$FW4" ]; then
		if [ -z "$(cat "/tmp/openclash-kejibear/china_ip_route.ipset" |grep "define china_ip_route")" ]; then
			rm -f "/tmp/openclash-kejibear/china_ip_route.ipset" >/dev/null 2>&1
			rm -f "/tmp/openclash-kejibear/china_ip6_route.ipset" >/dev/null 2>&1
		fi
	else
		if [ -z "$(cat "/tmp/openclash-kejibear/china_ip_route.ipset" |grep "create kjx_cnroute")" ]; then
			rm -f "/tmp/openclash-kejibear/china_ip_route.ipset" >/dev/null 2>&1
			rm -f "/tmp/openclash-kejibear/china_ip6_route.ipset" >/dev/null 2>&1
		fi
	fi
	mv -f "/tmp/openclash-kejibear.bak" "/etc/config/openclash_kejibear" >/dev/null 2>&1
	cp -rf "/tmp/openclash-kejibear/." "/etc/openclash-kejibear/" >/dev/null 2>&1
	#ui
	if [ -d "/tmp/openclash-kejibear_ui/" ]; then
		if [ -d "/tmp/openclash-kejibear_ui/metacubexd/" ] || [ -d "/tmp/openclash-kejibear_ui/zashboard/" ] || [ -d "/tmp/openclash-kejibear_ui/yacd/" ] || [ -d "/tmp/openclash-kejibear_ui/dashboard/" ]; then
			rm -rf "/usr/share/openclash-kejibear/ui/" >/dev/null 2>&1
			cp -rf "/tmp/openclash-kejibear_ui/." "/usr/share/openclash-kejibear/ui/" >/dev/null 2>&1
		fi
		rm -rf "/tmp/openclash-kejibear_ui/" >/dev/null 2>&1
	fi
	#pac
	if [ -d "/tmp/pac/" ]; then
		rm -rf "/www/luci-static/resources/openclash-kejibear/pac/" >/dev/null 2>&1
		cp -rf "/tmp/pac/." "/www/luci-static/resources/openclash-kejibear/pac/" >/dev/null 2>&1
		rm -rf "/tmp/pac/" >/dev/null 2>&1
	fi
	#oc-domain
	if [ -f "/etc/openclash-kejibear/rule_provider/oc-cn-domain.mrs" ]; then
		cp -f "/usr/share/openclash-kejibear/backup/oc-cn-domain.mrs" "/etc/openclash-kejibear/rule_provider/oc-cn-domain.mrs" >/dev/null 2>&1
	fi
	rm -rf "/etc/openclash-kejibear/openclash" >/dev/null 2>&1
	rm -rf "/tmp/openclash-kejibear" >/dev/null 2>&1
	rm -rf "/tmp/openclash-kejibear.bak" >/dev/null 2>&1
	#old version files
	rm -rf "/etc/openclash-kejibear/fake_filter.list" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/openclash_servers_fake_filter.conf" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/core/clash" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/core/clash_tun" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/accelerated-domains.china.conf" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/custom/openclash_force_sniffing_domain.yaml" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/custom/openclash_sniffing_ports_filter.yaml" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/custom/openclash_sniffing_port_filter.yaml" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/custom/openclash_sniffing_domain_filter.yaml" >/dev/null 2>&1
	rm -rf "/etc/openclash-kejibear/backup" >/dev/null 2>&1
fi

if [ -f "/usr/lib/lua/luci/model/network.lua" ]; then
   sed -i '/Kejibear Append/,/Kejibear Append End/d' "/usr/lib/lua/luci/model/network.lua" >/dev/null 2>&1
   cat >> "/usr/lib/lua/luci/model/network.lua" << EOF
-------------- Kejibear Append --------------

function get_all_wan_networks(self)
	local k, v
	local wan_nets = { }
	local route_statuses = self:get_all_status_by_route("0.0.0.0", 0)

	for k, v in pairs(route_statuses) do
		wan_nets[#wan_nets+1] = network(k, v.proto)
	end

	return wan_nets
end

function get_all_wan6_networks(self)
	local k, v
	local wan6_nets = { }
	local route_statuses = self:get_all_status_by_route("::", 0)

	for k, v in pairs(route_statuses) do
		wan6_nets[#wan6_nets+1] = network(k, v.proto)
	end

	return wan6_nets
end

function get_all_status_by_route(self, addr, mask)
	local route_statuses = { }
	local _, object
	for _, object in ipairs(utl.ubus()) do
		local net = object:match("^network%.interface%.(.+)")
		if net then
			local s = utl.ubus(object, "status", {})
			if s and s.route then
				local rt
				for _, rt in ipairs(s.route) do
					if not rt.table and rt.target == addr and rt.mask == mask then
						route_statuses[net] = s
					end
				end
			end
		end
	end

	return route_statuses
end

-------------- Kejibear Append End --------------
EOF
fi

# ---------------------------------------------------------------------------
# C4：一次性迁移 —— 清除 oixCloud 存量键
#
# 为什么必须清：uci_get_config 优先读 @overwrite[0]，只要 oix_token 还在，旧配置
# 就会继续把内核强换成 Oix。源码侧已经切断，但存量配置不会自己消失。
# 顺带删掉 keep.d 里上游包名留下的旧文件（K1 改名后由新文件接管）。
# ---------------------------------------------------------------------------
for _kjx_key in oix_token oix_params oix_email oix_passwd oix_checkin \
                oix_checkin_interval oix_checkin_multiple oix_default_params \
                oix_show_info_page; do
	uci -q delete "openclash_kejibear.config.${_kjx_key}" >/dev/null 2>&1
	uci -q delete "openclash_kejibear.@overwrite[0].${_kjx_key}" >/dev/null 2>&1
done
uci -q commit openclash_kejibear >/dev/null 2>&1
rm -f /lib/upgrade/keep.d/luci-app-openclash >/dev/null 2>&1
rm -rf /tmp/oix_checkin /tmp/oix_info /tmp/openclash-kejibear_oix_version.json >/dev/null 2>&1

# ---------------------------------------------------------------------------
# C15(e)：存量归位 —— 托管订阅生效时把日志等级拉回 info
#
# 升级前把等级设成 debug/trace 的用户，升级后那份设置还在，而 debug 会把每一次
# DNS 解析的域名写进日志流。托管态一律归位；非托管用户的设置不动。
# ---------------------------------------------------------------------------
. /usr/share/openclash-kejibear/kjx.sh 2>/dev/null
if command -v kjx_managed_name >/dev/null 2>&1 && [ -n "$(kjx_managed_name 2>/dev/null)" ]; then
	_kjx_lvl=$(uci -q get openclash_kejibear.config.log_level 2>/dev/null)
	case "$_kjx_lvl" in
		debug|trace|DEBUG|TRACE)
			uci -q set openclash_kejibear.config.log_level='info'
			uci -q commit openclash_kejibear
			;;
	esac
	_kjx_lvl=$(uci -q get openclash_kejibear.@overwrite[0].log_level 2>/dev/null)
	case "$_kjx_lvl" in
		debug|trace|DEBUG|TRACE)
			uci -q set openclash_kejibear.@overwrite[0].log_level='info'
			uci -q commit openclash_kejibear
			;;
	esac
fi

# C3③/N-GATE④：装上每小时那条定时任务（续期登录凭据 + 刷新客服口令散列）。
# 客服口令按「用户 + 自然日」派生、每天零点就变，所以这条不能跟着配置拉取降到一天一次。
# 它刻意不带 #openclash-kejibear-cron-task 标记 —— 带了的话停服务会把它一起删掉，
# 而这条必须在服务停止期间照常跑。
command -v kjx_cron_hourly_ensure >/dev/null 2>&1 && kjx_cron_hourly_ensure >/dev/null 2>&1

#set uhttpd && HTTP_MAX_CONTENT for large file edit
uci -q set uhttpd.main.max_requests=50
uci -q set uhttpd.main.max_connections=100
uci -q set uhttpd.main.script_timeout=3600
uci -q commit uhttpd
sed -i '/.*kB maximum content size*/c\HTTP_MAX_CONTENT = 1024*10240		-- 100 kB maximum content size' /usr/lib/lua/luci/http.lua >/dev/null 2>&1
sed -i '/.*kB maximum content size*/c\export let HTTP_MAX_CONTENT = 1024*10240;		// 100 kB maximum content size' /usr/share/ucode/luci/http.uc >/dev/null 2>&1

/etc/init.d/uhttpd restart >/dev/null 2>&1

rm -rf /tmp/luci-indexcache /tmp/luci-indexcache.* /var/luci-indexcache /var/luci-indexcache.* >/dev/null 2>&1
rm -rf /tmp/luci-modulecache /var/luci-modulecache >/dev/null 2>&1
exit 0
