#!/usr/bin/env bash

# 使用方式：
#   ./merge_db_backup /absolute/path/to/merge_setup.ini DB_NAME_POSTFIX <AccountDB/GameDB/WorldDB>
#
# 流程：
#   1. source load_merge_db_setup
#   2. load_merge_db_setup <merge_setup.ini>
#   3. 依參數 3 決定要備份哪些 DB：
#        - 無參數 3：AccountDB + GameDB + 全部 WorldDB
#        - AccountDB：只備份 AccountDB
#        - GameDB：只備份 GameDB
#        - WorldDB：只備份所有 WorldDB
#   4. 對每一個要備份的 DB，在遠端 PostgreSQL 建立：
#        CREATE DATABASE "<DB_NAME><POSTFIX>" TEMPLATE "<DB_NAME>";
#
# 依賴：
#   - load_merge_db_setup 內已實作：
#       load_merge_db_setup
#       get_accountdb_value
#       get_gamedb_value
#       get_worlddb_value
#       world_order (依 setup 順序的 WorldID array)
#
#   - 每個 DB 的設定提供：
#       AccountDBIP / AccountDBName / AccountDBUser / AccountDBPW / (AccountDBPort)
#       GameDBIP / GameDB / GameDBUser / GameDBPassword / (GameDBPort)
#       WorldDBIP / WorldDBName / WorldDBUser / WorldDBPassword / (WorldDBPort)

set -u

if [[ $# -lt 2 ]]; then
    echo "Usage: $0 /absolute/path/to/merge_setup.ini DB_NAME_POSTFIX <AccountDB|GameDB|WorldDB>" >&2
    exit 1
fi

SETUP_FILE="$1"
DB_POSTFIX="$2"
TARGET_KIND="${3-}"    # 可能不存在，必須用 ${3-}

# 強制要求 setup 檔案用絕對路徑
if [[ "${SETUP_FILE:0:1}" != "/" ]]; then
    echo "請使用 setup 檔案的絕對路徑（目前：$SETUP_FILE）" >&2
    exit 1
fi

if [[ ! -f "$SETUP_FILE" ]]; then
    echo "找不到 setup 檔案：$SETUP_FILE" >&2
    exit 1
fi

# 驗證第三個參數（若有提供）
if [[ -n "$TARGET_KIND" ]]; then
    case "$TARGET_KIND" in
        AccountDB|GameDB|WorldDB)
            # 合法
            ;;
        *)
            echo "第三個參數若提供，只能是：AccountDB / GameDB / WorldDB" >&2
            echo "實際輸入：$TARGET_KIND" >&2
            exit 1
            ;;
    esac
fi

# 取得目前腳本所在目錄，假設 load_merge_db_setup 跟這支在同一個目錄
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"

# 引入 load_merge_db_setup
source "$SCRIPT_DIR/load_merge_db_setup"

# 載入設定
if ! load_merge_db_setup "$SETUP_FILE"; then
    echo "載入設定檔失敗：$SETUP_FILE" >&2
    exit 1
fi

########################################
# 共用：在指定主機上 clone 一個 DB
########################################
# 參數：HOST SRC_DB USER PASS [PORT] POSTFIX
# 動作：在該 host 上執行
#   CREATE DATABASE "<SRC_DB><POSTFIX>" TEMPLATE "<SRC_DB>";
#
# 若備份 DB 已存在，則跳過並顯示 [SKIP] 訊息。
pg_clone_db() {
    local host="${1-}"
    local src_db="${2-}"
    local user="${3-}"
    local pass="${4-}"
    local port="${5-}"
    local postfix="${6-}"

    if [[ -z "$host" || -z "$src_db" || -z "$user" ]]; then
        echo "[NG]  參數不完整，host/src_db/user 不可為空 (host='$host', db='$src_db')" >&2
        return 1
    fi

    if [[ -z "$port" ]]; then
        port=5432
    fi

    local new_db="${src_db}${postfix}"

    echo ">>> ${host}:${port} - clone DB '${src_db}' -> '${new_db}'"

    # 檢查新 DB 是否已存在
    local exists
    exists=$(
        PGPASSWORD="$pass" PGCONNECT_TIMEOUT=3 \
        psql -h "$host" -p "$port" -U "$user" -d postgres \
             -tA -c "SELECT 1 FROM pg_database WHERE datname = '${new_db}'" \
             2>/dev/null || true
    )

    if [[ "$exists" == "1" ]]; then
        echo "[SKIP]  ${host}:${port} - DB '${new_db}' 已存在，略過建立"
        return 0
    fi

    # 實際建立備份 DB
    local sql
    sql="CREATE DATABASE \"${new_db}\" TEMPLATE \"${src_db}\";"

    if PGPASSWORD="$pass" PGCONNECT_TIMEOUT=5 \
        psql -h "$host" -p "$port" -U "$user" -d postgres \
             -c "$sql" >/dev/null 2>&1; then
        echo "[OK]    ${host}:${port} - 已建立備份 DB '${new_db}' (from '${src_db}')"
        return 0
    else
        echo "[NG]    ${host}:${port} - 建立備份 DB '${new_db}' 失敗" >&2
        return 1
    fi
}

