#!/bin/bash
# AWOOOI 重開機自動恢復腳本
# 2026-04-04 ogt: 根據實際事故建立，解決 PostgreSQL WAL 損壞 + Docker BoltDB 損壞 + K3s Kine 慢查詢
# 部署位置: /usr/local/bin/awoooi-startup.sh (on 192.168.0.188)
# systemd unit: /etc/systemd/system/awoooi-startup.service

set -uo pipefail
LOG="/var/log/awoooi-startup.log"
exec > >(tee -a "$LOG") 2>&1

log() { echo "[$(date '+%Y-%m-%d %H:%M:%S')] $*"; }

log "=== AWOOOI 啟動序列開始 ==="

# ──────────────────────────────────────────────
# STEP 1: containerd 修復（若損壞）
# ──────────────────────────────────────────────
log "[1/7] 檢查 containerd..."

if ! systemctl is-active containerd >/dev/null 2>&1; then
    log "containerd 未啟動，嘗試啟動..."
    systemctl start containerd || true
    sleep 5
fi

if ! systemctl is-active containerd >/dev/null 2>&1; then
    log "containerd 啟動失敗，檢查 BoltDB 損壞..."
    BOLT_DB="/var/lib/containerd/io.containerd.metadata.v1.bolt/meta.db"
    if [ -f "$BOLT_DB" ]; then
        log "備份並刪除損壞的 meta.db..."
        cp "$BOLT_DB" "${BOLT_DB}.bak.$(date +%Y%m%d%H%M%S)"
        rm -f "$BOLT_DB"
    fi
    systemctl start containerd
    sleep 5
    systemctl is-active containerd && log "✅ containerd 修復成功" || { log "❌ containerd 修復失敗"; exit 1; }
else
    log "✅ containerd 已 active"
fi

# ──────────────────────────────────────────────
# STEP 2: Docker 修復（若損壞）
# ──────────────────────────────────────────────
log "[2/7] 檢查 Docker..."

if ! systemctl is-active docker >/dev/null 2>&1; then
    log "Docker 未啟動，嘗試啟動..."
    systemctl start docker || true
    sleep 8
fi

if ! systemctl is-active docker >/dev/null 2>&1; then
    log "Docker 啟動失敗，修復 network BoltDB..."
    NETWORK_DB="/var/lib/docker/network/files/local-kv.db"
    if [ -f "$NETWORK_DB" ]; then
        log "備份並刪除損壞的 local-kv.db..."
        cp "$NETWORK_DB" "${NETWORK_DB}.bak.$(date +%Y%m%d%H%M%S)"
        rm -f "$NETWORK_DB"
    fi
    systemctl restart containerd
    sleep 5
    systemctl start docker
    sleep 8
    systemctl is-active docker && log "✅ Docker 修復成功" || { log "❌ Docker 修復失敗"; exit 1; }
else
    log "✅ Docker 已 active"
fi

# ──────────────────────────────────────────────
# STEP 3: PostgreSQL 修復（若損壞）
# ──────────────────────────────────────────────
log "[3/7] 檢查 PostgreSQL..."

if ! systemctl is-active postgresql@14-main >/dev/null 2>&1; then
    log "PostgreSQL 未啟動，嘗試啟動..."
    systemctl start postgresql@14-main || true
    sleep 8
fi

if ! systemctl is-active postgresql@14-main >/dev/null 2>&1; then
    log "PostgreSQL 啟動失敗，檢查是否 WAL 損壞..."
    if journalctl -u postgresql@14-main -n 20 | grep -q "could not locate a valid checkpoint"; then
        log "⚠️  WAL 損壞！執行 pg_resetwal..."
        /usr/lib/postgresql/14/bin/pg_resetwal -f /var/lib/postgresql/14/main
        log "WAL 重置完成，重啟 PostgreSQL..."
        systemctl start postgresql@14-main
        sleep 8
    fi
    systemctl is-active postgresql@14-main && log "✅ PostgreSQL 修復成功" || { log "❌ PostgreSQL 修復失敗"; exit 1; }
fi

# 等待 PG 接受連線
log "等待 PostgreSQL 就緒..."
for i in $(seq 1 30); do
    pg_isready -h localhost -p 5432 >/dev/null 2>&1 && break
    sleep 2
done
pg_isready -h localhost -p 5432 && log "✅ PostgreSQL accepting connections" || { log "❌ PostgreSQL 無法接受連線"; exit 1; }

