#!/usr/bin/env bash
set -euo pipefail

# jsatcm backend 安装脚本：
# 1. 创建服务用户与目录
# 2. 安装 deploy 脚本
# 3. 安装 supervisor 配置
# 4. 准备 shared/app.env

if [ "$(id -u)" -ne 0 ]; then
  echo "请使用 root 执行，例如：sudo bash install.sh"
  exit 1
fi

company_root="/opt/inqai"
runtime_root="${company_root}/runtime"
product_root="${company_root}/products/jsatcm/backend"
shared_root="${product_root}/shared"
service_user="jsatcm-backend"
program_name="jsatcm-backend"
supervisor_conf="${runtime_root}/supervisor/supervisord.conf"
program_conf="${runtime_root}/supervisor/conf.d/${program_name}.conf"
env_example_target="${shared_root}/app.env.example"
env_target="${shared_root}/app.env"

if [ ! -d "${runtime_root}/bin" ] || [ ! -d "${runtime_root}/supervisor/conf.d" ]; then
  echo "缺少主机级运行环境。"
  echo "请先完成 clients/windows-wsl-teleport 主机 bootstrap。"
  exit 1
fi

if ! id -u "${service_user}" >/dev/null 2>&1; then
  useradd --system --home "${product_root}" --shell /usr/sbin/nologin "${service_user}"
fi

install -d -m 0755 \
  "${product_root}" \
  "${product_root}/downloads" \
  "${product_root}/logs" \
  "${product_root}/releases" \
  "${shared_root}" \
  "${shared_root}/data" \
  "${shared_root}/.llama_index_storage"

chown -R "${service_user}:${service_user}" "${product_root}"

cat >"${env_example_target}" <<'EOF'
# jsatcm backend 运行环境示例。
# 复制为 /opt/inqai/products/jsatcm/backend/shared/app.env 后修改。

APP_ENV=production
APP_TIMEZONE=Asia/Shanghai
HOST=0.0.0.0
PORT=8000

DATABASE_URL=sqlite:////opt/inqai/products/jsatcm/backend/shared/data/tcm_metrics.db
INDEX_STORAGE_DIR=/opt/inqai/products/jsatcm/backend/shared/.llama_index_storage
MINIAPP_ATTACHMENT_DIR=/opt/inqai/products/jsatcm/backend/shared/data/preconsultation_attachments

OPENAI_API_KEY=
OPENAI_API_BASE=
LLM_API_KEY=
LLM_API_BASE=
LLM_MODEL=gpt-4o-mini
EMBED_API_KEY=
EMBED_API_BASE=
EMBED_MODEL=text-embedding-3-small
VISION_API_KEY=
VISION_API_BASE=
VISION_MODEL=qwen-vl-plus
ASR_API_KEY=
ASR_API_BASE=
ASR_MODEL=qwen3-asr-flash
PULSE_MODEL=qwen-plus
QINIU_ACCESS_KEY=
QINIU_SECRET_KEY=
QINIU_BUCKET=
QINIU_DOMAIN=
WECHAT_APP_ID=
WECHAT_APP_SECRET=
OPEN_API_APP_SECRETS_JSON=
OPEN_API_IP_WHITELIST=
OPEN_API_JWT_PRIVATE_KEY=
OPEN_API_JWT_PUBLIC_KEY=
EOF

if [ ! -f "${env_target}" ]; then
  install -m 0644 "${env_example_target}" "${env_target}"
fi

cat >"${runtime_root}/bin/deploy_jsatcm_backend.sh" <<'EOF'
#!/usr/bin/env bash
set -euo pipefail

if [ "$(id -u)" -ne 0 ]; then
  echo "请使用 root 执行 deploy_jsatcm_backend.sh"
  exit 1
fi

if [ "$#" -ne 3 ]; then
  echo "用法: deploy_jsatcm_backend.sh <version> <package_source> <sha256>"
  exit 1
fi

version="$1"
package_source="$2"
expected_sha256="$3"

company_root="/opt/inqai"
runtime_root="${company_root}/runtime"
product_root="${company_root}/products/jsatcm/backend"
release_root="${product_root}/releases"
release_dir="${release_root}/${version}"
release_tmp_dir="${release_root}/.${version}.tmp"
download_root="${product_root}/downloads"
download_name="$(basename "${package_source%%\?*}")"
download_file="${download_root}/${download_name}"
temp_file="$(mktemp)"
supervisor_conf="${runtime_root}/supervisor/supervisord.conf"
app_user="jsatcm-backend"
program_name="jsatcm-backend"
ready_marker=".release-ready"

cleanup() {
  rm -f "$temp_file"
}

trap cleanup EXIT

install -d -m 0755 "$release_root" "$download_root"

is_release_ready() {
  local candidate="$1"
  [ -f "${candidate}/${ready_marker}" ] || return 1
  [ -x "${candidate}/start.sh" ] || return 1
  if [ -f "${candidate}/requirements.txt" ]; then
    [ -x "${candidate}/.venv/bin/python" ] || return 1
  fi
}