echo "=== 建立 PostgreSQL DB 備份：$SETUP_FILE，POSTFIX='${DB_POSTFIX}'，TARGET='${TARGET_KIND:-ALL}' ==="

overall_status=0

########################################
# 1. Account DB
########################################
if [[ -z "$TARGET_KIND" || "$TARGET_KIND" == "AccountDB" ]]; then
    echo "--- AccountDB ---"
    {
        host=$(get_accountdb_value "AccountDBIP")
        dbname=$(get_accountdb_value "AccountDBName")
        user=$(get_accountdb_value "AccountDBUser")
        pass=$(get_accountdb_value "AccountDBPW")
        port=$(get_accountdb_value "AccountDBPort")

        if [[ -z "${dbname-}" ]]; then
            echo "[INFO]  未設定 AccountDBName，略過"
        else
            PG_VERSION=$(ssh -o StrictHostKeyChecking=no $host "psql --version | awk '{print \$3}' | cut -d. -f1")
            ssh -o StrictHostKeyChecking=no $host "sudo systemctl restart postgresql@${PG_VERSION}-main.service; sudo systemctl status postgresql@${PG_VERSION}-main.service"
            if pg_clone_db "$host" "$dbname" "$user" "$pass" "$port" "$DB_POSTFIX"; then
                :
            else
                overall_status=1
            fi
        fi
    }
    echo
fi

########################################
# 2. Game DB
########################################
if [[ -z "$TARGET_KIND" || "$TARGET_KIND" == "GameDB" ]]; then
    echo "--- GameDB ---"
    {
        host=$(get_gamedb_value "GameDBIP")
        dbname=$(get_gamedb_value "GameDB")
        user=$(get_gamedb_value "GameDBUser")
        pass=$(get_gamedb_value "GameDBPassword")
        port=$(get_gamedb_value "GameDBPort")

        if [[ -z "${dbname-}" ]]; then
            echo "[INFO]  未設定 GameDB，略過"
        else
            PG_VERSION=$(ssh -o StrictHostKeyChecking=no $host "psql --version | awk '{print \$3}' | cut -d. -f1")
            ssh -o StrictHostKeyChecking=no $host "sudo systemctl restart postgresql@${PG_VERSION}-main.service; sudo systemctl status postgresql@${PG_VERSION}-main.service"
            if pg_clone_db "$host" "$dbname" "$user" "$pass" "$port" "$DB_POSTFIX"; then
                :
            else
                overall_status=1
            fi
        fi
    }
    echo
fi

########################################
# 3. 所有 World DB
########################################
if [[ -z "$TARGET_KIND" || "$TARGET_KIND" == "WorldDB" ]]; then
    echo "--- WorldDB ---"
    if [[ "${#world_order[@]}" -gt 0 ]]; then
        for wid in "${world_order[@]}"; do
            host=$(get_worlddb_value "$wid" "WorldDBIP")
            dbname=$(get_worlddb_value "$wid" "WorldDBName")
            user=$(get_worlddb_value "$wid" "WorldDBUser")
            pass=$(get_worlddb_value "$wid" "WorldDBPassword")
            port=$(get_worlddb_value "$wid" "WorldDBPort")

            if [[ -z "${dbname-}" ]]; then
                echo "[INFO]  WorldID=${wid} 未設定 WorldDBName，略過"
                continue
            fi

            PG_VERSION=$(ssh -o StrictHostKeyChecking=no $host "psql --version | awk '{print \$3}' | cut -d. -f1")
            ssh -o StrictHostKeyChecking=no $host "sudo systemctl restart postgresql@${PG_VERSION}-main.service; sudo systemctl status postgresql@${PG_VERSION}-main.service"
            if pg_clone_db "$host" "$dbname" "$user" "$pass" "$port" "$DB_POSTFIX"; then
                :
            else
                overall_status=1
            fi
        done
    else
        echo "[INFO]  沒有任何 WorldDB 設定"
    fi
fi                                  

echo "=== 建立備份作業結束 ==="

exit "$overall_status"

