<?php

declare(strict_types=1);

function createBRScheduleBroadcast(
    PDO $pdo,
    int $stageId,
    ?int $onlyUserId = null,
    ?int $createdBy = null
): array {

    /*
     * ==========================================
     * Stage
     * ==========================================
     */
    $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
     * ==========================================
     *
     * تمام Roundهای Stage گرفته می‌شوند.
     */
    $st = $pdo->prepare("
        SELECT
            id,
            round_number,
            room_number,
            scheduled_at,
            map_name
        FROM tournament_br_rooms
        WHERE stage_id = ?
        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 / Round
     * ==========================================
     */
    $groups = [];

    foreach ($rooms as $room) {

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

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

        if (
            $group <= 0
            ||
            $round <= 0
        ) {
            continue;
        }

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

    ksort(
        $groups,
        SORT_NUMERIC
    );

    /*
     * ==========================================
     * تعداد Roundهای واقعی
     * ==========================================
     */
    $allRounds = [];

    foreach ($groups as $rounds) {

        foreach ($rounds as $roundNumber => $room) {
            $allRounds[(int) $roundNumber] = true;
        }
    }

    $roundNumbers =
        array_keys($allRounds);

    sort(
        $roundNumbers,
        SORT_NUMERIC
    );

    $totalRounds =
        count($roundNumbers);

    if ($totalRounds < 1) {
        throw new RuntimeException(
            'هیچ Round معتبری برای این Stage پیدا نشد.'
        );
    }

    /*
     * ==========================================
     * Users
     * ==========================================
     *
     * هر User فقط یک بار برای Group خودش.
     */
    $st = $pdo->prepare("
        SELECT DISTINCT
            br.room_number AS group_number,
            ep.user_id

        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 ep.user_id IS NOT NULL

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

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

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

    $groupUsers = [];

    foreach ($rows as $row) {

        $group =
            (int) $row['group_number'];

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

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

        if (
            $onlyUserId !== null
            &&
            $userId !== $onlyUserId
        ) {
            continue;
        }

        $groupUsers[$group][$userId] = true;
    }

    /*
     * ==========================================
     * هیچ کاربری پیدا نشد
     * ==========================================
     */
    if (!$groupUsers) {
        return [
            'broadcast_id' => 0,
            'stage_id' => $stageId,
            'groups' => 0,
            'users' => 0,
        ];
    }

    /*
     * ==========================================
     * ساخت Broadcast
     * ==========================================
     */
    $pdo->beginTransaction();

    try {

        $insertBroadcast = $pdo->prepare("
            INSERT INTO tournament_br_broadcasts (
                stage_id,
                type,
                status,
                created_by
            )
            VALUES (
                ?,
                'room_schedule',
                'queued',
                ?
            )
        ");

        $insertBroadcast->execute([
            $stageId,
            $createdBy
        ]);

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

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

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

        $totalUsers = 0;
        $groupsQueued = 0;

        /*
         * ==========================================
         * Groupها
         * ==========================================
         */
        foreach (
            $groups as $groupNumber => $rounds
        ) {

            /*
             * فقط Roundهای معتبر و زمان‌بندی‌شده
             */
            $validRounds = [];

            foreach (
                $roundNumbers as $roundNumber
            ) {

                if (
                    !isset(
                        $rounds[$roundNumber]
                    )
                ) {
                    continue;
                }

                $room =
                    $rounds[$roundNumber];

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

                $validRounds[
                    $roundNumber
                ] = $room;
            }

            /*
             * اگر هیچ Round زمان‌بندی‌شده‌ای نیست
             */
            if (!$validRounds) {
                continue;
            }

            /*
             * ======================================
             * Header
             * ======================================
             */
            $message =
                "<blockquote>"
                . "🎮 <b>برنامه مسابقات شما</b>"
                . "</blockquote>\n\n"

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

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

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

                . "⚠️ <b>مسابقه شما شامل "
                . $totalRounds
                . " راند است.</b>\n"
                . "هر راند در یک مپ برگزار می‌شود و "
                . "<b>نتیجه مجموع تمام راندها</b> "
                . "در نتیجه نهایی شما محاسبه خواهد شد.\n\n";

            /*
             * ======================================
             * Roundها
             * ======================================
             */
            $displayRound = 0;

            foreach (
                $validRounds as $roundNumber => $room
            ) {

                $displayRound++;

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

                if ($scheduledAt === false) {
                    continue;
                }

                $roundDate =
                    jdate(
                        'j F Y',
                        $scheduledAt,
                        '',
                        'Asia/Tehran'
                    );

                $roundTime =
                    jdate(
                        'H:i',
                        $scheduledAt,
                        '',
                        'Asia/Tehran'
                    );

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

                if ($map === '') {
                    $map =
                        'تعیین نشده';
                }

                $message .=
                    "<blockquote>"
                    . "🎯 <b>راند "
                    . $displayRound
                    . "</b>\n"
                    . "🗺 <b>"
                    . htmlspecialchars(
                        $map,
                        ENT_QUOTES |
                        ENT_SUBSTITUTE,
                        'UTF-8'
                    )
                    . "</b>"
                    . "</blockquote>\n"

                    . "📅 تاریخ: <b>"
                    . htmlspecialchars(
                        $roundDate,
                        ENT_QUOTES |
                        ENT_SUBSTITUTE,
                        'UTF-8'
                    )
                    . "</b>\n"

                    . "🕒 ساعت شروع: <b>"
                    . $roundTime
                    . "</b>\n\n";
            }

            /*
             * ======================================
             * توضیحات
             * ======================================
             */
            $message .=
                "<blockquote>"
                . "📊 <b>امتیاز نهایی شما بر اساس "
                . "مجموع عملکرد در هر "
                . $totalRounds
                . " راند محاسبه می‌شود.</b>"
                . "</blockquote>\n\n"

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

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

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

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

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

            if (!$users) {
                continue;
            }

            $groupsQueued++;

            foreach (
                array_keys($users) as $userId
            ) {

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

                if (
                    $insertQueue->rowCount() > 0
                ) {
                    $totalUsers++;
                }
            }
        }

        /*
         * ==========================================
         * تعداد کل
         * ==========================================
         */
        $update = $pdo->prepare("
            UPDATE tournament_br_broadcasts
            SET
                total_users = ?
            WHERE id = ?
        ");

        $update->execute([
            $totalUsers,
            $broadcastId
        ]);

        /*
         * ==========================================
         * اگر Queue خالی بود
         * ==========================================
         */
        if ($totalUsers === 0) {

            $pdo->prepare("
                UPDATE tournament_br_broadcasts
                SET
                    status = 'completed',
                    completed_at = NOW()
                WHERE id = ?
            ")->execute([
                $broadcastId
            ]);
        }

        /*
         * ==========================================
         * Commit
         * ==========================================
         */
        $pdo->commit();

        return [
            'broadcast_id' =>
                $broadcastId,

            'stage_id' =>
                $stageId,

            'groups' =>
                $groupsQueued,

            'users' =>
                $totalUsers,÷÷÷÷

            'rounds' =>
                $totalRounds,
        ];

    } catch (Throwable $e) {

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

        throw $e;
    }
}