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

# 将当前数据库导出并加密后推送到“私有数据仓库”（Gitea）。
# - 不把明文 SQL 放入 git
# - 数据仓库建议单独授权/独立权限
#
# 依赖：mysqldump / mysql / openssl / gzip / git
#
# 用法：
#   1) 设置密钥（不要写入仓库）：
#      export SAASSHOP_DB_SNAPSHOT_KEY='你的强密码'
#   2) 可选设置数据仓库地址（若不设则从 /app/working.secret/saasshop_data_repo_ssh 读取）：
#      export SAASSHOP_DATA_REPO_SSH='git@git.xxx:owner/saasshop-data(.wiki).git'
#   3) 执行：
#      bash scripts/db_snapshot_publish.sh

REPO_DIR=$(cd "$(dirname "$0")/.." && pwd)
cd "$REPO_DIR"

DATA_REPO_SSH=${SAASSHOP_DATA_REPO_SSH:-""}
if [[ "$DATA_REPO_SSH" == "" && -f /app/working.secret/saasshop_data_repo_ssh ]]; then
  DATA_REPO_SSH=$(cat /app/working.secret/saasshop_data_repo_ssh)
fi

if [[ "$DATA_REPO_SSH" == "" ]]; then
  echo "缺少数据仓库地址："
  echo "- 请设置环境变量 SAASSHOP_DATA_REPO_SSH"
  echo "- 或创建文件 /app/working.secret/saasshop_data_repo_ssh（内容为 ssh 地址）"
  exit 11
fi

if [[ "${SAASSHOP_DB_SNAPSHOT_KEY:-}" == "" ]]; then
  echo "缺少加密密钥：请先 export SAASSHOP_DB_SNAPSHOT_KEY='...'(不要写入仓库)"
  exit 12
fi

# 读取 DB 连接（优先 .env，其次 /app/working.secret/laravel.env.snapshot）
ENV_FILE="$REPO_DIR/.env"
if [[ ! -f "$ENV_FILE" && -f /app/working.secret/laravel.env.snapshot ]]; then
  ENV_FILE="/app/working.secret/laravel.env.snapshot"
fi

if [[ ! -f "$ENV_FILE" ]]; then
  echo "找不到 .env 或 /app/working.secret/laravel.env.snapshot，无法确定 DB 配置"
  exit 13
fi

# shellcheck disable=SC1090
set -a
source "$ENV_FILE"
set +a

DB_HOST=${DB_HOST:-127.0.0.1}
DB_PORT=${DB_PORT:-3306}
DB_DATABASE=${DB_DATABASE:-}
DB_USERNAME=${DB_USERNAME:-}
DB_PASSWORD=${DB_PASSWORD:-}

if [[ "$DB_DATABASE" == "" || "$DB_USERNAME" == "" ]]; then
  echo "DB 配置不完整：DB_DATABASE/DB_USERNAME 不能为空"
  exit 14
fi

STAMP=$(date +%Y%m%d_%H%M%S)
OUT_DIR=$(mktemp -d)
SQL_GZ="$OUT_DIR/${DB_DATABASE}_${STAMP}.sql.gz"
ENC_FILE="$OUT_DIR/${DB_DATABASE}_${STAMP}.sql.gz.enc"
MANIFEST="$OUT_DIR/manifest.json"

cleanup() {
  rm -rf "$OUT_DIR" || true
}
trap cleanup EXIT

echo "[snapshot] dumping database '$DB_DATABASE' ..."
# 导出策略：单库结构+数据；保留 routines/triggers/events；避免锁表
# 注意：--databases 会在 SQL 中带 CREATE DATABASE/USE
mysqldump \
  --host="$DB_HOST" --port="$DB_PORT" \
  --user="$DB_USERNAME" --password="$DB_PASSWORD" \
  --databases "$DB_DATABASE" \
  --single-transaction --quick --skip-lock-tables \
  --routines --triggers --events \
  --hex-blob \
  --default-character-set=utf8mb4 \
  | gzip -9 > "$SQL_GZ"

echo "[snapshot] encrypting ..."
openssl enc -aes-256-cbc -pbkdf2 -salt \
  -pass env:SAASSHOP_DB_SNAPSHOT_KEY \
  -in "$SQL_GZ" -out "$ENC_FILE"

SHA256=$(sha256sum "$ENC_FILE" | awk '{print $1}')
SIZE=$(wc -c < "$ENC_FILE" | tr -d ' ')
CODE_HEAD=$(git rev-parse --short HEAD)
BRANCH=$(git rev-parse --abbrev-ref HEAD)

cat > "$MANIFEST" <<EOF
{
  "generated_at": "$(date -Iseconds)",
  "db": {
    "host": "${DB_HOST}",
    "port": ${DB_PORT},
    "database": "${DB_DATABASE}"
  },
  "code": {
    "repo": "saasshop",
    "branch": "${BRANCH}",
    "commit": "${CODE_HEAD}"
  },
  "snapshot": {
    "filename": "latest.sql.gz.enc",
    "source_filename": "$(basename "$ENC_FILE")",
    "sha256": "${SHA256}",
    "size": ${SIZE}
  }
}
EOF

# 准备数据仓工作区
# 数据仓工作区：固定目录，但每次都会强制将 remote 指向当前 DATA_REPO_SSH，避免曾经 clone 过其它仓（如 .wiki.git）导致推错。
WORK_DIR="/tmp/saasshop-data-repo"
if [[ -d "$WORK_DIR/.git" ]]; then
  echo "[data-repo] updating existing clone: $WORK_DIR"
  git -C "$WORK_DIR" remote set-url origin "$DATA_REPO_SSH"
  git -C "$WORK_DIR" fetch origin
  git -C "$WORK_DIR" checkout main || git -C "$WORK_DIR" checkout -b main
  git -C "$WORK_DIR" pull --rebase origin main || true
else
  rm -rf "$WORK_DIR" || true
  echo "[data-repo] cloning: $DATA_REPO_SSH -> $WORK_DIR"
  git clone "$DATA_REPO_SSH" "$WORK_DIR"
  git -C "$WORK_DIR" checkout main || git -C "$WORK_DIR" checkout -b main
fi

mkdir -p "$WORK_DIR/snapshots"
cp -f "$ENC_FILE" "$WORK_DIR/snapshots/latest.sql.gz.enc"
cp -f "$MANIFEST" "$WORK_DIR/snapshots/manifest.json"

# 同时保留一份带时间戳的历史（便于回滚/比对）
cp -f "$ENC_FILE" "$WORK_DIR/snapshots/${DB_DATABASE}_${STAMP}.sql.gz.enc"

git -C "$WORK_DIR" add snapshots

if git -C "$WORK_DIR" diff --cached --quiet; then
  echo "[data-repo] no changes, skip commit"
else
  git -C "$WORK_DIR" commit -m "snapshot: ${DB_DATABASE} ${STAMP} (code ${CODE_HEAD})"
  git -C "$WORK_DIR" push origin main
fi

echo "[done] snapshot published to data repo"