# kine 表維護（若有 stale 連線或 WAL 剛重置）
log "維護 k3s_datastore kine 表..."
sudo -u postgres psql -d k3s_datastore -c "
    SELECT pg_terminate_backend(pid)
    FROM pg_stat_activity
    WHERE datname='k3s_datastore' AND pid!=pg_backend_pid() AND state='active'
    AND query_start < now() - interval '5 minutes';
" 2>/dev/null || true

sudo -u postgres psql -d k3s_datastore -c "VACUUM ANALYZE kine;" 2>/dev/null && log "✅ kine VACUUM ANALYZE 完成" || log "⚠️  kine VACUUM 跳過（可能無法連線）"

# ──────────────────────────────────────────────
# STEP 4: Redis
# ──────────────────────────────────────────────
log "[4/7] 啟動 Redis..."
systemctl start redis-server || true
sleep 3
redis-cli ping 2>/dev/null | grep -q PONG && log "✅ Redis UP" || log "⚠️  Redis 可能未就緒"

# ──────────────────────────────────────────────
# STEP 5: Ollama
# ──────────────────────────────────────────────
log "[5/7] 啟動 Ollama..."
systemctl start ollama || true
# Ollama 載入模型需要時間，不立刻驗證

# ──────────────────────────────────────────────
# STEP 6: Nginx
# ──────────────────────────────────────────────
log "[6/7] 啟動 Nginx..."
systemctl start nginx || true
systemctl is-active nginx >/dev/null 2>&1 && log "✅ Nginx UP" || log "⚠️  Nginx 未就緒"

# ──────────────────────────────────────────────
# STEP 7: Docker Compose 服務
# ──────────────────────────────────────────────
log "[7/7] 啟動 Docker Compose 服務..."

# SignOz
SIGNOZ_DIR="/home/ollama/signoz/deploy/docker"
if [ -f "$SIGNOZ_DIR/docker-compose.yaml" ]; then
    log "啟動 SignOz..."
    cd "$SIGNOZ_DIR"
    docker compose up -d 2>&1 | tail -3
    log "✅ SignOz 啟動指令已發送"
else
    log "⚠️  找不到 SignOz compose 檔案"
fi

# MinIO（Velero 備份存儲）
# 2026-04-05 Claude Code: 加入 MinIO — 解決 Velero BSL Unavailable 問題
MINIO_DIR="/home/ollama/minio"
if [ -f "$MINIO_DIR/docker-compose.yml" ]; then
    log "啟動 MinIO (Velero 備份存儲)..."
    cd "$MINIO_DIR"
    docker compose up -d 2>&1 | tail -3
    log "✅ MinIO 啟動指令已發送"
else
    log "⚠️  找不到 MinIO compose 檔案"
fi

# ClawBot（依賴 aiops-network）
# 確保 aiops-network 存在（重開機後 external network 需手動建立）
if ! docker network ls | grep -q aiops-network; then
    log "建立 aiops-network..."
    docker network create aiops-network && log "✅ aiops-network 建立" || log "⚠️ aiops-network 建立失敗"
fi

CLAWBOT_DIR="/home/ollama/clawbot-v5"
if [ -f "$CLAWBOT_DIR/docker-compose.yml" ]; then
    log "啟動 ClawBot..."
    cd "$CLAWBOT_DIR"
    # 若 image snapshot 損壞，先 rebuild
    if ! docker compose up -d 2>&1 | tee /tmp/clawbot-up.log | grep -q "Started\|Running\|healthy"; then
        log "ClawBot 啟動失敗，嘗試 rebuild..."
        docker compose build --no-cache 2>&1 | tail -5 || true
        docker compose up -d 2>&1 | tail -3 || log "⚠️  ClawBot rebuild 也失敗，跳過"
    fi
    log "✅ ClawBot 啟動指令已發送"
else
    log "⚠️  找不到 ClawBot compose 檔案"
fi

# ──────────────────────────────────────────────
# 完成
# ──────────────────────────────────────────────
log "=== AWOOOI 啟動序列完成 ==="
# 最後永遠 exit 0，不讓 systemd 認為失敗
log "K3s 需在 120/121 手動確認啟動（或由 k3s.service 自動啟動）"
log "詳細 SOP: docs/runbooks/REBOOT-RECOVERY-SOP.md"

exit 0
