#!/usr/bin/env bash
# build_new_game_servers_opless
#
# 營運人員版建機腳本。只需輸入專案代碼和 WS ID 範圍，
# 系統自動從 env.yaml 推算所有 IP 參數並執行建機流程。
#
# 用法:
#   build_new_game_servers_opless <project_code> <ws_id_start> <ws_id_end> <timezone> [region_name]
#
# 範例:
#   build_new_game_servers_opless n1-jp 1001 1010 +9
#   build_new_game_servers_opless n1-jp 1001 1010 +9 "JP (S10)"
#   build_new_game_servers_opless n1-en 2001 2010 -5 "US (S20)"

set -euo pipefail

# ── center 機器連線設定（resolve_env.py / reconcile-machines.py 在此執行）────
CENTER_USER="xvincent_tu"
CENTER_HOST="10.150.10.251"
CENTER_BASE="/home/xvincent_tu/center"

# ── 使用說明 ──────────────────────────────────────────────────────────────────
usage() {
    cat <<EOF
用法: $(basename "$0") [--dry-run] <project_code> <ws_id_start> <ws_id_end> <timezone> [region_name]

  --dry-run     只解析參數並印出，不執行建機流程
  project_code  專案代碼，e.g. n1-jp / n1-en
  ws_id_start   WS ID 起始（含），e.g. 1001
  ws_id_end     WS ID 結束（含），e.g. 1010
  timezone      時區偏移，e.g. +9 / +8 / +1 / -5
  region_name   區域顯示名稱（選填，自動產生）

範例:
  $(basename "$0") --dry-run n1-jp 1001 1010 +9
  $(basename "$0") n1-jp 1001 1010 +9
  $(basename "$0") n1-jp 1001 1010 +9 "JP (S10)"
  $(basename "$0") n1-en 2001 2010 -5 "US (S20)"
EOF
    exit 1
}

# ── --dry-run 旗標 ────────────────────────────────────────────────────────────
DRY_RUN=false
if [[ "${1:-}" == "--dry-run" ]]; then
    DRY_RUN=true
    shift
fi

