#!/bin/bash

# ==============================================================================
#      RCLONE ENTERPRISE-GRADE SYNC SCRIPT (v4.1 - Corrected & Final)
# ==============================================================================
#
#  版本: 4.1
#  修正:
#  - [关键] 恢复了 rclone sync 命令中缺失的 --backup-dir 参数，确保文件在
#    被覆盖或删除前能正确备份。
#
#  完整功能:
#  - 单向同步 (rclone sync)
#  - 智能备份被覆盖/删除的文件到按天组织的目录
#  - 防止并发执行的锁文件机制
#  - 自动清理指定天数之前的旧备份
#  - 自动日志轮转，防止日志文件无限增长
#  - 成功或失败时发送钉钉通知
#  - 失败时，通知中包含错误日志摘要
#
# ==============================================================================

# ============================ 用户配置区域 ============================

# --- Rclone 配置 ---
SOURCE_DIR="/data2/immich/library/"
REMOTE_PATH="onedrive:immich/library/"
# 备份文件的父目录。脚本将在此目录下创建每日备份文件夹。
BACKUP_PARENT_PATH="onedrive:immich/backup/"
# 动态生成当天的完整备份路径，用于 --backup-dir 参数
TODAY_BACKUP_PATH="${BACKUP_PARENT_PATH}$(date +%Y-%m-%d)"
LOG_FILE="/data2/immich/log/rclone-immich-sync.log"
# 这个log_file也需要上传到onedrive，使用另外一个进程
# --- 锁文件配置 ---
LOCK_FILE="/data2/immich/rclone-immich-sync.lock"

# --- 日志与备份清理配置 ---
LOG_MAX_SIZE_MB=200
# 备份保留天数。所有文件修改时间早于这个天数的备份将被删除。
BACKUP_RETENTION_DAYS=180

# --- 钉钉机器人配置 ---
DINGTALK_ACCESS_TOKEN="d10822224bf76dfcadad9da452cd37fafd3439aac0a1a4bf592214f9a3768a69"
DINGTALK_SECRET="SECdb923bef42b35beca1254215d9abcfe142465628ff91e4fcaa22678bcec5c9da"
# 加签：SECdb923bef42b35beca1254215d9abcfe142465628ff91e4fcaa22678bcec5c9da
# https://oapi.dingtalk.com/robot/send?access_token=d10822224bf76dfcadad9da452cd37fafd3439aac0a1a4bf592214f9a3768a69

# --- 代理设置 ---
PROXY_URL="http://127.0.0.1:1099"
ROXY_TEST_URL="https://pac-9d7.pages.dev/access"
PROXY_KEYWORD="ACCESS"
# ============================ 初始化与检查 ============================

# --- 锁文件检查 ---
if ! mkdir "${LOCK_FILE}" 2>/dev/null; then
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 错误：检测到上一个同步任务仍在运行。脚本退出以防止重复执行。" | tee -a "${LOG_FILE}"
    exit 1
fi

# --- 设定陷阱 (trap)，确保脚本在任何情况下退出时都能删除锁文件 ---
trap 'rm -rf "${LOCK_FILE}"' EXIT

# ========================= 钉钉通知函数 (无需修改) =========================
# 此函数已包含 jq 依赖来安全处理消息内容
# 请确保已安装 jq: sudo apt-get install jq 或 sudo yum install jq
urlencode() {
    string="${1}"; 
    strlen=${#string}; 
    encoded=""; 
    pos c o
    for (( pos=0 ; pos<strlen ; pos++ )); do c=${string:$pos:1}; case "$c" in [-_.a-zA-Z0-9] ) o="${c}" ;; * ) printf -v o '%%%02x' "'$c"; esac; encoded+="${o}"; done
    echo "${encoded}"
}
send_dingtalk_notification() {
    if [[ -z "${DINGTALK_ACCESS_TOKEN}" || -z "${DINGTALK_SECRET}" || "${DINGTALK_ACCESS_TOKEN}" == "YOUR_ACCESS_TOKEN_HERE" ]]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 未配置钉钉机器人，跳过发送通知。" >> "${LOG_FILE}"; return
    fi
    message="$1"; 
    timestamp=$(date +%s%N | cut -b1-13); 
    string_to_sign="${timestamp}\n${DINGTALK_SECRET}"
    sign_base64=$(echo -ne "$string_to_sign" | openssl dgst -sha256 -hmac "$DINGTALK_SECRET" -binary | base64)
    sign_encoded=$(urlencode "$sign_base64")
    webhook_url="https://oapi.dingtalk.com/robot/send?access_token=${DINGTALK_ACCESS_TOKEN}&timetamp=${timestamp}&sign=${sign_encoded}"
    json_payload=$(jq -n --arg content "$message" '{"msgtype": "text", "text": {"content": $content}}')
    curl -s -X POST "${webhook_url}" -H 'Content-Type: application/json' -d "${json_payload}" >> "${LOG_FILE}" 2>&1
}
# ============================ 主任务：文件同步 ============================
echo "==================================================" >> "${LOG_FILE}"
echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始执行 Immich 库同步任务..." >> "${LOG_FILE}"

