#!/bin/sh
# tcblock_daemon - 常驻调度器；不依赖 BusyBox crond 或其 cron 目录差异。
. /etc/PG.conf

APPNAME=tcblock
CONFDIR="${PGETC}/App/${APPNAME}"
APPCONF="${CONFDIR}/tcblock.conf"
RAMROOT="/usr/ramdisk/app/${APPNAME}"
PIDFILE="${RAMROOT}/state/daemon.pid"
# 调度、MD5 与上次检查均可从平台/配置重建，避免高频写入 flash。
SYNCFILE="${CONFDIR}/sync.state"
STATEFILE="${RAMROOT}/state/daemon.state"

valid_num() { case "$1" in ''|*[!0-9]*) return 1;; *) return 0;; esac; }

# 配置按键读取 + 白名单(不 source,理由见 run_loop 内注释)
conf_get() { [ -f "${APPCONF}" ] && grep "^$1=" "${APPCONF}" 2>/dev/null | tail -1 | cut -d'=' -f2-; }
in_set()   { for _x in $2; do [ "$1" = "${_x}" ] && { echo "$1"; return; }; done; echo "$3"; }

last_value() { grep "^$1=" "$2" 2>/dev/null | tail -1 | cut -d= -f2; }
set_state() {
	tmp="${STATEFILE}.tmp.$$"
	{ grep -v "^$1=" "${STATEFILE}" 2>/dev/null; printf "%s=%s\n" "$1" "$2"; } > "${tmp}" && mv -f "${tmp}" "${STATEFILE}"
}


run_loop()
{
	mkdir -p "${RAMROOT}/state" "${CONFDIR}"
	echo $$ > "${PIDFILE}"
	# 🔴 INT/TERM 必须真的退出,不能只删 PID 文件
	# 若只删文件不退出:本进程还在 while 循环里跑,但 PIDFILE 已没了 →
	# 下一次 appctrl start 的 daemon_alive 判为"没在跑" → 再拉起一个 →
	# 双实例并存,同步被触发两次(多耗一次订阅配额)。
	# 与 tcblock_sync 里锁的 trap 是同一类问题,一并按"释放+退出"处理。
	trap 'rm -f "${PIDFILE}"' EXIT
	trap 'rm -f "${PIDFILE}"; exit 0' INT TERM
	while :; do
		# 每轮重新读取持久配置，Web 保存后无需重启守护进程。
		# 🔴 按键读取 + 白名单,绝不 source:conf 值一旦进入 shell 解析器就是 root 执行,
		#    历史脏配置/手工编辑/升级异常都能绕过 WebUI 的写入白名单。
		enable=$(in_set "$(conf_get enable)" "0 1" "0")
		interval=$(conf_get interval | tr -cd '0-9' | cut -c1-9)
		valid_num "${interval}" || interval=1440
		[ "${interval}" -lt 5 ] && interval=5
		now=$(date +%s)
		# 失败也推进尝试时间，避免每分钟重复下载消耗配额。
		last=$(last_value sync_attempt "${STATEFILE}")
		[ -z "${last}" ] && last=$(last_value last_check "${SYNCFILE}")
		valid_num "${last}" || last=0
		if [ "${enable}" = "1" ] && [ $((now - last)) -ge $((interval * 60)) ]; then
			bin="${RAMROOT}/bin/tcblock_sync"; [ -x "${bin}" ] || bin="${PGPATH}/app/${APPNAME}/bin/tcblock_sync"
			set_state sync_attempt "${now}"
			sh "${bin}" sync >/dev/null 2>&1
		fi

		# 在线版本检查仍每天一次；自动更新是否执行由 updater 内的 autoupdate 配置决定。
		upd_last=$(last_value update_check "${STATEFILE}")
		valid_num "${upd_last}" || upd_last=0
		if [ $((now - upd_last)) -ge 86400 ]; then
			upd="${RAMROOT}/bin/tcblock_update"; [ -x "${upd}" ] || upd="${PGPATH}/app/${APPNAME}/bin/tcblock_update"
			sh "${upd}" check >/dev/null 2>&1
			set_state update_check "${now}"
		fi
		sleep 60
	done
}

case "$1" in
	daemon|"") run_loop ;;
	*) echo "usage: tcblock_daemon daemon"; exit 1 ;;
esac
