#!/bin/sh /etc/rc.common
# Cloudreve init script
#   程序、配置文件、数据库都放在用户所选外置盘的 <盘>/Configs/cloudreve/ 下，不占路由器闪存
#
# 实测修正（Cloudreve V4.19.1，aarch64）：
#   1) 必须用子命令启动：cloudreve server -c <conf>
#      裸跑 `cloudreve -c conf` 只会打印 usage 然后退出
#   2) V4 不认 [Database] 段，数据库固定在「程序所在目录/data/cloudreve.db」
#      所以不写 DBFile，也不设 workingdir，让它自己定位
#   3) conf.ini 只在缺失/残缺时生成，避免每次启动都换 SessionSecret 导致掉登录
#   4) 没配存储盘就自动挑一块外置盘，挑不到就拒绝启动并写日志，
#      不回落系统闪存（/root、/tmp 都不是合法的数据落点）

USE_PROCD=1
START=99
STOP=15

CONF="cloudreve"
LOG_PATH="/var/log/cloudreve.log"
CONFIGS_DIR="Configs"
APP_SUBDIR="cloudreve"

uci_get() {
	local ret=$(uci -q get ${CONF}.@cloudreve[0].${1} 2>/dev/null)
	echo ${ret:=$2}
}

log_msg() {
	mkdir -p /var/log 2>/dev/null
	echo "[$(date '+%Y-%m-%d %H:%M:%S')] $1" >> $LOG_PATH
}

# 存储盘：先用 LuCI 里选的；留空则按官方策略自动挑一块外置盘；
# 都拿不到就返回空串，由调用方拒绝启动
resolve_storage() {
	local root=$(uci_get root_path "")
	if [ -n "$root" ]; then
		echo "$root"
		return 0
	fi
	local auto=$(sh /usr/libexec/cloudreve/detect_base.sh 2>/dev/null)
	if [ -n "$auto" ]; then
		echo "$auto"
		return 0
	fi
	echo ""
	return 1
}

resolve_app_dir() {
	local storage=$(resolve_storage)
	[ -n "$storage" ] || return 1
	echo "${storage}/${CONFIGS_DIR}/${APP_SUBDIR}"
}

# 配置文件路径：<root>/Configs/cloudreve/cloudreve.ini
resolve_conf() {
	local app_dir=$(resolve_app_dir)
	[ -n "$app_dir" ] || { echo ""; return 1; }
	echo "${app_dir}/cloudreve.ini"
}

rand_str() {
	local s=$(head -c 32 /dev/urandom 2>/dev/null | md5sum 2>/dev/null | head -c 32)
	[ -z "$s" ] && s=$(head -c 32 /dev/urandom 2>/dev/null | tr -dc 'a-f0-9' | head -c 32)
	[ -z "$s" ] && s="0123456789abcdef0123456789abcdef"
	echo "$s"
}

write_conf() {
	local conf_path="$1"
	local listen="$2"
	cat > "$conf_path" <<EOF
[System]
Debug = false
Mode = master
Listen = ${listen}
SessionSecret = $(rand_str)
HashIDSalt = $(rand_str)
LogLevel = info
EOF
}

start_service() {
	config_load "$CONF"

	local app_dir=$(resolve_app_dir)
	if [ -z "$app_dir" ]; then
		log_msg "启动失败：没有可用的外置存储盘。请在 LuCI 的「程序根目录」里选一块外置硬盘（需位于 /mnt 或 /media 下、可写、剩余空间至少 1GiB）"
		return 1
	fi

	local bin="${app_dir}/cloudreve"
	local conf_file="${app_dir}/cloudreve.ini"
	local data_dir="${app_dir}/data"

	mkdir -p "$app_dir" 2>/dev/null
	mkdir -p "$data_dir" 2>/dev/null
	chmod 700 "$data_dir" 2>/dev/null

	if [ ! -f "$bin" ]; then
		log_msg "启动失败：在 $bin 找不到程序本体，请先在 LuCI 页面点「下载最新二进制」"
		return 1
	fi

	chmod 755 "$bin" 2>/dev/null
	chown root:root "$bin" 2>/dev/null

	local listen_port=$(uci_get listen_port "5212")
	local listen="0.0.0.0:${listen_port}"

	# conf.ini 只在不存在、为空、或缺少 HashIDSalt（旧 v3 格式）时重建
	if [ ! -s "$conf_file" ] || ! grep -q "HashIDSalt" "$conf_file" 2>/dev/null; then
		write_conf "$conf_file" "$listen"
		log_msg "已生成配置文件：$conf_file"
	else
		sed -i "s|^Listen[ \t]*=.*|Listen = ${listen}|" "$conf_file" 2>/dev/null
	fi

	log_msg "正在启动 Cloudreve：程序=$bin，配置=$conf_file，监听=$listen，数据目录=$data_dir"

	procd_open_instance
	procd_set_param command "$bin"
	procd_append_param command server
	procd_append_param command -c "$conf_file"
	procd_set_param limits core="unlimited"
	procd_set_param limits nofile="1000000 1000000"
	procd_set_param stdout 1
	procd_set_param stderr 1
	procd_set_param respawn
	procd_close_instance

	return 0
}

stop_service() {
	log_msg "正在停止 Cloudreve"
}

reload_service() {
	restart
}

service_triggers() {
	procd_add_reload_trigger "$CONF"
}
