#!/usr/bin/env bash
set -euo pipefail

########################################
# merge_update_real_world_id_for_source_wids_on_fake_worlds (PostgreSQL)
#
# 參數:
#   $1: merge_setup.ini 絕對路徑
#
# 行為:
#   - source $HOME/bin/load_merge_db_setup
#   - load_merge_db_setup <merge_setup.ini>
#   - 取得 AccountDB 連線資訊
#   - 依 world_order:
#       * 第一個視為 target_world_id
#       * 其餘視為 source_world_ids（去重但保序）
#       * 產生 source_world_ids_str（逗點分隔）
#   - 連線 AccountDB 執行：
#       UPDATE fake_worlds
#       SET real_world_id = target_world_id
#       WHERE real_world_id IN (source_world_ids_str);
#   - 回報更新筆數
########################################

if [ "$#" -ne 1 ]; then
  echo "Usage: $0 <ABS_merge_setup.ini>" >&2
  exit 1
fi

INI_PATH="$1"

if [ ! -f "$INI_PATH" ]; then
  echo "Error: merge_setup.ini not found: $INI_PATH" >&2
  exit 1
fi
if [ ! -s "$INI_PATH" ]; then
  echo "Error: merge_setup.ini is empty: $INI_PATH" >&2
  exit 1
fi

LOADER="$HOME/bin/load_merge_db_setup"
if [ ! -f "$LOADER" ]; then
  echo "Error: loader not found: $LOADER" >&2
  exit 1
fi

# shellcheck source=/dev/null
source "$LOADER"

for fn in load_merge_db_setup get_accountdb_value check_accountdb_connection; do
  if ! declare -F "$fn" >/dev/null 2>&1; then
    echo "Error: function '$fn' not found after sourcing $LOADER" >&2
    exit 1
  fi
done

load_merge_db_setup "$INI_PATH"

ACCOUNT_HOST="$(get_accountdb_value "AccountDBIP")"
ACCOUNT_DB="$(get_accountdb_value "AccountDBName")"
ACCOUNT_USER="$(get_accountdb_value "AccountDBUser")"
ACCOUNT_PASS="$(get_accountdb_value "AccountDBPW")"
ACCOUNT_PORT="$(get_accountdb_value "AccountDBPort")"
ACCOUNT_PORT="${ACCOUNT_PORT:-5432}"

if [ -z "$ACCOUNT_HOST" ] || [ -z "$ACCOUNT_DB" ] || [ -z "$ACCOUNT_USER" ]; then
  echo "Error: AccountDB connection info missing from $INI_PATH" >&2
  echo "  host='$ACCOUNT_HOST' db='$ACCOUNT_DB' user='$ACCOUNT_USER' port='$ACCOUNT_PORT'" >&2
  exit 1
fi

if [ "${#world_order[@]}" -lt 2 ]; then
  echo "Error: need at least 2 WorldID entries in merge_setup.ini." >&2
  echo "  world_order count: ${#world_order[@]}" >&2
  exit 1
fi

target_world_id="${world_order[0]}"
source_world_ids=( "${world_order[@]:1}" )

# 去重但保序
declare -A SEEN=()
declare -a source_world_ids_uniq=()
for wid in "${source_world_ids[@]}"; do
  if [[ -z "${SEEN[$wid]+x}" ]]; then
    SEEN["$wid"]=1
    source_world_ids_uniq+=( "$wid" )
  fi
done

if [ "${#source_world_ids_uniq[@]}" -eq 0 ]; then
  echo "No source world ids after ignoring target_world_id=${target_world_id}. Nothing to do."
  exit 0
fi

# 基本安全檢查：世界 ID 預期為數字（避免注入 & 非預期字串）
if ! [[ "$target_world_id" =~ ^[0-9]+$ ]]; then
  echo "Error: target_world_id is not numeric: '$target_world_id'" >&2
  exit 1
fi
for wid in "${source_world_ids_uniq[@]}"; do
  if ! [[ "$wid" =~ ^[0-9]+$ ]]; then
    echo "Error: source_world_id is not numeric: '$wid'" >&2
    exit 1
  fi
done

# 逗點分隔（例如：1002,1003,1004）
source_world_ids_str="$(IFS=','; printf '%s' "${source_world_ids_uniq[*]}")"

export PGHOST="$ACCOUNT_HOST"
export PGPORT="$ACCOUNT_PORT"
export PGUSER="$ACCOUNT_USER"
export PGPASSWORD="${ACCOUNT_PASS:-}"

echo "== merge_update_real_world_id_for_source_wids_on_fake_worlds (PostgreSQL) =="
echo "INI               : $INI_PATH"
echo "AccountDB Host    : $ACCOUNT_HOST:$ACCOUNT_PORT"
echo "AccountDB Name    : $ACCOUNT_DB"
echo "target_world_id   : $target_world_id"
echo "source_world_ids  : ${source_world_ids_uniq[*]}"
echo "source_world_ids_str: $source_world_ids_str"
echo

if ! check_accountdb_connection; then
  echo "Error: AccountDB connection check failed." >&2
  exit 1
fi

echo "Updating fake_worlds.real_world_id: (${source_world_ids_str}) -> ${target_world_id}"
echo

# 注意：
# - 你需求寫的是 IN (${source_world_ids_str})
# - 這裡用 ANY(string_to_array(...)) 避免把整段 IN list 直接拼 SQL（在已做數字檢查下等價且更穩）
psql -d "$ACCOUNT_DB" -v ON_ERROR_STOP=1 -X -t -A \
  -v target_world_id="$target_world_id" \
  -v source_world_ids_str="$source_world_ids_str" <<'SQL'
BEGIN;

WITH u AS (
  UPDATE fake_worlds
  SET real_world_id = (:'target_world_id')::int
  WHERE real_world_id = ANY(string_to_array(:'source_world_ids_str', ',')::int[])
  RETURNING 1
)
SELECT 'updated rows: ' || count(*) FROM u;

COMMIT;
SQL

echo "All updates done."

