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

########################################
# merge_update_race_data (PostgreSQL)
#
# 參數:
#   $1: merge_setup.ini 絕對路徑
#
# 行為:
#   - source $HOME/bin/load_merge_db_setup
#   - load_merge_db_setup <merge_setup.ini>
#   - 取得 GameDB 連線資訊
#   - 依 world_order:
#       * 第一個視為 target_world_id
#       * 其餘視為 source_world_ids（去重但保序）
#   - for each source_world_id:
#       在 GameDB 執行兩段 UPDATE：
#         1) guild_race_data.fightrecordata（fightrecords）
#         2) guild_race_data.defendrecordata（defendrecords）
########################################

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_gamedb_value check_gamedb_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"

GAME_HOST="$(get_gamedb_value "GameDBIP")"
GAME_DB="$(get_gamedb_value "GameDB")"
GAME_USER="$(get_gamedb_value "GameDBUser")"
GAME_PASS="$(get_gamedb_value "GameDBPassword")"
GAME_PORT="$(get_gamedb_value "GameDBPort")"
GAME_PORT="${GAME_PORT:-5432}"

if [ -z "$GAME_HOST" ] || [ -z "$GAME_DB" ] || [ -z "$GAME_USER" ]; then
  echo "Error: GameDB connection info missing from $INI_PATH" >&2
  echo "  host='$GAME_HOST' db='$GAME_DB' user='$GAME_USER' port='$GAME_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

export PGHOST="$GAME_HOST"
export PGPORT="$GAME_PORT"
export PGUSER="$GAME_USER"
export PGPASSWORD="${GAME_PASS:-}"

echo "== merge_update_race_data (PostgreSQL) =="
echo "INI             : $INI_PATH"
echo "GameDB Host     : $GAME_HOST:$GAME_PORT"
echo "GameDB Name     : $GAME_DB"
echo "target_world_id : $target_world_id"
echo "source_world_ids: ${source_world_ids_uniq[*]}"
echo

# 連線檢查（使用你 loader 裡的檢查函式）
if ! check_gamedb_connection; then
  echo "Error: GameDB connection check failed." >&2
  exit 1
fi

for source_world_id in "${source_world_ids_uniq[@]}"; do
  echo "Updating guild_race_data: source_world_id=${source_world_id} -> target_world_id=${target_world_id}"

  psql -d "$GAME_DB" -v ON_ERROR_STOP=1 \
    -v source_world_id="$source_world_id" \
    -v target_world_id="$target_world_id" <<'SQL'
BEGIN;

-- 1) fightrecordata / fightrecords
UPDATE guild_race_data AS grd
SET fightrecordata =
  CASE
    WHEN grd.fightrecordata IS NULL THEN
      jsonb_build_object('fightrecords', jsonb_build_object())
    WHEN grd.fightrecordata ? 'fightrecords'
     AND jsonb_typeof(grd.fightrecordata -> 'fightrecords') = 'object'
    THEN
      jsonb_set(
        grd.fightrecordata,
        '{fightrecords}',
        COALESCE(
          (
            SELECT jsonb_object_agg(e.key, v2)
            FROM jsonb_each(grd.fightrecordata -> 'fightrecords') AS e(key, value)
            CROSS JOIN LATERAL (
              SELECT CASE
                WHEN e.value ->> 'challengerworldID' = :'source_world_id' THEN
                  jsonb_set(e.value, '{challengerworldID}', to_jsonb((:'target_world_id')::text), true)
                ELSE e.value
              END AS v1
            ) s1
            CROSS JOIN LATERAL (
              SELECT CASE
                WHEN s1.v1 ->> 'targetworldID' = :'source_world_id' THEN
                  jsonb_set(s1.v1, '{targetworldID}', to_jsonb((:'target_world_id')::text), true)
                ELSE s1.v1
              END AS v2
            ) s2
          ),
          '{}'::jsonb
        ),
        true
      )
    ELSE
      jsonb_set(
        COALESCE(grd.fightrecordata, '{}'::jsonb),
        '{fightrecords}',
        '{}'::jsonb,
        true
      )
  END;

-- 2) defendrecordata / defendrecords
UPDATE guild_race_data AS grd
SET defendrecordata =
  CASE
    WHEN grd.defendrecordata IS NULL THEN
      jsonb_build_object('defendrecords', jsonb_build_object())
    WHEN grd.defendrecordata ? 'defendrecords'
     AND jsonb_typeof(grd.defendrecordata -> 'defendrecords') = 'object'
    THEN
      jsonb_set(
        grd.defendrecordata,
        '{defendrecords}',
        COALESCE(
          (
            SELECT jsonb_object_agg(e.key, v2)
            FROM jsonb_each(grd.defendrecordata -> 'defendrecords') AS e(key, value)
            CROSS JOIN LATERAL (
              SELECT CASE
                WHEN e.value ->> 'challengerworldID' = :'source_world_id' THEN
                  jsonb_set(e.value, '{challengerworldID}', to_jsonb((:'target_world_id')::text), true)
                ELSE e.value
              END AS v1
            ) s1
            CROSS JOIN LATERAL (
              SELECT CASE
                WHEN s1.v1 ->> 'targetworldID' = :'source_world_id' THEN
                  jsonb_set(s1.v1, '{targetworldID}', to_jsonb((:'target_world_id')::text), true)
                ELSE s1.v1
              END AS v2
            ) s2
          ),
          '{}'::jsonb
        ),
        true
      )
    ELSE
      jsonb_set(
        COALESCE(grd.defendrecordata, '{}'::jsonb),
        '{defendrecords}',
        '{}'::jsonb,
        true
      )
  END;

COMMIT;
SQL

done

echo "All updates done."

