#!/usr/bin/env bash

set -o pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
source "$SCRIPT_DIR/world_server_force_changed.conf"

set +e
source "$HOME/.gamerc"
source_rc=$?
set -e

if (( source_rc != 0 )); then
    echo "ERROR: source \$HOME/.gamerc failed with rc=$source_rc" >&2
    exit 1
fi

#GOOGLE_CHAT_WEBHOOK_URL="https://chat.googleapis.com/v1/spaces/AAAA7hXAOCM/messages?key=AIzaSyDdI0hCZtE6vySjMm-WEfRq3CPzqKqqsHI&token=YupvEeDhNq2aF9ldCAf8TeJw8kmafVAXpj3xJWIzRGw%3D"
WEBHOOK_URL="${GOOGLE_CHAT_WEBHOOK_URL:-}"
MODE="local"

case "${1:-}" in
    --test)
        MODE="test"
        ;;
    --local|"")
        MODE="local"
        ;;
    --allws)
        MODE="allws"
        ;;
    --wsok)
        MODE="wsok"
        WSOK_COUNT="${2:-}"
        ;;
    *)
        echo "Usage: $0 [--test|--local|--allws|--wsok COUNT]" >&2
        exit 1
        ;;
esac

if [[ -z "$WEBHOOK_URL" ]]; then
    echo "ERROR: GOOGLE_CHAT_WEBHOOK_URL is not set in $HOME/.gamerc" >&2
    exit 1
fi

send_gchat() {
    local message="$1"
    local json_payload

    json_payload="$(
        /usr/bin/python3 -c 'import json,sys; print(json.dumps({"text": sys.stdin.read()}))' <<< "$message"
    )"

    /usr/bin/curl -fsS \
        -X POST \
        -H 'Content-Type: application/json; charset=UTF-8' \
        -d "$json_payload" \
        "$WEBHOOK_URL"
}

normalize_grep_raw() {
    local raw="$1"

    printf '%s\n' "$raw" |
    sed -r 's/\x1B\[[0-9;]*[A-Za-z]//g' |
    awk '
    /^WS[0-9_[:alnum:]]+$/ {
        next
    }

    /^\/.*CharacterState.*:.*\[P:.*\]Force Changed/ {
        if (buf != "") {
            print buf
        }
        buf = $0
        next
    }

    /^=> / {
        if (buf != "") {
            buf = buf " " $0
        }
        next
    }

    /^$/ {
        next
    }

    {
        if (buf != "") {
            buf = buf " " $0
        }
    }

    END {
        if (buf != "") {
            print buf
        }
    }'
}