# ============================ 日志轮转逻辑 (无需修改) ============================
if [ -f "${LOG_FILE}" ]; then
    max_size_bytes=$((LOG_MAX_SIZE_MB * 1024 * 1024));
    current_size_bytes=$(stat -c%s "${LOG_FILE}")

    if [ ${current_size_bytes} -gt ${max_size_bytes} ]; then
        archive_name="${LOG_FILE}.$(date +%Y%m%d-%H%M%S).gz"; echo "$(date '+%Y-%m-%d %H:%M:%S') - 日志文件大小超限，正在归档..." >> "${LOG_FILE}"
        gzip -c "${LOG_FILE}" > "${archive_name}" && > "${LOG_FILE}"
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 日志归档完成。" >> "${LOG_FILE}"
    fi
fi

# -------- 设置代理 --------
echo "-------- 设置代理 ----------" >> "${LOG_FILE}"
test_response=$(curl -s --proxy "$PROXY_URL" "$PROXY_TEST_URL" --connect-timeout 5)
if [ "$test_response" != "$PROXY_KEYWORD" ]; then
    echo "代理测试失败 (返回值: '$response')，无代理模式连接..." >> "${LOG_FILE}" 
    unset https_proxy
else
    export https_proxy=$PROXY_URL
    echo "使用代理模式连接..." >> "${LOG_FILE}" 
fi
# ==============
rclone sync "${SOURCE_DIR}" "${REMOTE_PATH}" \
    --fast-list \
    --checkers 32 \
    --transfers 8 \
    --bwlimit 1000M \
    --backup-dir "${TODAY_BACKUP_PATH}" \
    --retries 5 \
    --retries-sleep 30s \
    --log-file "${LOG_FILE}" \
    --onedrive-no-version \
    -v

sync_exit_code=$?

# ======================== 结果检查与通知 ========================
if [ ${sync_exit_code} -eq 0 ]; then
    log_message="$(date '+%Y-%m-%d %H:%M:%S') - Immich 库同步成功完成。"
    dingtalk_message="【备份成功】服务器上的 Immich 库已于 $(date '+%Y-%m-%d %H:%M:%S') 成功同步到 OneDrive。"
    echo "${log_message}" >> "${LOG_FILE}"
    send_dingtalk_notification "${dingtalk_message}"

    # --- 子任务：清理旧备份 (仅在主任务成功后执行) ---
    echo "$(date '+%Y-%m-%d %H:%M:%S') - 开始清理 ${BACKUP_RETENTION_DAYS} 天前的旧备份..." >> "${LOG_FILE}"
    # 删除备份父目录中，所有修改时间早于指定天数的 文件，然后用 --rmdirs 删除因此变空的目录
    rclone delete "${BACKUP_PARENT_PATH}" \
        --min-age "${BACKUP_RETENTION_DAYS}d" \
        --rmdirs \
        --log-file "${LOG_FILE}" \
        -v
    
    cleanup_exit_code=$?
    if [ ${cleanup_exit_code} -ne 0 ]; then
        echo "$(date '+%Y-%m-%d %H:%M:%S') - 警告：旧备份清理失败！退出代码: ${cleanup_exit_code}" >> "${LOG_FILE}"
        send_dingtalk_notification "【备份警告】主同步任务成功，但清理旧备份失败。请检查日志。"
    fi
else
    # --- 主任务失败 ---
    log_message="$(date '+%Y-%m-%d %H:%M:%S') - 错误：Immich 库同步失败！退出代码: ${sync_exit_code}"
    error_details=$(tail -n 10 "${LOG_FILE}")
    dingtalk_message="【备份失败】警告！服务器上的 Immich 库同步任务失败，请立即检查！

退出代码: ${sync_exit_code}
错误摘要 (最后10行日志):
---------------------
${error_details}"
    echo "${log_message}" >> "${LOG_FILE}"
    send_dingtalk_notification "${dingtalk_message}"
fi

echo "$(date '+%Y-%m-%d %H:%M:%S') - 任务脚本执行完毕。" >> "${LOG_FILE}"
echo "==================================================" >> "${LOG_FILE}"
echo "" >> "${LOG_FILE}"

exit ${sync_exit_code}