#!/bin/sh
# Trae2api CN M·Desk 启动脚本
# - socket 模式：uvicorn 直接监听 ${MDESK_SOCKET}，ASGI 中间件剥掉 /apps/<id> 前缀
# - port 模式：uvicorn 监听 ${MDESK_PORT}
# 内置 Python 先复制到可写的 var 目录再执行。
set -eu

ROOT="$(CDPATH= cd -- "$(dirname -- "$0")/.." && pwd -P)"

case "$(uname -m)" in
    x86_64|amd64)  ARCH=x86_64 ;;
    aarch64|arm64) ARCH=aarch64 ;;
    *) echo "unsupported arch: $(uname -m)" >&2; exit 1 ;;
esac

: "${MDESK_DATA_DIR:?MDESK_DATA_DIR is required}"
: "${MDESK_VAR_DIR:?MDESK_VAR_DIR is required}"

umask 077
export PYTHONUTF8=1
export PYTHONDONTWRITEBYTECODE=1

mkdir -p "$MDESK_DATA_DIR/data" "$MDESK_DATA_DIR/logs" 2>/dev/null || true
LOG_DIR="${MDESK_LOG_DIR:-$MDESK_DATA_DIR/logs}"
if ! mkdir -p "$LOG_DIR" 2>/dev/null || ! : >>"$LOG_DIR/launcher.log" 2>/dev/null; then
    LOG_DIR="$MDESK_DATA_DIR/logs"
    mkdir -p "$LOG_DIR" 2>/dev/null || true
fi
LOG="$LOG_DIR/launcher.log"
log() {
    printf '%s %s\n' "$(date '+%Y-%m-%d %H:%M:%S')" "$*" >>"$LOG" 2>/dev/null || true
}
log "start arch=$ARCH port=${MDESK_PORT:-} socket=${MDESK_SOCKET:-} base=${MDESK_BASE_PATH:-} app=$ROOT"

PY_SRC="$ROOT/runtime/$ARCH/python/bin/python3.11"
if [ ! -f "$PY_SRC" ]; then
    log "missing python runtime: $PY_SRC"
    echo "python runtime missing for $ARCH: $PY_SRC" >&2
    exit 1
fi

export PYTHONHOME="$ROOT/runtime/$ARCH/python"

PY="$MDESK_VAR_DIR/python3.11-$ARCH"
if [ ! -x "$PY" ] || [ "$PY_SRC" -nt "$PY" ]; then
    log "copy python -> $PY"
    mkdir -p "$MDESK_VAR_DIR"
    cp "$PY_SRC" "$PY.tmp.$$"
    chmod +x "$PY.tmp.$$"
    mv "$PY.tmp.$$" "$PY"
fi

if ! "$PY" -c 'pass' >/dev/null 2>&1; then
    log "copied python failed, fallback to app root"
    PY="$PY_SRC"
    chmod +x "$PY" 2>/dev/null || true
fi
if [ ! -x "$PY" ]; then
    log "cannot execute python: $PY"
    echo "cannot execute python: $PY" >&2
    exit 1
fi
log "python=$PY"

SITE="$MDESK_VAR_DIR/pysite-$ARCH"
STAMP="$SITE/.stamp"
WANT="${MDESK_APP_VERSION:-dev}"
if [ ! -f "$STAMP" ] || [ "$(cat "$STAMP" 2>/dev/null)" != "$WANT" ]; then
    log "extract wheels -> $SITE"
    rm -rf "$SITE"
    mkdir -p "$SITE"
    "$PY" - "$ROOT/wheels/$ARCH" "$SITE" <<'PY'
import pathlib
import sys
import zipfile

src = pathlib.Path(sys.argv[1])
dst = pathlib.Path(sys.argv[2])
for wheel in sorted(src.glob("*.whl")):
    with zipfile.ZipFile(wheel) as archive:
        archive.extractall(dst)
PY
    printf '%s' "$WANT" > "$STAMP"
fi

ENV_FILE="$MDESK_DATA_DIR/.env"
if [ ! -s "$ENV_FILE" ]; then
    KEY="$("$PY" -c 'import secrets; print(secrets.token_urlsafe(24))')"
    log "generate $ENV_FILE and api-key.txt"
    "$PY" - "$ROOT/config/default.env" "$ENV_FILE" "$KEY" "$MDESK_DATA_DIR" <<'PY'
import pathlib
import sys

template, destination, key, data_dir = sys.argv[1:]
text = pathlib.Path(template).read_text(encoding="utf-8")
text = text.replace("__RELAY_API_KEY__", key).replace("__DATA_DIR__", data_dir)
pathlib.Path(destination).write_text(text, encoding="utf-8")
PY
    chmod 600 "$ENV_FILE"
    printf 'RELAY_API_KEYS=%s\n' "$KEY" > "$MDESK_DATA_DIR/api-key.txt"
    chmod 600 "$MDESK_DATA_DIR/api-key.txt"
fi

export MDESK_DATA_DIR
export TRAE_ENV_PATH="$MDESK_DATA_DIR/.env"
export TRAE_USAGE_RECORDS_PATH="$MDESK_DATA_DIR/data/usage_records.json"
export TRAE_USAGE_STATS_PATH="$MDESK_DATA_DIR/data/usage_stats.json"
export PYTHONPATH="$SITE:$ROOT/app"

cd "$MDESK_DATA_DIR"

if [ -n "${MDESK_PORT:-}" ]; then
    log "mode=port port=$MDESK_PORT"
    exec "$PY" "$ROOT/bin/run_app.py"
fi

if [ -n "${MDESK_SOCKET:-}" ]; then
    : "${MDESK_BASE_PATH:?MDESK_BASE_PATH is required in socket mode}"
    log "mode=socket socket=$MDESK_SOCKET base=$MDESK_BASE_PATH"
    rm -f "$MDESK_SOCKET" 2>/dev/null || true
    exec "$PY" "$ROOT/bin/run_app.py"
fi

log "neither MDESK_PORT nor MDESK_SOCKET is set"
echo "neither MDESK_PORT nor MDESK_SOCKET is set" >&2
exit 1