build_summary_from_normalized_raw() {
    local raw="$1"
    [[ -z "$raw" ]] && return

    printf '%s\n' "$raw" |
    awk '
    {
        short_line = $0
        sub(/^.*\/servers[0-9]+\//, "", short_line)

        split(short_line, a, ":")
        file_path = a[1]

        split(file_path, p, "/")
        world_name = p[1]

        world_num = world_name
        sub(/^WorldServer/, "", world_num)

        set_num = int(world_num / 100)
        set_name = "Set" set_num

        dedup_key = set_name SUBSEP short_line
        if (!(dedup_key in seen_detail)) {
            seen_detail[dedup_key] = 1

            if (!(set_name in set_seen)) {
                set_seen[set_name] = 1
                set_order[++set_n] = set_name
            }

            world_key = set_name SUBSEP world_name
            world_count[world_key]++
            set_total[set_name]++
        }
    }

    END {
        for (i = 1; i <= set_n; i++) {
            set_name = set_order[i]

            delete world_seen
            delete world_order
            world_n = 0

            for (k in world_count) {
                split(k, a, SUBSEP)
                if (a[1] != set_name) {
                    continue
                }
                world = a[2]
                if (!(world in world_seen)) {
                    world_seen[world] = 1
                    world_order[++world_n] = world
                }
            }

            for (x = 1; x <= world_n; x++) {
                for (y = x + 1; y <= world_n; y++) {
                    wx = world_order[x]
                    wy = world_order[y]

                    nx = wx
                    ny = wy
                    sub(/^WorldServer/, "", nx)
                    sub(/^WorldServer/, "", ny)

                    if ((nx + 0) > (ny + 0)) {
                        tmp = world_order[x]
                        world_order[x] = world_order[y]
                        world_order[y] = tmp
                    }
                }
            }

            for (j = 1; j <= world_n; j++) {
                world = world_order[j]
                printf "%s\t%s\t%d\n", set_name, world, world_count[set_name SUBSEP world] + 0
            }

            printf "%s\tTOTAL\t%d\n\n", set_name, set_total[set_name] + 0
        }
    }'
}

build_detail_from_normalized_raw() {
    local raw="$1"
    [[ -z "$raw" ]] && return

    printf '%s\n' "$raw" |
    awk '
    {
        short_line = $0
        sub(/^.*\/servers[0-9]+\//, "", short_line)

        split(short_line, a, ":")
        file_path = a[1]

        split(file_path, p, "/")
        world_name = p[1]

        world_num = world_name
        sub(/^WorldServer/, "", world_num)

        set_num = int(world_num / 100)
        set_name = "Set" set_num

        dedup_key = set_name SUBSEP short_line
        if (!(dedup_key in seen_detail)) {
            seen_detail[dedup_key] = 1

            if (!(set_name in set_seen)) {
                set_seen[set_name] = 1
                set_order[++set_n] = set_name
            }

            detail_lines[set_name] = detail_lines[set_name] short_line ORS
            detail_count[set_name]++
        }
    }

    END {
        for (i = 1; i <= set_n; i++) {
            set_name = set_order[i]
            printf "%s\n", set_name
            printf "%s", detail_lines[set_name]
            printf "%s\tDETAIL_TOTAL\t%d\n\n", set_name, detail_count[set_name] + 0
        }
    }'
}

calc_grand_total_from_normalized_raw() {
    local raw="$1"
    [[ -z "$raw" ]] && { echo "0"; return; }

    printf '%s\n' "$raw" |
    awk '
    {
        short_line = $0
        sub(/^.*\/servers[0-9]+\//, "", short_line)

        if (!(short_line in seen)) {
            seen[short_line] = 1
            sum++
        }
    }

    END {
        print sum + 0
    }'
}

build_detail_file_url() {
    local filename="$1"
    printf '%s/%s\n' "${FORCE_CHANGED_DETAIL_BASE_URL%/}" "$filename"
}

now_str="$(date '+%F %T') $(date '+%z' | cut -c1-3)"
title="[${GAME_TYPE}-${COUNTRY_CODE_DISPLAY}] 戰力變動通知"

if [[ "$MODE" == "wsok" ]]; then
    if ! [[ "$WSOK_COUNT" =~ ^[0-9]+$ ]]; then
        WSOK_COUNT="?"
    fi
    send_gchat "[${GAME_TYPE}-${COUNTRY_CODE_DISPLAY}] 正式機 World Servers ( ${WSOK_COUNT} ) 已全數啟動完成
$now_str"
    echo "[notify] ws-startup-complete notification sent (count=${WSOK_COUNT})" >&2
    exit 0
fi

raw=""
normalized_raw=""
summary_report=""
detail_report=""

if [[ "$MODE" == "test" ]]; then
    raw="$(
cat <<'EOF'
WS1001_WHS10011_WHS10012_WORLDDB1001_WWEBSPS10011
/home/n1admin/servers10/WorldServer1001/CharacterState1001.log.0325.144953: 71906,2026/03/25 14:52:38,[P:1001000000229:柴柴地瓜球]Force Changed!! [134719284] => [134729284]
/home/n1admin/servers10/WorldServer1001/CharacterState1001.log.0325.144953: 71907,2026/03/25 14:52:38,[P:1001000001883:曼波曼波]Force Changed!! [189781601] => [189791601]
/home/n1admin/servers10/WorldServer1011/CharacterState1011.log.0325.145001: 38357,2026/03/25 14:51:27,[P:1011000000740:SKH]Force Changed!! [495881149] => [495891149]
/home/n1admin/servers10/WorldServer1081/CharacterState1081.log.0325.145055: 20898,2026/03/25 14:52:39,[P:1081000000817:<RS:textindex69Text>00817]Force Changed!! [16812171]
=> [16822171]
EOF
)"
elif [[ "$MODE" == "local" ]]; then
    raw="$(
        grep -H -E '\[P:.*\]Force Changed!!' "$HOME"/servers*/WorldServer*/CharacterState*log* 2>/dev/null || true
    )"
else
    set +e
    raw="$(
        sendscript allws <<< "grep -H -E '\[P:.*\]Force Changed!!' \$HOME/servers*/WorldServer*/CharacterState*log*" 2>&1
    )"
    sendscript_rc=$?
    set -e

    printf '%s\n' "$raw" > /tmp/notify_force_changed_allws.raw

    if (( sendscript_rc != 0 )); then
        echo "[notify] sendscript allws returned rc=$sendscript_rc, continue with collected output" >&2
    fi

    if [[ -z "$raw" ]]; then
        echo "[notify] sendscript allws produced no output" >&2
        exit 1
    fi
fi

normalized_raw="$(normalize_grep_raw "$raw")"

if [[ "$MODE" == "allws" ]]; then
    printf '%s\n' "$normalized_raw" > /tmp/notify_force_changed_allws.normalized
fi

summary_report="$(build_summary_from_normalized_raw "$normalized_raw")"
detail_report="$(build_detail_from_normalized_raw "$normalized_raw")"
grand_total="$(calc_grand_total_from_normalized_raw "$normalized_raw")"

if [[ "$MODE" == "allws" ]]; then
    printf '%s\n' "$summary_report" > /tmp/notify_force_changed_allws.summary
    printf '%s\n' "$detail_report" > /tmp/notify_force_changed_allws.detail
fi

if [[ -z "$summary_report" ]]; then
    zero_message="$(
cat <<EOF
$title
$now_str
沒有角色有戰力數值的變動!
EOF
)"
    send_gchat "$zero_message"
    echo "[notify] zero-change notification sent in $MODE mode" >&2
    exit 0
fi

if (( grand_total == 0 )); then
    zero_message="$(
cat <<EOF
$title
$now_str
沒有角色有戰力數值的變動!
EOF
)"
    send_gchat "$zero_message"
    echo "[notify] zero-change notification sent in $MODE mode" >&2
    exit 0
fi

detail_url=""
detail_file_path=""

if [[ -n "$detail_report" ]]; then
    mkdir -p "$FORCE_CHANGED_DETAIL_OUTPUT_DIR"

    detail_filename="force_changed_$(date '+%Y%m%d_%H%M%S').txt"
    detail_file_path="$FORCE_CHANGED_DETAIL_OUTPUT_DIR/$detail_filename"

    printf '%s\n' "$detail_report" > "$detail_file_path"
    detail_url="$(build_detail_file_url "$detail_filename")"
fi

summary_message="$(
cat <<EOF
$title
$now_str
加總數目: $grand_total
詳細資訊: ${detail_url:-N/A}

$summary_report
EOF
)"

send_gchat "$summary_message"
echo "[notify] summary notification sent in $MODE mode" >&2

if [[ -n "$detail_url" ]]; then
    echo "[notify] detail file written: $detail_file_path" >&2
    echo "[notify] detail url: $detail_url" >&2
fi
