<?php

declare(strict_types=1);

/**
 * ارسال زمان‌بندی Custom Roomهای یک Stage
 * به تمام بازیکنان هر Group.
 *
 * هر Group یک پیام دریافت می‌کند
 * که شامل Round 1 و Round 2 همان Group است.
 *
 * @return array{
 *     stage_id:int,
 *     groups:int,
 *     groups_sent:int,
 *     users_total:int,
 *     users_sent:int,
 *     users_failed:int,
 *     skipped_groups:int
 * }
 */
function sendBRRoomScheduleBroadcast(
    PDO $pdo,
    int $stageId,
    callable $sendMessage
): array {
    /*
     * ==========================================
     * Stage + Event
     * ==========================================
     */
    $st = $pdo->prepare("
        SELECT
            ts.id,
            ts.ev_id,
            ts.name AS stage_name,
            e.name AS event_name
        FROM tournament_stages ts
        INNER JOIN events e
            ON e.id = ts.ev_id
        WHERE ts.id = ?
          AND ts.format = 'battle_royale'
        LIMIT 1
    ");

    $st->execute([
        $stageId
    ]);

    $stage =
        $st->fetch(PDO::FETCH_ASSOC);

    if (!$stage) {
        throw new RuntimeException(
            'Battle Royale Stage پیدا نشد.'
        );
    }

    /*
     * ==========================================
     * Rooms
     * ==========================================
     */
    $st = $pdo->prepare("
        SELECT
            id,
            round_number,
            room_number,
            scheduled_at,
            map_name,
            status
        FROM tournament_br_rooms
        WHERE stage_id = ?
          AND round_number IN (1, 2)
        ORDER BY
            room_number ASC,
            round_number ASC
    ");

    $st->execute([
        $stageId
    ]);

    $rooms =
        $st->fetchAll(PDO::FETCH_ASSOC);

    if (!$rooms) {
        throw new RuntimeException(
            'هیچ Roomای برای این Stage پیدا نشد.'
        );
    }

    /*
     * ==========================================
     * Group Rooms
     * ==========================================
     */
    $groups = [];

    foreach ($rooms as $room) {

        $groupNumber =
            (int) $room['room_number'];

        $round =
            (int) $room['round_number'];

        if ($groupNumber <= 0) {
            continue;
        }

        if (!isset($groups[$groupNumber])) {
            $groups[$groupNumber] = [];
        }

        $groups[$groupNumber][$round] =
            $room;
    }

    ksort(
        $groups,
        SORT_NUMERIC
    );

    /*
     * ==========================================
     * Participants
     * ==========================================
     *
     * Group از room_number گرفته می‌شود.
     *
     * DISTINCT باعث می‌شود یک User
     * برای یک Group دوبار دریافت نشود.
     */
    $st = $pdo->prepare("
        SELECT DISTINCT

            br.room_number AS group_number,

            ep.user_id,

            ep.ign

        FROM tournament_br_room_participants rp

        INNER JOIN tournament_br_rooms br
            ON br.id = rp.room_id

        INNER JOIN tournament_participants tp
            ON tp.id =
                rp.tournament_participant_id

        INNER JOIN event_players ep
            ON ep.id =
                tp.event_player_id

        WHERE br.stage_id = ?
          AND br.round_number IN (1, 2)
          AND ep.user_id IS NOT NULL

        ORDER BY
            br.room_number ASC,
            ep.user_id ASC
    ");

    $st->execute([
        $stageId
    ]);

    $participantRows =
        $st->fetchAll(PDO::FETCH_ASSOC);

    /*
     * ==========================================
     * Group Users
     * ==========================================
     */
    $groupUsers = [];

    foreach (
        $participantRows as $row
    ) {

        $groupNumber =
            (int) (
                $row['group_number']
                ?? 0
            );

        $userId =
            (int) (
                $row['user_id']
                ?? 0
            );

        if (
            $groupNumber <= 0
            || $userId <= 0
        ) {
            continue;
        }

        if (
            !isset(
                $groupUsers[$groupNumber]
            )
        ) {
            $groupUsers[$groupNumber] = [];
        }

        $groupUsers[
            $groupNumber
        ][$userId] =
            (string) (
                $row['ign']
                ?? ''
            );
    }

    /*
     * ==========================================
     * Statistics
     * ==========================================
     */
    $groupsSent = 0;
    $usersTotal = 0;
    $usersSent = 0;
    $usersFailed = 0;
    $skippedGroups = 0;

    /*
     * ==========================================
     * Time Formatter
     * ==========================================
     */
    $formatSchedule =
        static function (
            array $room
        ): ?array {

            if (
                empty(
                    $room['scheduled_at']
                )
            ) {
                return null;
            }

            $scheduledAt =
                (string) $room[
                    'scheduled_at'
                ];

            try {

                $dateTime =
                    new DateTime(
                        $scheduledAt,
                        new DateTimeZone(
                            'Asia/Tehran'
                        )
                    );

                $timestamp =
                    $dateTime->getTimestamp();

                return [
                    'date' =>
                        jdate(
                            'j F Y',
                            $timestamp,
                            '',
                            'Asia/Tehran'
                        ),

                    'time' =>
                        jdate(
                            'H:i',
                            $timestamp,
                            '',
                            'Asia/Tehran'
                        ),

                    'timestamp' =>
                        $timestamp,

                    'map' =>
                        trim(
                            (string) (
                                $room['map_name']
                                ?? ''
                            )
                        ),
                ];

            } catch (Throwable) {

                return null;
            }
        };

    /*
     * ==========================================
     * Group Broadcast
     * ==========================================
     */
    foreach (
        $groups as $groupNumber =>
        $roundRooms
    ) {

        /*
         * هر دو Round باید وجود داشته باشند.
         */
        if (
            !isset(
                $roundRooms[1],
                $roundRooms[2]
            )
        ) {
            $skippedGroups++;
            continue;
        }

        $round1 =
            $formatSchedule(
                $roundRooms[1]
            );

        $round2 =
            $formatSchedule(
                $roundRooms[2]
            );

        /*
         * هر دو زمان باید تنظیم شده باشند.
         */
        if (
            !$round1
            || !$round2
        ) {
            $skippedGroups++;
            continue;
        }

        /*
         * ======================================
         * Group Users
         * ======================================
         */
        $users =
            $groupUsers[
                $groupNumber
            ]
            ?? [];

        if (!$users) {
            $skippedGroups++;
            continue;
        }

        $usersTotal +=
            count($users);

        /*
         * ======================================
         * Map
         * ======================================
         */
        $map1 =
            $round1['map']
            !== ''
                ? $round1['map']
                : 'تعیین نشده';

        $map2 =
            $round2['map']
            !== ''
                ? $round2['map']
                : 'تعیین نشده';

        /*
         * ======================================
         * Date
         * ======================================
         */
        $sameDate =
            $round1['date']
            ===
            $round2['date'];

        /*
         * تاریخ Round 1
         */
        $round1DateText =
            $round1['date'];

        $round2DateText =
            $round2['date'];

        /*
         * ======================================
         * Message
         * ======================================
         */
        $txt =
            "<blockquote>🎮 <b>زمان برگزاری مسابقات شما</b></blockquote>\n\n"

            . "🏆 <b>"
            . htmlspecialchars(
                (string) (
                    $stage[
                        'event_name'
                    ]
                    ?? 'Tournament'
                ),
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            )
            . "</b>\n"

            . "🔥 مرحله: <b>"
            . htmlspecialchars(
                (string) (
                    $stage[
                        'stage_name'
                    ]
                    ?? 'Qualification'
                ),
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            )
            . "</b>\n"

            . "👥 گروه شما: <b>Group "
            . $groupNumber
            . "</b>\n\n"


            . "<blockquote>🎯 <b>راند اول</b></blockquote>\n"
            . "📅 تاریخ: <b>"
            . htmlspecialchars(
                $round1DateText,
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            )
            . "</b>\n"
            . "🗺 مپ: <b>"
            . htmlspecialchars(
                $map1,
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            )
            . "</b>\n"
            . "🕒 ساعت شروع: <b>"
            . $round1['time']
            . "</b>\n\n"

            . "<blockquote>🎯 <b>راند دوم</b></blockquote>\n"
            . "📅 تاریخ: <b>"
            . htmlspecialchars(
                $round2DateText,
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            )
            . "</b>\n"
            . "🗺 مپ: <b>"
            . htmlspecialchars(
                $map2,
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            )
            . "</b>\n"
            . "🕒 ساعت شروع: <b>"
            . $round2['time']
            . "</b>\n\n"


            . "<blockquote>⏱ این دو راند <b>پشت سر هم</b> برگزار می‌شوند و ممکن است مجموع برگزاری مسابقات حدود <b>۲ ساعت</b> زمان ببرد.</blockquote>\n\n"

            . "<blockquote>📩 <b>ایدی و پسورد هر روم</b> قبل از شروع، به صورت شخصی برای شما ارسال می‌شود.</blockquote>\n\n"

            . "<blockquote>📥 حتماً مپ‌های اعلام‌شده را از قبل دانلود و آماده داشته باشید.</blockquote>\n\n"

            . "<blockquote>⚠️ در صورت تأخیر بیش از <b>۵ دقیقه</b> در ورود به Room، از ادامه مسابقات حذف خواهید شد.</blockquote>\n\n"

            . "<blockquote>✅ لطفاً چند دقیقه قبل از زمان اعلام‌شده آنلاین و آماده باشید.</blockquote>";

        /*
         * ======================================
         * Send to Users
         * ======================================
         */

        $users = [
            1373340301 => ($users[1373340301] ?? 'Test User')
        ];
        
        foreach (
            $users as $userId => $ign
        ) {

            try {

                $result =
                    $sendMessage(
                        (int) $userId,
                        $txt
                    );

                /*
                 * در صورت API استاندارد Telegram
                 */
                if (
                    is_array($result)
                    && (
                        !isset($result['ok'])
                        || $result['ok'] === true
                    )
                ) {
                    $usersSent++;

                } else {
                    $usersFailed++;
                }

            } catch (Throwable $e) {

                $usersFailed++;

                error_log(
                    '[BR SCHEDULE BROADCAST ERROR] '
                    . 'stage=' . $stageId
                    . ' group=' . $groupNumber
                    . ' user=' . $userId
                    . ' error=' . $e->getMessage()
                );
            }
        }

        $groupsSent++;
    }

    return [
        'stage_id' =>
            $stageId,

        'groups' =>
            count($groups),

        'groups_sent' =>
            $groupsSent,

        'users_total' =>
            $usersTotal,

        'users_sent' =>
            $usersSent,

        'users_failed' =>
            $usersFailed,

        'skipped_groups' =>
            $skippedGroups,
    ];
}