[[ $# -lt 4 ]] && usage

# ── 參數 ──────────────────────────────────────────────────────────────────────
PROJECT_CODE="$1"
WS_ID_START="$2"
WS_ID_END="$3"
TIMEZONE="$4"
REGION_NAME="${5:-}"
DBNAME="${6:-WebTool}"

# ── Source .gamerc（暫時關閉嚴格模式，避免 .gamerc 內部指令觸發 set -e）──────
set +euo pipefail
source "$HOME/.gamerc" 2>/dev/null || true
set -euo pipefail

# ── 時間戳記（JST = UTC+9）────────────────────────────────────────────────────
TIMESTAMP=$(TZ=Asia/Tokyo date +"%Y%m%dT%H%M")

log()       { echo "[$(date +%T)] $*"; }
log_start() { echo ""; echo "[$(date +%T)] ▶▶▶ $* 開始"; echo ""; }
log_end()   { echo ""; echo "[$(date +%T)] ◀◀◀ $* 完成"; echo ""; }

# ═════════════════════════════════════════════════════════════════════════════
# Step 0: 參數解析 — resolve_env.py 推算 IP 參數
# ═════════════════════════════════════════════════════════════════════════════
log_start "Step 0: 參數解析（resolve_env.py）"

RESOLVE_OUTPUT=$(ssh "${CENTER_USER}@${CENTER_HOST}" \
    "python3 ${CENTER_BASE}/scripts/resolve_env.py '$PROJECT_CODE' '$WS_ID_START'" 2>&1)
if [[ $? -ne 0 ]]; then
    echo "$RESOLVE_OUTPUT" >&2
    exit 1
fi

# 解析 resolve_env.py 輸出
eval "$RESOLVE_OUTPUT"
# 現在有: CLOUD, ENV_YAML, ZONE_ID, MS_IP, WS_IP_INIT, SUBNET_NAME

# ── 驗證 WS ID Start / End 在同一 Zone ──────────────────────────────────────
ZONE_FROM_END=$(( WS_ID_END / 100 ))
if [[ "$ZONE_ID" != "$ZONE_FROM_END" ]]; then
    echo "錯誤：WS ID Start ($WS_ID_START) 和 WS ID End ($WS_ID_END) 不在同一 Zone" >&2
    echo "  WS ID Start → Zone $ZONE_ID" >&2
    echo "  WS ID End   → Zone $ZONE_FROM_END" >&2
    exit 1
fi

# ── WS ID Start ≤ End ────────────────────────────────────────────────────────
if [[ "$WS_ID_START" -gt "$WS_ID_END" ]]; then
    echo "錯誤：WS ID Start ($WS_ID_START) 不能大於 WS ID End ($WS_ID_END)" >&2
    exit 1
fi

# ── Region Name 自動產生 ─────────────────────────────────────────────────────
if [[ -z "$REGION_NAME" ]]; then
    REGION_NAME="${SUBNET_NAME} (S${ZONE_ID})"
fi

# ── 設定 log 檔案 ────────────────────────────────────────────────────────────
LOG_FILE="/tmp/build_opless-${PROJECT_CODE}_${ZONE_ID}_${WS_ID_START}_${WS_ID_END}_${TIMESTAMP}.log"
OUTPUT_FILENAME="s${ZONE_ID}_db_setup_${TIMESTAMP}.txt"

# ── 全程 stdout/stderr tee 到 log 檔 ─────────────────────────────────────────
exec > >(tee -a "$LOG_FILE") 2>&1

echo "======================================================"
echo " build_new_game_servers_opless 開始"
echo " Project:     ${PROJECT_CODE} (${CLOUD})"
echo " TimeZone:    ${TIMEZONE}"
echo " Region:      ${REGION_NAME}"
echo " Zone ID:     ${ZONE_ID}"
echo " MS IP:       ${MS_IP}"
echo " WS IP Init:  ${WS_IP_INIT}"
echo " WS ID 範圍:  ${WS_ID_START} ~ ${WS_ID_END}"
echo " DBNAME:      ${DBNAME}"
echo " Log:         ${LOG_FILE}"
echo " 時間:        $(date '+%Y-%m-%d %H:%M:%S') JST"
echo "======================================================"

log_end "Step 0: 參數解析"

# ── dry-run 模式：只印參數，不執行 ──────────────────────────────────────────
if [[ "$DRY_RUN" == true ]]; then
    echo ""
    echo "[dry-run] 參數解析完成，不執行建機流程。"
    exit 0
fi

# ── WS IP 計算（與 generate_hosts_n1_whole_new_zone 邏輯一致）─────────────────
calc_ws_ip() {
    local ws_ip_init="$1" ws_id="$2"
    local last_digit=$(( ws_id % 10 ))
    local offset=$(( (last_digit - 1 + 10) % 10 ))
    local prefix="${ws_ip_init%.*}"
    local last_octet="${ws_ip_init##*.}"
    echo "${prefix}.$((last_octet + offset))"
}

# 去重後收集本次所有 WS IP
collect_ws_ips() {
    declare -gA _seen=()
    WS_IPS=()
    local ws_id ip
    for ws_id in $(seq "$WS_ID_START" "$WS_ID_END"); do
        ip=$(calc_ws_ip "$WS_IP_INIT" "$ws_id")
        if [[ -z "${_seen[$ip]+_}" ]]; then
            _seen[$ip]=1
            WS_IPS+=("$ip")
        fi
    done
}

# ═════════════════════════════════════════════════════════════════════════════
# Step 1: 確認 hosts 是否已有任何 WS 項目
# ═════════════════════════════════════════════════════════════════════════════
log_start "Step 1: 確認 hosts WS 項目"
HOSTS_FILE="$HOME/bin/hosts"
if grep -qP "(?<!\S)WS\d" "$HOSTS_FILE" 2>/dev/null; then
    HAS_EXISTING_WS=true
    log "hosts 已有 WS 項目 → 將使用 Ctrl LIVEBuild nosync noreset"
else
    HAS_EXISTING_WS=false
    log "hosts 無任何 WS 項目 → 將使用 Ctrl LIVEBuild（首次建置）"
fi
log_end "Step 1: 確認 hosts WS 項目"

# ═════════════════════════════════════════════════════════════════════════════
# Step 2: 更新 hosts
# ═════════════════════════════════════════════════════════════════════════════
log_start "Step 2: generate_hosts_n1_whole_new_zone"
"$HOME/bin/generate_hosts_n1_whole_new_zone" \
    "$REGION_NAME" "$ZONE_ID" "$MS_IP" "$WS_IP_INIT" "$WS_ID_START" "$WS_ID_END"
log_end "Step 2: generate_hosts_n1_whole_new_zone"

# ═════════════════════════════════════════════════════════════════════════════
# Step 3: rewrite_etc_hosts
# ═════════════════════════════════════════════════════════════════════════════
log_start "Step 3: rewrite_etc_hosts"
set +u
rewrite_etc_hosts
set -u
log_end "Step 3: rewrite_etc_hosts"

# ═════════════════════════════════════════════════════════════════════════════
# Step 4: reconcile-machines.py（動態 env.yaml 路徑）
# ═════════════════════════════════════════════════════════════════════════════
RECONCILE_LOG="/tmp/reconcile-machines-$(date +%Y%m%d-%H%M%S).log"
log_start "Step 4: reconcile-machines.py (${CLOUD})"

set +eo pipefail
ssh "${CENTER_USER}@${CENTER_HOST}" \
    "python3 ${CENTER_BASE}/scripts/reconcile-machines.py --env ${ENV_YAML} --hosts /dev/stdin" \
    < /etc/hosts | tee "$RECONCILE_LOG"
RECONCILE_STATUS=("${PIPESTATUS[@]}")
set -eo pipefail
if [ "${RECONCILE_STATUS[0]}" -ne 0 ]; then
    log "機器建置失敗，中止"
    exit 1
fi
log_end "Step 4: reconcile-machines.py（log: ${RECONCILE_LOG}）"

# ═════════════════════════════════════════════════════════════════════════════
# Step 5: rsync common → 新建機器
# ═════════════════════════════════════════════════════════════════════════════
BUILT_COUNT=0
if [[ -f "$RECONCILE_LOG" ]]; then
    BUILT_COUNT=$(grep -oP "需建立: \K\d+" "$RECONCILE_LOG" 2>/dev/null || echo 0)
fi

if [[ "$BUILT_COUNT" -gt 0 ]]; then
    collect_ws_ips
    ALL_NEW_IPS=("$MS_IP" "${WS_IPS[@]}")
    log_start "Step 5: rsync common → 新機器（共 ${#ALL_NEW_IPS[@]} 台）"
    for ip in "${ALL_NEW_IPS[@]}"; do
        log "  rsync → $ip"
        ssh -o StrictHostKeyChecking=no "$ip" \
            'cd $HOME; rsync -avz -e "ssh -o StrictHostKeyChecking=no" CTRL:$HOME/common .'
    done
    log_end "Step 5: rsync common"
else
    log "Step 5: 略過 rsync（無新建機器）"
fi

# ═════════════════════════════════════════════════════════════════════════════
# Step 6: Ctrl LIVEBuild
# ═════════════════════════════════════════════════════════════════════════════
if [[ "$HAS_EXISTING_WS" == false ]]; then
    log_start "Step 6: Ctrl LIVEBuild"
    echo "yes" | "$HOME/bin/Ctrl" LIVEBuild
    log_end "Step 6: Ctrl LIVEBuild"
else
    log_start "Step 6: Ctrl LIVEBuild nosync noreset"
    echo "yes" | "$HOME/bin/Ctrl" LIVEBuild nosync noreset
    log_end "Step 6: Ctrl LIVEBuild nosync noreset"
fi

# ═════════════════════════════════════════════════════════════════════════════
# Step 7: generate_dbsetup → CTRL
# ═════════════════════════════════════════════════════════════════════════════
log_start "Step 7: generate_dbsetup → CTRL"
ssh CTRL '$HOME/bin/generate_dbsetup '"${TIMEZONE} ${ZONE_ID} ${WS_ID_START} ${WS_ID_END} | tee /tmp/${OUTPUT_FILENAME}"
log_end "Step 7: generate_dbsetup → CTRL:/tmp/${OUTPUT_FILENAME}"

# ═════════════════════════════════════════════════════════════════════════════
# Step 8: psql 匯入
# ═════════════════════════════════════════════════════════════════════════════
log_start "Step 8: psql 匯入"
if ssh CTRL "psql -U postgres -lqt | cut -d'|' -f1 | grep -qw '${DBNAME}'"; then
    log "DB '${DBNAME}' 存在，執行 psql 匯入..."
    ssh CTRL "psql -U postgres -d ${DBNAME} < /tmp/${OUTPUT_FILENAME}"
    log_end "Step 8: psql 匯入完成"
else
    log "⚠️  DB '${DBNAME}' 不存在，已跳過 psql 匯入"
    log "    請手動執行匯入："
    log "    ssh CTRL 'psql -U postgres -d ${DBNAME} < /tmp/${OUTPUT_FILENAME}'"
    log_end "Step 8: psql 匯入（跳過）"
fi

# ── 完成 ──────────────────────────────────────────────────────────────────────
echo ""
echo "======================================================"
echo " build_new_game_servers_opless 完成"
echo " Project:  ${PROJECT_CODE} (${CLOUD})"
echo " Zone:     ${ZONE_ID}"
echo " DB:       ${DBNAME}"
echo " DB setup: CTRL:/tmp/${OUTPUT_FILENAME}"
echo " Log:      ${LOG_FILE}"
echo " 時間:     $(date '+%Y-%m-%d %H:%M:%S') JST"
echo "======================================================"
