#!/bin/bash
set -euo pipefail

SSH_OPTS=(-o StrictHostKeyChecking=no)

usage() {
  echo "用法: $0 <new_merge_filename> <old_merge_filename> <restore_dbbackup_date (YYYYMMDD)> [localdb]" >&2
  exit 1
}

# 檢查參數數量
[[ $# -eq 3 || $# -eq 4 ]] || usage

new_merge_filename="$1"
old_merge_filename="$2"
restore_dbbackup_date="$3"

localdb_mode=0
if [[ $# -eq 4 ]]; then
  [[ "$4" == "localdb" ]] || { echo "ERROR: unknown 4th parameter: $4 (only allow: localdb)" >&2; exit 1; }
  localdb_mode=1
fi

new_file="$HOME/bin/merge_n1/test/${new_merge_filename}"
old_file="$HOME/bin/merge_n1/test/${old_merge_filename}"

# 檢查檔案是否存在
[[ -f "$new_file" ]] || { echo "找不到檔案: $new_file" >&2; exit 1; }
[[ -f "$old_file" ]] || { echo "找不到檔案: $old_file" >&2; exit 1; }

is_leap_year() {
  local y="$1"
  (( (y % 400 == 0) || (y % 4 == 0 && y % 100 != 0) ))
}

is_valid_yyyymmdd() {
  local s="$1"
  [[ "$s" =~ ^[0-9]{8}$ ]] || return 1

  local y="${s:0:4}"
  local m="${s:4:2}"
  local d="${s:6:2}"

  local yi=$((10#$y))
  local mi=$((10#$m))
  local di=$((10#$d))

  (( yi >= 1 )) || return 1
  (( mi >= 1 && mi <= 12 )) || return 1
  (( di >= 1 && di <= 31 )) || return 1

  local maxd
  case "$mi" in
    1|3|5|7|8|10|12) maxd=31 ;;
    4|6|9|11)        maxd=30 ;;
    2)
      if is_leap_year "$yi"; then maxd=29; else maxd=28; fi
      ;;
    *) return 1 ;;
  esac

  (( di <= maxd )) || return 1
  return 0
}

if ! is_valid_yyyymmdd "$restore_dbbackup_date"; then
  echo "ERROR: invalid date (expect YYYYMMDD) on the 3rd Parameter: $restore_dbbackup_date" >&2
  exit 1
fi

# 一次讀檔：每行可能有多個 world_id，必須逐欄位處理
declare -a total_arr=()
declare -A set_seen=()

while IFS= read -r line; do
  [[ -n "$line" ]] || continue

  for wid in $line; do
    [[ "$wid" =~ ^[0-9]+$ ]] || continue

    total_arr+=("$wid")
    sid=$((10#$wid / 100))
    set_seen["$sid"]=1
  done
done < "$new_file"

sorted_total="$(printf '%s\n' "${total_arr[@]}" | sort -n | xargs)"
uniq_set_id="$(printf '%s\n' "${!set_seen[@]}" | sort -n | xargs)"

echo "sorted_total=$sorted_total"
echo "uniq_set_id=$uniq_set_id"

# 分組與排序：sorted_s[$set_id] = 該 set 的 world_id 清單（升冪）
declare -A s
declare -A sorted_s

for set_id in $uniq_set_id; do
  s["$set_id"]=""
  sorted_s["$set_id"]=""
done

for wid in "${total_arr[@]}"; do
  sid=$((10#$wid / 100))
  [[ -n "${s[$sid]+x}" ]] || continue
  s["$sid"]+="$wid "
done

for set_id in $uniq_set_id; do
  sorted_s["$set_id"]="$(printf '%s\n' ${s[$set_id]} | sort -n | xargs)"
  echo "sorted_s${set_id}=${sorted_s[$set_id]}"
done

# MACHINE_ALL / MACHINE_AREA（去重）
declare -a MACHINE_ALL_ARR=("MERGE_COMMON")
declare -a MACHINE_AREA_ARR=()
declare -A machine_seen=()

for set_id in $uniq_set_id; do
  area_id=$((10#$set_id / 10))
  case "$area_id" in
    1) MERGE_MACHINE="MERGE_ASIA" ;;
    2) MERGE_MACHINE="MERGE_US"   ;;
    3) MERGE_MACHINE="MERGE_EU"   ;;
    *) continue ;;
  esac

  if [[ -z "${machine_seen[$MERGE_MACHINE]+x}" ]]; then
    MACHINE_ALL_ARR+=("$MERGE_MACHINE")
    MACHINE_AREA_ARR+=("$MERGE_MACHINE")
    machine_seen["$MERGE_MACHINE"]=1
  fi
done

echo "MACHINE_ALL=${MACHINE_ALL_ARR[*]}"
echo "MACHINE_AREA=${MACHINE_AREA_ARR[*]}"

if (( localdb_mode == 1 )); then
  echo "INFO: localdb mode enabled; skip remote DB backup fetch block."
else
  # 合併機建立 DB 還原目錄
  ssh "${SSH_OPTS[@]}" MERGE_COMMON "mkdir -p /tmp/merge_${new_merge_filename}_test/accountdb"
  for machine in "${MACHINE_AREA_ARR[@]}"; do
    ssh "${SSH_OPTS[@]}" "$machine" "mkdir -p /tmp/merge_${new_merge_filename}_test/{gamedb,worlddb}"
  done

  # 同步需要合併日期的 DB 檔案到合併機
  # AccountDB
  sendscript accountdb <<< "cd DBbackup; rsync -avz *${restore_dbbackup_date}* MERGE_COMMON:/tmp/merge_${new_merge_filename}_test/accountdb/." || true

  # GameDB
  for set_id in $uniq_set_id; do
    area_id=$((10#$set_id / 10))
    case "$area_id" in
      1) MERGE_MACHINE="MERGE_ASIA" ;;
      2) MERGE_MACHINE="MERGE_US"   ;;
      3) MERGE_MACHINE="MERGE_EU"   ;;
      *) continue ;;
    esac

    sendscript "ms${set_id}" <<< "cd DBbackup; rsync -avz *${restore_dbbackup_date}* ${MERGE_MACHINE}:/tmp/merge_${new_merge_filename}_test/gamedb/." || true
  done

  # WorldDB
  for set_id in $uniq_set_id; do
    area_id=$((10#$set_id / 10))
    case "$area_id" in
      1) MERGE_MACHINE="MERGE_ASIA" ;;
      2) MERGE_MACHINE="MERGE_US"   ;;
      3) MERGE_MACHINE="MERGE_EU"   ;;
      *) continue ;;
    esac

    [[ -n "${sorted_s[$set_id]}" ]] || continue

    for world_id in ${sorted_s[$set_id]}; do
      ssh "${SSH_OPTS[@]}" "ws${world_id}" \
        "cd DBbackup && rsync -e 'ssh -o StrictHostKeyChecking=no' -avz \
        N1World${world_id}-${restore_dbbackup_date}* \
        ${MERGE_MACHINE}:/tmp/merge_${new_merge_filename}_test/worlddb/."
    done
  done
fi

# 刪除合併機 舊的 DB
for machine in "${MACHINE_ALL_ARR[@]}"; do
  ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/drop_database_for_current_machine_by_pattern postfix _${old_merge_filename}_Pre 0"
  ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/drop_database_for_current_machine_by_pattern postfix _${old_merge_filename}_Post 0"
done

ssh "${SSH_OPTS[@]}" MERGE_COMMON "psql -U postgres -c 'DROP DATABASE IF EXISTS \"N1Account\";'"
ssh "${SSH_OPTS[@]}" MERGE_COMMON "psql -U postgres -c 'DROP DATABASE IF EXISTS \"N1Member\";'"

for machine in "${MACHINE_AREA_ARR[@]}"; do
  ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/drop_database_for_current_machine_by_pattern prefix N1 0"
done

# 還原新的合併 DB
for machine in "${MACHINE_ALL_ARR[@]}"; do
  if [[ "$machine" == "MERGE_COMMON" ]]; then
    ssh "${SSH_OPTS[@]}" "$machine" "cd /tmp/merge_${new_merge_filename}_test/accountdb/; $HOME/bin/create_database_on_local_machine_from_backup_file"
  else
    ssh "${SSH_OPTS[@]}" "$machine" "cd /tmp/merge_${new_merge_filename}_test/gamedb/; $HOME/bin/create_database_on_local_machine_from_backup_file"
    ssh "${SSH_OPTS[@]}" "$machine" "cd /tmp/merge_${new_merge_filename}_test/worlddb/; $HOME/bin/create_database_on_local_machine_from_backup_file"
  fi
done

# 新的合併 DB, Schema 更新 ( AccountDB / GameDB )
for machine in "${MACHINE_ALL_ARR[@]}"; do
  if [[ "$machine" == "MERGE_COMMON" ]]; then
    ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/do_dbpatch_for_current_machine_n1 ACCOUNTDB"
  else
    ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/do_dbpatch_for_current_machine_n1 GAMEDB"
  fi
done

# 更新合併機 GameDB > player_characters::privilege = 5
#for machine in "${MACHINE_ALL_ARR[@]}"; do
#  if [[ "$machine" != "MERGE_COMMON" ]]; then
#    ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/update_gamedb_pcs_privilege_5_for_merge_n1"
#  fi
#done

# 測試合併機 AccountDB 還原測試機最新版本的所有資料表
ssh "${SSH_OPTS[@]}" TEST "$HOME/bin/dump_all_promotion_tables MERGE_COMMON"

# 新的合併, World 相關目錄建立
for machine in "${MACHINE_AREA_ARR[@]}"; do
  ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/test_merge_create_worldserver_directory_n1 ${new_merge_filename}"
done

# 新的合併 DB, Schema 更新 ( WorldDB )
for machine in "${MACHINE_AREA_ARR[@]}"; do
  ssh "${SSH_OPTS[@]}" "$machine" "$HOME/bin/do_dbpatch_for_current_machine_n1 WORLDDB"
done

# 合併 worlds 資料處理
ssh "${SSH_OPTS[@]}" MERGE_COMMON "$HOME/bin/test_merge_update_worlds_n1 ${new_merge_filename}"