fetch_package() {
  if [ -f "$package_source" ]; then
    cp "$package_source" "$temp_file"
    return 0
  fi
  case "$package_source" in
    http://*|https://*)
      curl -fL "$package_source" -o "$temp_file"
      return 0
      ;;
  esac
  echo "不支持的 package_source: $package_source"
  exit 1
}

if [ -d "$release_dir" ] && is_release_ready "$release_dir"; then
  echo "版本已存在且完整: $release_dir"
else
  rm -rf "$release_tmp_dir"
  fetch_package
  actual_sha256="$(sha256sum "$temp_file" | awk '{print $1}')"
  if [ "$actual_sha256" != "$expected_sha256" ]; then
    echo "SHA256 校验失败"
    echo "期望: $expected_sha256"
    echo "实际: $actual_sha256"
    exit 1
  fi

  install -d -m 0755 "$release_tmp_dir"

  case "$download_name" in
    *.zip)
      unzip -q "$temp_file" -d "$release_tmp_dir"
      ;;
    *.tar.gz|*.tgz)
      tar -xzf "$temp_file" -C "$release_tmp_dir"
      ;;
    *)
      echo "不支持的包格式: $download_name"
      exit 1
      ;;
  esac

  if [ ! -f "${release_tmp_dir}/start.sh" ]; then
    echo "发布包缺少 start.sh"
    exit 1
  fi

  install -m 0644 "$temp_file" "$download_file"
  chmod 0755 "${release_tmp_dir}/start.sh"
  ln -sfn "${env_target}" "${release_tmp_dir}/.env"

  chown -R "${app_user}:${app_user}" "$release_tmp_dir"

  if [ -f "${release_tmp_dir}/requirements.txt" ]; then
    runuser -u "$app_user" -- python3 -m venv "${release_tmp_dir}/.venv"
    runuser -u "$app_user" -- "${release_tmp_dir}/.venv/bin/pip" install --upgrade pip
    if [ -d "${release_tmp_dir}/wheelhouse" ]; then
      runuser -u "$app_user" -- "${release_tmp_dir}/.venv/bin/pip" install \
        --no-index \
        --find-links "${release_tmp_dir}/wheelhouse" \
        -r "${release_tmp_dir}/requirements.txt"
    else
      runuser -u "$app_user" -- "${release_tmp_dir}/.venv/bin/pip" install -r "${release_tmp_dir}/requirements.txt"
    fi
  fi

  touch "${release_tmp_dir}/${ready_marker}"
  chown "${app_user}:${app_user}" "${release_tmp_dir}/${ready_marker}"
  rm -rf "$release_dir"
  mv "$release_tmp_dir" "$release_dir"
fi

ln -sfn "$release_dir" "${product_root}/current"

if supervisorctl -c "$supervisor_conf" status "$program_name" 2>/dev/null | grep -q RUNNING; then
  supervisorctl -c "$supervisor_conf" restart "$program_name"
else
  supervisorctl -c "$supervisor_conf" start "$program_name"
fi

for _ in $(seq 1 30); do
  status="$(supervisorctl -c "$supervisor_conf" status "$program_name" 2>/dev/null || true)"
  if printf '%s\n' "$status" | grep -q "RUNNING"; then
    printf '%s\n' "$status"
    break
  fi
  sleep 1
done

if ! supervisorctl -c "$supervisor_conf" status "$program_name" | grep -q "RUNNING"; then
  echo "jsatcm-backend 未成功进入 RUNNING。"
  tail -n 100 "${product_root}/logs/jsatcm-backend.stderr.log" || true
  exit 1
fi
EOF

chmod 0755 "${runtime_root}/bin/deploy_jsatcm_backend.sh"

cat >"${program_conf}" <<'EOF'
[program:jsatcm-backend]
command=/bin/bash -lc 'test -x /opt/inqai/products/jsatcm/backend/current/start.sh || exit 0; cd /opt/inqai/products/jsatcm/backend/current && exec ./start.sh'
directory=/opt/inqai/products/jsatcm/backend
user=jsatcm-backend
autostart=true
autorestart=unexpected
exitcodes=0
priority=20
stdout_logfile=/opt/inqai/products/jsatcm/backend/logs/jsatcm-backend.stdout.log
stderr_logfile=/opt/inqai/products/jsatcm/backend/logs/jsatcm-backend.stderr.log
EOF

if supervisorctl -c "${supervisor_conf}" status >/dev/null 2>&1; then
  supervisorctl -c "${supervisor_conf}" reread >/dev/null || true
  supervisorctl -c "${supervisor_conf}" update >/dev/null || true
fi

echo "jsatcm backend 产品配置已安装。"
echo "环境文件：${env_target}"
echo "发布命令：sudo ${runtime_root}/bin/deploy_jsatcm_backend.sh <version> <url> <sha256>"
