#!/bin/bash
### MusicMate lifecycle script (Python 版，fnOS Debian12 自带 python3)
### - strict error handling
### - use lsof + pkill (not fuser — psmisc may be missing)
### - exec python3 so PID in PID_FILE is the actual server process
set -euo pipefail

LOG_FILE="${TRIM_PKGVAR}/info.log"
PID_FILE="${TRIM_PKGVAR}/app.pid"

# 读取持久化的向导端口（config_callback/install_callback 写入 $TRIM_PKGETC/config.conf）
# 注意：不能 source 整个 config.conf——其中 ai_endpoint 等值可能含 &、空格等 shell
# 特殊字符，source 会破坏环境或产生副作用；只 grep 提取 wizard_app_port 行。
PORT=""
if [ -r "${TRIM_PKGETC}/config.conf" ]; then
    PORT="$(grep -E '^wizard_app_port=' "${TRIM_PKGETC}/config.conf" 2>/dev/null | head -1 | cut -d= -f2- | tr -d '[:space:]')"
fi
PORT="${PORT:-4534}"

CMD="python3 ${TRIM_APPDEST}/server.py"

log_msg() {
    echo "$(date '+%Y-%m-%d %H:%M:%S') - $1" >> "${LOG_FILE}"
}

# Clean up zombie MusicMate server processes（只清理自身，避免误杀占用同端口的其他应用）
cleanup_port() {
    pkill -TERM -f "musicmate/server\\.py" 2>/dev/null || true
    sleep 0.5
    pkill -KILL -f "musicmate/server\\.py" 2>/dev/null || true
}

check_process() {
    local pid=$1
    if kill -0 "${pid}" 2>/dev/null; then
        return 0
    else
        return 1
    fi
}

status() {
    if [ -f "${PID_FILE}" ]; then
        local pid
        pid=$(head -n 1 "${PID_FILE}" | tr -d '[:space:]')
        if check_process "${pid}"; then
            return 0
        else
            rm -f "${PID_FILE}"
        fi
    fi
    return 1
}

start_process() {
    if status; then
        return 0
    fi
    log_msg "Starting process on port ${PORT} ..."
    cleanup_port
    sleep 0.3
    PORT="${PORT}" TRIM_PKGETC="${TRIM_PKGETC}" TRIM_PKGVAR="${TRIM_PKGVAR}" bash -c "exec ${CMD}" >> "${LOG_FILE}" 2>&1 &
    local pid=$!
    printf "%s" "${pid}" > "${PID_FILE}"
    log_msg "pid=${pid}"
    sleep 1
    if ! check_process "${pid}"; then
        echo "Failed to start MusicMate server, see ${LOG_FILE}" > "${TRIM_TEMP_LOGFILE}"
        return 1
    fi
    return 0
}

stop_process() {
    log_msg "Stopping process ..."

    if [ -r "${PID_FILE}" ]; then
        local pid
        pid=$(head -n 1 "${PID_FILE}" | tr -d '[:space:]')

        log_msg "pid=${pid}"
        if ! check_process "${pid}"; then
            rm -f "${PID_FILE}"
            log_msg "remove pid file (process not exist)"
            return
        fi

        log_msg "send TERM signal to PID:${pid}..."
        kill -TERM "${pid}" >> "${LOG_FILE}" 2>&1

        local count=0
        while check_process "${pid}" && [ $count -lt 10 ]; do
            sleep 1
            count=$((count + 1))
            log_msg "waiting process terminal... (${count}s/10s)"
        done

        if check_process "${pid}"; then
            log_msg "send KILL signal to PID:${pid}..."
            kill -KILL "${pid}"
            sleep 1
        fi
        rm -f "${PID_FILE}"
    fi

    return 0
}

case "$1" in
start)
    # run start command. exit 0 if success, exit 1 if failed
    start_process
    ;;
stop)
    # run stop command. exit 0 if success, exit 1 if failed
    stop_process
    ;;
status)
    # check application status command. exit 0 if running, exit 3 if not running
    if status; then
        exit 0
    else
        exit 3
    fi
    ;;
*)
    echo "Unknown command: $1" > "${TRIM_TEMP_LOGFILE:-/dev/null}" 2>/dev/null || true
    exit 1
    ;;
esac
