#!/usr/bin/env bash
# scripts/ops/pg-backup.sh
# Sprint 5.2: PostgreSQL 自動備份腳本
# 部署: cron 0 */6 * * * on 188 (ollama user)
# 備份目標: awoooi_prod + momo_analytics
# 保留策略: 7 天
# 2026-04-09 Claude Sonnet 4.6 Asia/Taipei

set -euo pipefail

BACKUP_DIR="${BACKUP_DIR:-/home/ollama/backups}"
SECRETS_FILE="${SECRETS_FILE:-/home/ollama/awoooi-ops-secrets/secrets.env}"
RETAIN_DAYS="${RETAIN_DAYS:-7}"
AWOOOI_API_URL="${AWOOOI_API_URL:-https://awoooi.wooo.work}"
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 載入 secrets（含 Telegram token for fallback）
[[ -f "$SECRETS_FILE" ]] && source "$SECRETS_FILE"

TIMESTAMP=$(date '+%Y%m%d_%H%M%S')
LOG_PREFIX="[$(date '+%Y-%m-%d %H:%M:%S %z')]"

log() { echo "${LOG_PREFIX} $*"; }

notify_awoooi_ops() {
    local status="$1"
    local msg="$2"
    local helper="${SCRIPT_DIR}/notify-awoooi-ops.sh"
    [[ -x "$helper" ]] || return 1

    AWOOI_OPS_ALERTNAME="Backup.PG" \
    AWOOI_OPS_JOB_NAME="AWOOOI DB 備份" \
    AWOOI_OPS_STATUS="$status" \
    AWOOI_OPS_SEVERITY="info" \
    AWOOI_OPS_SOURCE="pg-backup" \
    AWOOI_OPS_COMPONENT="postgres-backup" \
    AWOOI_OPS_SUMMARY="AWOOOI DB 備份 ${status}" \
    AWOOI_OPS_DETAIL="$msg" \
    "$helper" >/dev/null
}

notify_telegram() {
    local msg="$1"
    local status="${2:-success}"

    # 正式路徑：先交給 AWOOI API，由 TelegramGateway 送出並鏡像到 AwoooP。
    # 只有 API 不可達或 helper 未部署時，才使用 Telegram 直發救命旁路。
    notify_awoooi_ops "$status" "$msg" && return 0

    local chat_id="${SRE_GROUP_CHAT_ID:--1003711974679}"
    if [[ -n "${TELEGRAM_BOT_TOKEN:-}" && -n "$chat_id" ]]; then
        curl -s -X POST "https://api.telegram.org/bot${TELEGRAM_BOT_TOKEN}/sendMessage" \
            -d "chat_id=${chat_id}" \
            -d "parse_mode=HTML" \
            --data-urlencode "text=${msg}" \
            > /dev/null 2>&1 || true
    fi
}

backup_db() {
    local label="$1"   # awoooi_prod | momo_analytics
    local host="$2"    # 127.0.0.1
    local user="$3"
    local password="$4"
    local dbname="$5"

    local outfile="${BACKUP_DIR}/${label}_${TIMESTAMP}.sql.gz"
    log "開始備份 ${label} → ${outfile}"

    if PGPASSWORD="$password" pg_dump \
        -h "$host" -U "$user" -d "$dbname" \
        --no-owner --no-acl \
        2>/dev/null | gzip > "$outfile"; then

        local size
        size=$(du -sh "$outfile" | cut -f1)
        log "✅ ${label} 備份完成 (${size})"
        echo "success:${label}:${size}"
    else
        log "❌ ${label} 備份失敗"
        echo "failed:${label}"
    fi
}

cleanup_old_backups() {
    local label="$1"
    local count
    count=$(find "$BACKUP_DIR" -name "${label}_*.sql.gz" -mtime "+${RETAIN_DAYS}" | wc -l)
    if (( count > 0 )); then
        find "$BACKUP_DIR" -name "${label}_*.sql.gz" -mtime "+${RETAIN_DAYS}" -delete
        log "🗑️ 清理 ${label} 舊備份 ${count} 個 (>${RETAIN_DAYS}天)"
    fi
}

main() {
    mkdir -p "$BACKUP_DIR"
    log "=== pg-backup 開始 (retain=${RETAIN_DAYS}d) ==="

    local results=()

    # awoooi_prod (host PostgreSQL, TCP)
    results+=("$(backup_db "awoooi_prod" "127.0.0.1" "awoooi" "awoooi_prod_2026" "awoooi_prod")")

    # momo_analytics (momo-db 容器，無對外 port，用 docker exec 直接 dump)
    local outfile_momo="${BACKUP_DIR}/momo_analytics_${TIMESTAMP}.sql.gz"
    log "開始備份 momo_analytics (docker exec) → ${outfile_momo}"
    if docker exec momo-db pg_dump -U momo momo_analytics 2>/dev/null | gzip > "$outfile_momo"; then
        local size_momo
        size_momo=$(du -sh "$outfile_momo" | cut -f1)
        log "✅ momo_analytics 備份完成 (${size_momo})"
        results+=("success:momo_analytics:${size_momo}")
    else
        log "❌ momo_analytics 備份失敗"
        rm -f "$outfile_momo"
        results+=("failed:momo_analytics")
    fi

    # 清理舊備份
    cleanup_old_backups "awoooi_prod"
    cleanup_old_backups "momo_analytics"

    log "=== pg-backup 完成 ==="

    # 組裝 Telegram 通知
    local success_count=0 fail_count=0 details=""
    for r in "${results[@]}"; do
        IFS=':' read -r status label size_or_empty <<< "$r"
        case "$status" in
            success) ((success_count++)) || true; details+="✅ ${label} (${size_or_empty})\n" ;;
            failed)  ((fail_count++)) || true;    details+="❌ ${label} 失敗\n" ;;
            skipped) details+="⏭️ ${label} 跳過\n" ;;
        esac
    done

    local icon="✅"
    [[ $fail_count -gt 0 ]] && icon="⚠️"

    local notify_status="success"
    [[ $fail_count -gt 0 ]] && notify_status="failed"

    notify_telegram "${icon} <b>AWOOOI DB 備份</b>
├ 時間: $(date '+%Y-%m-%d %H:%M') +0800
├ 成功: ${success_count} | 失敗: ${fail_count}
└ ${details}" "$notify_status"

    [[ $fail_count -gt 0 ]] && exit 1
    return 0
}

main "$@"
