<?php

declare(strict_types=1);

use Tournament\Stage\BattleRoyaleAdvancementCalculator;
use Tournament\Scoring\PlacementKillsStrategy;

/**
 * Finalize نتیجه یک Group از Battle Royale
 *
 * قوانین:
 *
 * - placement = 0 یعنی DQ همان Round
 * - placement = 0 نباید Duplicate محسوب شود
 * - بازیکن فقط زمانی DQ نهایی می‌شود که
 *   تمام Resultهای ثبت‌شده او placement = 0 باشند
 * - اگر حداقل یک placement معتبر >= 1 داشته باشد،
 *   بازیکن DQ نهایی نیست
 * - DQها وارد Ranking نمی‌شوند
 * - DQها هیچ‌وقت صعود نمی‌کنند
 * - Placement 1 اجباری نیست
 * - نتیجه Group فقط زمانی Finalize می‌شود که
 *   تمام Roomهای Group completed باشند
 */
function finalizeBRGroupIfComplete(
    PDO $pdo,
    int $roomId
): ?array {

    /*
     * ==========================================
     * Room
     * ==========================================
     */

    $st = $pdo->prepare("
        SELECT
            id,
            stage_id,
            room_number,
            round_number,
            status
        FROM tournament_br_rooms
        WHERE id = ?
        LIMIT 1
    ");

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

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

    if (!$room) {
        return null;
    }

    /*
     * فقط Room completed
     */
    if ((string) ($room['status'] ?? '') !== 'completed') {
        return null;
    }

    $stageId = (int) ($room['stage_id'] ?? 0);
    $groupNumber = (int) ($room['room_number'] ?? 0);

    if (
        $stageId <= 0
        ||
        $groupNumber <= 0
    ) {
        return null;
    }

    /*
     * ==========================================
     * بررسی تمام Roomهای Group
     * ==========================================
     */

    $st = $pdo->prepare("
        SELECT
            COUNT(*) AS total_rooms,

            COALESCE(
                SUM(
                    CASE
                        WHEN status = 'completed'
                        THEN 1
                        ELSE 0
                    END
                ),
                0
            ) AS completed_rooms

        FROM tournament_br_rooms

        WHERE stage_id = ?
          AND room_number = ?
    ");

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

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

    if (!$roomState) {
        return null;
    }

    $totalRooms = (int) (
        $roomState['total_rooms'] ?? 0
    );

    $completedRooms = (int) (
        $roomState['completed_rooms'] ?? 0
    );

    if (
        $totalRooms <= 0
        ||
        $completedRooms !== $totalRooms
    ) {
        return null;
    }

    /*
     * ==========================================
     * جلوگیری از Finalize مجدد
     * ==========================================
     */

    $broadcastType =
        'qualification_result_group_' .
        $groupNumber;

    $st = $pdo->prepare("
        SELECT
            id

        FROM tournament_br_broadcasts

        WHERE stage_id = ?
          AND type = ?

        ORDER BY id DESC

        LIMIT 1
    ");

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

    $existingBroadcast = $st->fetchColumn();

    if ($existingBroadcast !== false) {

        return [
            'already_finalized' => true,

            'broadcast_id' =>
                (int) $existingBroadcast,

            'stage_id' =>
                $stageId,

            'group_number' =>
                $groupNumber,
        ];
    }

    /*
     * ==========================================
     * Stage
     * ==========================================
     */

    $st = $pdo->prepare("
        SELECT
            ts.id,
            ts.name AS stage_name,
            ts.format,
            ts.matches_per_player,
            ts.advancement_type,
            ts.advancement_count,
            ts.scoring_strategy,

            e.name AS event_name

        FROM tournament_stages ts

        INNER JOIN events e
            ON e.id = ts.ev_id

        WHERE ts.id = ?

        LIMIT 1
    ");

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

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

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

    if (
        (string) (
            $stage['format'] ?? ''
        )
        !==
        'battle_royale'
    ) {
        throw new RuntimeException(
            'این Stage از نوع Battle Royale نیست.'
        );
    }

    /*
     * ==========================================
     * Advancement Rules
     * ==========================================
     */

    $advancementType = strtolower(
        trim(
            (string) (
                $stage['advancement_type']
                ?? ''
            )
        )
    );

    $advancementCount = (int) (
        $stage['advancement_count']
        ?? 0
    );

    if (
        $advancementType === ''
        ||
        $advancementCount < 0
    ) {
        throw new RuntimeException(
            'قوانین صعود Stage معتبر نیست.'
        );
    }

    /*
     * ==========================================
     * تعداد Groupهای Stage
     * ==========================================
     */

    $st = $pdo->prepare("
        SELECT
            COUNT(DISTINCT room_number)

        FROM tournament_br_rooms

        WHERE stage_id = ?
          AND room_number > 0
    ");

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

    $groupCount = (int) $st->fetchColumn();

    if ($groupCount <= 0) {
        throw new RuntimeException(
            'هیچ Groupای برای این Stage پیدا نشد.'
        );
    }

    /*
     * ==========================================
     * Participantهای Group
     * ==========================================
     */

    $st = $pdo->prepare("
        SELECT
            rp.tournament_participant_id

        FROM tournament_br_room_participants rp

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

        WHERE br.stage_id = ?
          AND br.room_number = ?

        GROUP BY
            rp.tournament_participant_id

        ORDER BY
            MIN(rp.slot_number) ASC
    ");

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

    $participantIds = array_map(
        'intval',
        $st->fetchAll(PDO::FETCH_COLUMN)
    );

    if (!$participantIds) {
        throw new RuntimeException(
            'هیچ بازیکنی برای این Group پیدا نشد.'
        );
    }

    /*
     * ==========================================
     * Participant + User
     * ==========================================
     */

    $placeholders = implode(
        ', ',
        array_fill(
            0,
            count($participantIds),
            '?'
        )
    );

    $st = $pdo->prepare("
        SELECT
            tp.id AS participant_id,
            tp.status AS participant_status,

            ep.user_id,
            ep.ign

        FROM tournament_participants tp

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

        WHERE tp.id IN (
            {$placeholders}
        )
    ");

    $st->execute($participantIds);

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

    $participantMap = [];

    foreach ($participantRows as $row) {

        $participantId = (int) (
            $row['participant_id']
            ?? 0
        );

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

        $participantMap[$participantId] = $row;
    }

    /*
     * ==========================================
     * تمام نتایج Group
     * ==========================================
     */

    $st = $pdo->prepare("
        SELECT
            br.id AS room_id,
            br.round_number,
            br.map_name,

            rp.id AS room_participant_id,
            rp.tournament_participant_id,

            r.placement,
            r.kills,
            r.score,
            r.status AS result_status

        FROM tournament_br_rooms br

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

        LEFT JOIN tournament_br_results r
            ON r.room_participant_id = rp.id
            AND r.tournament_participant_id =
                rp.tournament_participant_id

        WHERE br.stage_id = ?
          AND br.room_number = ?

        ORDER BY
            br.round_number ASC,
            rp.slot_number ASC
    ");

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

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

    if (!is_array($roundRows)) {
        $roundRows = [];
    }

    /*
     * ==========================================
     * ساخت Playerها
     * ==========================================
     */

    $players = [];

    foreach ($participantIds as $participantId) {

        if (
            !isset(
                $participantMap[$participantId]
            )
        ) {
            continue;
        }

        $participant =
            $participantMap[$participantId];

        $participantStatus = strtolower(
            trim(
                (string) (
                    $participant['participant_status']
                    ?? ''
                )
            )
        );

        $players[$participantId] = [

            'participant_id' =>
                $participantId,

            'user_id' =>
                (int) (
                    $participant['user_id']
                    ?? 0
                ),

            'ign' =>
                (string) (
                    $participant['ign']
                    ?? ''
                ),

            /*
             * اگر قبلاً در DB DQ شده باشد،
             * DQ باقی می‌ماند.
             */
            'is_disqualified' =>
                $participantStatus ===
                'disqualified',

            /*
             * تعداد تمام Resultهای confirmed
             * این بازیکن
             */
            'confirmed_rounds' =>
                0,

            /*
             * تعداد Resultهایی که placement = 0
             */
            'zero_placement_rounds' =>
                0,

            'total_score' =>
                0.0,

            'total_kills' =>
                0,

            'games_played' =>
                0,

            'best_placement' =>
                null,

            'rounds' =>
                [],
        ];
    }

    if (!$players) {
        throw new RuntimeException(
            'هیچ Participant معتبری برای Group پیدا نشد.'
        );
    }

    /*
     * ==========================================
     * Scoring Strategy
     * ==========================================
     */

    $scoringStrategy =
        new PlacementKillsStrategy();

    /*
     * ==========================================
     * محاسبه Score تمام Roundها
     * ==========================================
     */

    foreach ($roundRows as $row) {

        $participantId = (int) (
            $row['tournament_participant_id']
            ?? 0
        );

        if (
            $participantId <= 0
            ||
            !isset(
                $players[$participantId]
            )
        ) {
            continue;
        }

        $placement =
            $row['placement'] !== null
                ? (int) $row['placement']
                : null;

        $kills =
            $row['kills'] !== null
                ? max(0, (int) $row['kills'])
                : 0;

        $resultStatus = strtolower(
            trim(
                (string) (
                    $row['result_status']
                    ?? ''
                )
            )
        );

        $roundScore = 0.0;

        /*
         * فقط Resultهای confirmed
         * در محاسبات نهایی لحاظ می‌شوند.
         */

        if ($resultStatus === 'confirmed') {

            /*
             * یک Result confirmed داریم.
             */
            $players[
                $participantId
            ]['confirmed_rounds']++;

            /*
             * ==================================
             * Placement = 0
             * ==================================
             *
             * فقط این Round DQ است.
             *
             * هنوز بازیکن را DQ نهایی نمی‌کنیم.
             */

            if ($placement === 0) {

                $players[
                    $participantId
                ]['zero_placement_rounds']++;

                $roundScore = 0.0;
            }

            /*
             * ==================================
             * Placement معتبر
             * ==================================
             */

            elseif (
                $placement !== null
                &&
                $placement >= 1
            ) {

                $roundScore =
                    (float) $scoringStrategy->calculateScore([
                        'participant_id' =>
                            $participantId,

                        'placement' =>
                            $placement,

                        'kills' =>
                            $kills,
                    ]);

                $players[
                    $participantId
                ]['total_score'] +=
                    $roundScore;

                $players[
                    $participantId
                ]['total_kills'] +=
                    $kills;

                $players[
                    $participantId
                ]['games_played']++;

                if (
                    $players[
                        $participantId
                    ]['best_placement'] === null

                    ||

                    $placement <
                    $players[
                        $participantId
                    ]['best_placement']
                ) {

                    $players[
                        $participantId
                    ]['best_placement'] =
                        $placement;
                }
            }
        }

        /*
         * ==================================
         * ذخیره نتیجه برای پیام
         * ==================================
         */

        $players[
            $participantId
        ]['rounds'][] = [

            'round_number' =>
                (int) (
                    $row['round_number']
                    ?? 0
                ),

            'map_name' =>
                (string) (
                    $row['map_name']
                    ?? ''
                ),

            'placement' =>
                $placement,

            'kills' =>
                $kills,

            'score' =>
                $roundScore,

            'result_status' =>
                $resultStatus,
        ];
    }

    /*
     * ==========================================
     * تعیین DQ نهایی
     * ==========================================
     *
     * قانون:
     *
     * اگر تمام Resultهای confirmed بازیکن
     * placement = 0 باشند → DQ
     *
     * مثال:
     *
     * 0, 0, 0 → DQ
     *
     * 0, 5, 3 → DQ نیست
     *
     * 4, 0, 2 → DQ نیست
     *
     * 0, 0, 8 → DQ نیست
     */

    foreach ($players as &$player) {

        $confirmedRounds = (int) (
            $player['confirmed_rounds']
            ?? 0
        );

        $zeroPlacementRounds = (int) (
            $player['zero_placement_rounds']
            ?? 0
        );

        /*
         * اگر قبلاً در DB DQ بوده،
         * DQ باقی می‌ماند.
         */

        if (
            $player['is_disqualified']
            === true
        ) {
            continue;
        }

        /*
         * فقط زمانی DQ:
         *
         * confirmed rounds > 0
         * و تمام آنها placement = 0
         */

        if (
            $confirmedRounds > 0
            &&
            $zeroPlacementRounds ===
            $confirmedRounds
        ) {

            $player['is_disqualified'] = true;

        } else {

            $player['is_disqualified'] = false;
        }
    }

    unset($player);

    /*
     * ==========================================
     * جدا کردن Ranking و DQ
     * ==========================================
     */

    $rankingPlayers = array_values(
        array_filter(
            $players,
            static function (
                array $player
            ): bool {

                return
                    ($player['is_disqualified'] ?? false)
                    !== true;
            }
        )
    );

    $disqualifiedPlayers = array_values(
        array_filter(
            $players,
            static function (
                array $player
            ): bool {

                return
                    ($player['is_disqualified'] ?? false)
                    === true;
            }
        )
    );

    /*
     * ==========================================
     * رتبه‌بندی
     * ==========================================
     */

    usort(
        $rankingPlayers,
        static function (
            array $a,
            array $b
        ): int {

            /*
             * Score DESC
             */

            $aScore = (float) (
                $a['total_score']
                ?? 0
            );

            $bScore = (float) (
                $b['total_score']
                ?? 0
            );

            if ($aScore != $bScore) {

                return $bScore <=> $aScore;
            }

            /*
             * Kills DESC
             */

            $aKills = (int) (
                $a['total_kills']
                ?? 0
            );

            $bKills = (int) (
                $b['total_kills']
                ?? 0
            );

            if ($aKills != $bKills) {

                return $bKills <=> $aKills;
            }

            /*
             * Best Placement ASC
             */

            $aPlacement =
                $a['best_placement']
                ??
                PHP_INT_MAX;

            $bPlacement =
                $b['best_placement']
                ??
                PHP_INT_MAX;

            if (
                $aPlacement !=
                $bPlacement
            ) {

                return
                    $aPlacement
                    <=>
                    $bPlacement;
            }

            /*
             * Participant ID ASC
             */

            return
                (int) (
                    $a['participant_id']
                    ?? 0
                )
                <=>
                (int) (
                    $b['participant_id']
                    ?? 0
                );
        }
    );

    /*
     * ==========================================
     * تعیین Rank
     * ==========================================
     */

    foreach (
        $rankingPlayers as $index => &$player
    ) {

        $player['rank'] =
            $index + 1;
    }

    unset($player);

    /*
     * ==========================================
     * DQ Rank
     * ==========================================
     */

    foreach (
        $disqualifiedPlayers as &$player
    ) {

        $player['rank'] = null;

        $player['final_status'] =
            'disqualified';
    }

    unset($player);

    /*
     * ==========================================
     * تعداد Eligible هر Group
     * ==========================================
     */

    $groupEligibleCounts = [];

    /*
     * Groupهای Stage
     */

    $st = $pdo->prepare("
        SELECT
            br.room_number AS group_number,

            COUNT(
                DISTINCT rp.tournament_participant_id
            ) AS player_count

        FROM tournament_br_rooms br

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

        WHERE br.stage_id = ?
          AND br.room_number > 0

        GROUP BY
            br.room_number

        ORDER BY
            br.room_number ASC
    ");

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

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

    if (!is_array($groupRows)) {
        $groupRows = [];
    }

    foreach ($groupRows as $groupRow) {

        $g = (int) (
            $groupRow['group_number']
            ?? 0
        );

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

        $groupEligibleCounts[$g] = 0;
    }

    /*
     * ==========================================
     * محاسبه Eligible
     * ==========================================
     *
     * اینجا فقط tp.status را نگاه نمی‌کنیم،
     * چون DQ همین Group همین الان محاسبه شده
     * و هنوز ممکن است DB status آپدیت نشده باشد.
     *
     * برای Group جاری:
     * از $rankingPlayers استفاده می‌کنیم.
     *
     * برای Groupهای دیگر:
     * وضعیت فعلی DB استفاده می‌شود.
     */

    foreach ($groupRows as $groupRow) {

        $g = (int) (
            $groupRow['group_number']
            ?? 0
        );

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

        /*
         * Group جاری
         */

        if ($g === $groupNumber) {

            $groupEligibleCounts[$g] =
                count($rankingPlayers);

            continue;
        }

        /*
         * Groupهای دیگر
         */

        $st = $pdo->prepare("
            SELECT
                COUNT(DISTINCT tp.id)

            FROM tournament_participants tp

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

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

            WHERE br.stage_id = ?
              AND br.room_number = ?

              AND tp.status <> 'disqualified'
        ");

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

        $groupEligibleCounts[$g] =
            (int) $st->fetchColumn();
    }

    /*
     * ==========================================
     * Calculator
     * ==========================================
     */

    $calculator =
        new BattleRoyaleAdvancementCalculator();

    $groupQuotas =
        $calculator->calculateGroupQuotas(
            $groupEligibleCounts,
            $advancementType,
            $advancementCount
        );

    if (!is_array($groupQuotas)) {
        $groupQuotas = [];
    }

    /*
     * ==========================================
     * سهم Group
     * ==========================================
     */

    $groupQuota = (int) (
        $groupQuotas[$groupNumber]
        ?? 0
    );

    $eligibleCountThisGroup =
        count($rankingPlayers);

    $actualAdvanceCount = min(
        max(0, $groupQuota),
        $eligibleCountThisGroup
    );

    /*
     * ==========================================
     * تعیین Final Status
     * ==========================================
     */

    $qualifiedCount = 0;

    foreach (
        $rankingPlayers as &$player
    ) {

        if (
            $qualifiedCount <
            $actualAdvanceCount
        ) {

            $player['final_status'] =
                'active';

            $qualifiedCount++;

        } else {

            $player['final_status'] =
                'eliminated';
        }
    }

    unset($player);

    /*
     * ==========================================
     * Merge
     * ==========================================
     *
     * Ranking اول
     * DQ بعد از آن
     */

    $allPlayers = array_merge(
        $rankingPlayers,
        $disqualifiedPlayers
    );

    /*
     * ==========================================
     * Transaction
     * ==========================================
     */

    $pdo->beginTransaction();

    try {

        /*
         * ======================================
         * Race Condition Check
         * ======================================
         */

        $st = $pdo->prepare("
            SELECT
                id

            FROM tournament_br_broadcasts

            WHERE stage_id = ?
              AND type = ?

            LIMIT 1

            FOR UPDATE
        ");

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

        $lockedBroadcastId =
            $st->fetchColumn();

        if ($lockedBroadcastId !== false) {

            $pdo->rollBack();

            return [
                'already_finalized' =>
                    true,

                'broadcast_id' =>
                    (int) $lockedBroadcastId,

                'stage_id' =>
                    $stageId,

                'group_number' =>
                    $groupNumber,
            ];
        }

        /*
         * ======================================
         * ساخت Broadcast
         * ======================================
         */

        $st = $pdo->prepare("
            INSERT INTO tournament_br_broadcasts (
                stage_id,
                type,
                status,
                total_users,
                created_at
            )
            VALUES (
                ?,
                ?,
                'queued',
                0,
                NOW()
            )
        ");

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

        $broadcastId =
            (int) $pdo->lastInsertId();

        if ($broadcastId <= 0) {
            throw new RuntimeException(
                'ساخت Broadcast انجام نشد.'
            );
        }

        /*
         * ======================================
         * Queue Statement
         * ======================================
         */

        $insertQueue = $pdo->prepare("
            INSERT INTO tournament_br_broadcast_queue (
                broadcast_id,
                stage_id,
                group_number,
                user_id,
                message_text
            )
            VALUES (
                ?,
                ?,
                ?,
                ?,
                ?
            )
        ");

        $queuedUsers = 0;

        /*
         * ======================================
         * پیام کاربران
         * ======================================
         */

        foreach ($allPlayers as $player) {

            $participantId = (int) (
                $player['participant_id']
                ?? 0
            );

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

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

            $finalStatus = (string) (
                $player['final_status']
                ?? 'eliminated'
            );

            /*
             * ==================================
             * Status Message
             * ==================================
             */

            if (
                $finalStatus ===
                'active'
            ) {

                $statusTitle =
                    '🎉 <b>شما به مرحله بعد صعود کردید!</b>';

                $statusText =
                    'با قرار گرفتن در جمع '
                    . '<b>'
                    . $actualAdvanceCount
                    . ' نفر برتر واجد شرایط این گروه</b>، '
                    . 'به مرحله بعد صعود کردید.';

            } elseif (
                $finalStatus ===
                'disqualified'
            ) {

                $statusTitle =
                    '🚫 <b>شما دیسکوالیفای شدید.</b>';

                $statusText =
                    'تمام راندهای شما با '
                    . '<b>Placement 0</b> '
                    . 'ثبت شده و به همین دلیل '
                    . 'از ادامه مسابقات محروم شدید.';

            } else {

                $statusTitle =
                    '❌ <b>شما از مسابقات حذف شدید.</b>';

                $statusText =
                    'رتبه شما برای صعود به مرحله بعد کافی نبود.';
            }

            /*
             * ==================================
             * Score
             * ==================================
             */

            $scoreValue = (float) (
                $player['total_score']
                ?? 0
            );

            $scoreText = rtrim(
                rtrim(
                    number_format(
                        $scoreValue,
                        2,
                        '.',
                        ','
                    ),
                    '0'
                ),
                '.'
            );

            if ($scoreText === '') {
                $scoreText = '0';
            }

            /*
             * ==================================
             * Names
             * ==================================
             */

            $eventName = htmlspecialchars(
                (string) (
                    $stage['event_name']
                    ?? ''
                ),
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            );

            $stageName = htmlspecialchars(
                (string) (
                    $stage['stage_name']
                    ?? ''
                ),
                ENT_QUOTES |
                ENT_SUBSTITUTE,
                'UTF-8'
            );

            /*
             * DQ رتبه ندارد.
             */

            if (
                $finalStatus ===
                'disqualified'
            ) {

                $rankLine =
                    "🏅 رتبه نهایی گروه: <b>DQ</b>\n";

            } else {

                $rank =
                    (int) (
                        $player['rank']
                        ?? 0
                    );

                $rankLine =
                    "🏅 رتبه نهایی گروه: <b>#"
                    . $rank
                    . " از "
                    . count($rankingPlayers)
                    . "</b>\n";
            }

            /*
             * ==================================
             * Message
             * ==================================
             */

            $txt =
                "<blockquote>🏆 <b>نتیجه نهایی مرحله</b></blockquote>\n\n"

                . "🏆 <b>"
                . $eventName
                . "</b>\n"

                . "🔥 مرحله: <b>"
                . $stageName
                . "</b>\n"

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

                . $statusTitle
                . "\n\n"

                . $statusText
                . "\n\n"

                . $rankLine

                . "⭐ امتیاز نهایی: <b>"
                . $scoreText
                . "</b>\n"

                . "💀 مجموع Kills: <b>"
                . number_format(
                    (int) (
                        $player['total_kills']
                        ?? 0
                    )
                )
                . "</b>\n\n"

                . "━━━━━━━━━━━━\n\n";

            /*
             * ==================================
             * Round Results
             * ==================================
             */

            $playerRounds =
                $player['rounds']
                ?? [];

            if (!is_array($playerRounds)) {
                $playerRounds = [];
            }

            foreach (
                $playerRounds as $round
            ) {

                if (!is_array($round)) {
                    continue;
                }

                $roundNumber = (int) (
                    $round['round_number']
                    ?? 0
                );

                $mapName = trim(
                    (string) (
                        $round['map_name']
                        ?? ''
                    )
                );

                $placement =
                    $round['placement']
                    ?? null;

                $kills = (int) (
                    $round['kills']
                    ?? 0
                );

                $roundScore = (float) (
                    $round['score']
                    ?? 0
                );

                $resultStatus = strtolower(
                    trim(
                        (string) (
                            $round['result_status']
                            ?? ''
                        )
                    )
                );

                $txt .=
                    "<blockquote>🎮 <b>راند "
                    . $roundNumber
                    . "</b></blockquote>\n";

                if ($mapName !== '') {

                    $txt .=
                        "🗺 مپ: <b>"
                        . htmlspecialchars(
                            $mapName,
                            ENT_QUOTES |
                            ENT_SUBSTITUTE,
                            'UTF-8'
                        )
                        . "</b>\n";
                }

                /*
                 * Placement معتبر
                 */

                if (
                    $resultStatus ===
                    'confirmed'
                    &&
                    $placement !== null
                    &&
                    (int) $placement >= 1
                ) {

                    $roundScoreText =
                        rtrim(
                            rtrim(
                                number_format(
                                    $roundScore,
                                    2,
                                    '.',
                                    ','
                                ),
                                '0'
                            ),
                            '.'
                        );

                    if (
                        $roundScoreText === ''
                    ) {
                        $roundScoreText = '0';
                    }

                    $txt .=
                        "🏆 رتبه: <b>#"
                        . (int) $placement
                        . "</b>\n"

                        . "💀 Kills: <b>"
                        . $kills
                        . "</b>\n"

                        . "⭐ امتیاز: <b>"
                        . $roundScoreText
                        . "</b>\n";
                }

                /*
                 * Placement 0
                 *
                 * DQ همان Round
                 */

                elseif (
                    $resultStatus ===
                    'confirmed'
                    &&
                    $placement !== null
                    &&
                    (int) $placement === 0
                ) {

                    $txt .=
                        "🚫 <b>دیسکوالیفای این راند</b>\n"

                        . "💀 Kills: <b>"
                        . $kills
                        . "</b>\n"

                        . "⭐ امتیاز: <b>0</b>\n";
                }

                /*
                 * Result ناقص / ثبت نشده
                 */

                else {

                    $txt .=
                        "⏳ نتیجه این راند ثبت نشده است.\n";
                }

                $txt .= "\n";
            }

            /*
             * ==================================
             * Footer
             * ==================================
             */

            $txt .=
                "━━━━━━━━━━━━\n\n";

            if (
                $finalStatus ===
                'active'
            ) {

                $txt .=
                    "📢 <b>مرحله بعدی</b>\n"
                    . "زمان و اطلاعات مرحله بعد "
                    . "پس از آماده‌سازی اعلام خواهد شد.";

            } elseif (
                $finalStatus ===
                'eliminated'
            ) {

                $txt .=
                    "🙏 از حضور شما در این تورنومنت متشکریم.";

            } else {

                $txt .=
                    "🚫 این نتیجه به دلیل دیسکوالیفای شدن شما ثبت شده است.";
            }

            /*
             * ==================================
             * Insert Queue
             * ==================================
             */

            $insertQueue->execute([
                $broadcastId,
                $stageId,
                $groupNumber,
                $userId,
                $txt
            ]);

            $queuedUsers++;
        }

        /*
         * ======================================
         * Update Broadcast Count
         * ======================================
         */

        $st = $pdo->prepare("
            UPDATE tournament_br_broadcasts

            SET
                total_users = ?

            WHERE id = ?
        ");

        $st->execute([
            $queuedUsers,
            $broadcastId
        ]);

        /*
         * ======================================
         * Commit
         * ======================================
         */

        $pdo->commit();

    } catch (Throwable $e) {

        if ($pdo->inTransaction()) {
            $pdo->rollBack();
        }

        throw $e;
    }

    /*
     * ==========================================
     * Return
     * ==========================================
     */

    return [
        'already_finalized' =>
            false,

        'broadcast_id' =>
            $broadcastId,

        'stage_id' =>
            $stageId,

        'group_number' =>
            $groupNumber,

        'group_count' =>
            $groupCount,

        'stage_advancement_count' =>
            $advancementCount,

        'group_quota' =>
            $groupQuota,

        'eligible_count' =>
            $eligibleCountThisGroup,

        'actual_advance_count' =>
            $actualAdvanceCount,

        'total_users' =>
            $queuedUsers,
    ];
}