<!DOCTYPE html>
<html lang="id">
<!--begin::Head-->

<head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />

    <!-- Default values (akan diubah JS) -->
    <title>Loading...</title>
    <meta name="description" content="Memuat data toko..." />

    <!-- Favicon default -->
    <link id="dynamic-favicon" rel="icon" href="icons/logo_placeholder.png" type="image/png" />

    <!-- OG Meta default -->
    <meta property="og:title" content="Loading..." />
    <meta property="og:description" content="Memuat data toko..." />
    <meta property="og:type" content="website" />
    <meta property="og:url" content="" />
    <meta property="og:image" content="icons/logo_placeholder.png" />
    <meta property="og:site_name" content="Aplikasi Toko" />

    <!-- Twitter Meta -->
    <meta name="twitter:card" content="summary_large_image" />
    <meta name="twitter:title" content="Loading..." />
    <meta name="twitter:description" content="Memuat data toko..." />
    <meta name="twitter:image" content="icons/logo_placeholder.png" />

    <?php include_once("assets/addon/icon_css.php"); ?>
</head>
<!--end::Head-->
<!--begin::Custom Style-->
<style>
    .hover-elevate:hover {
        transform: translateY(-3px);
        box-shadow: 0 6px 16px rgba(0, 0, 0, 0.12);
        transition: all 0.2s ease-in-out;
    }

    .status-badge {
        font-size: 0.85rem;
        padding: 0.5rem 1rem;
        border-radius: 0.3rem;
    }

    .steps-container {
        display: flex;
        justify-content: space-between;
        align-items: center;
        margin-bottom: 2rem;
        padding: 1.5rem;
        background: #F3F6F9;
        border-radius: 0.5rem;
    }

    .step-item {
        text-align: center;
        flex: 1;
        padding: 0.5rem;
    }

    .step-item.active {
        color: #007bff;
        font-weight: 600;
    }

    .step-item.disabled {
        color: #ccc;
    }

    .step-divider {
        flex: 0 0 2rem;
        height: 2px;
        background: #E4E6EF;
        margin: 0 -1rem;
    }

    .section-tabs {
        display: flex;
        gap: 0.5rem;
        margin-bottom: 1.5rem;
        flex-wrap: wrap;
    }

    .section-tab {
        padding: 0.75rem 1.5rem;
        border: 1px solid #E4E6EF;
        background: #fff;
        cursor: pointer;
        border-radius: 0.3rem;
        transition: all 0.2s;
    }

    .section-tab.active {
        background: #007bff;
        color: #fff;
        border-color: #007bff;
    }

    .section-tab:disabled {
        opacity: 0.5;
        cursor: not-allowed;
    }

    .category-level-entry {
        display: flex;
        gap: 1rem;
        align-items: flex-end;
        margin-bottom: 1rem;
        padding: 1rem;
        background: #f8f9fa;
        border-radius: 0.3rem;
        border-left: 3px solid #007bff;
    }

    .category-level-entry .col {
        flex: 1;
    }

    .section-indicator {
        display: inline-block;
        margin-top: 0.5rem;
        font-size: 0.85rem;
        padding: 0.35rem 0.6rem;
        border-radius: 0.35rem;
    }

    .category-level-entry .form-label {
        font-size: 0.875rem;
        margin-bottom: 0.5rem;
    }

    .btn-remove-entry {
        white-space: nowrap;
    }

    .empty-category-level-message {
        text-align: center;
        padding: 2rem;
        background: #f8f9fa;
        border-radius: 0.3rem;
        color: #6c757d;
    }


    /* Responsive Bracket */
    .bracket-container {
        display: flex;
        align-items: flex-start;
        gap: 60px;
        overflow-x: auto;
    }

    .bracket-round {
        display: flex;
        flex-direction: column;
        position: relative;
    }

    .round-title {
        text-align: center;
        font-weight: bold;
        margin-bottom: 20px;
    }

    /* MAGIC CENTERING SYSTEM */
    .match-wrapper {
        position: relative;
        margin: calc(40px * var(--spacing)) 0;
    }

    .match-box {
        width: 220px;
        background: #fff;
        border: 1px solid #ccc;
        border-radius: 6px;
        padding: 10px;
        box-shadow: 0 2px 6px rgba(0, 0, 0, 0.05);
    }

    .team-row {
        display: flex;
        justify-content: space-between;
        font-size: 14px;
    }

    .winner {
        font-weight: bold;
        color: #198754;
    }

    .score-divider {
        border-top: 1px solid #ccc;
        margin-top: 6px;
        padding-top: 4px;
        font-size: 12px;
        font-weight: bold;
    }

    .sets {
        font-size: 12px;
        margin-top: 4px;
    }

    /* Horizontal line to next round */
    .connector-horizontal {
        position: absolute;
        right: -60px;
        top: 50%;
        width: 60px;
        height: 2px;
        background: #999;
    }
</style>
<!--end::Custom Style-->
<!--begin::Body-->

<body id="kt_body" class="header-extended header-fixed header-tablet-and-mobile-fixed">

    <!--begin::Main-->
    <!--begin::Root-->
    <div class="d-flex flex-column flex-root">
        <!--begin::Page-->
        <div class="page d-flex flex-row flex-column-fluid">
            <!--begin::Wrapper-->
            <div class="wrapper d-flex flex-column flex-row-fluid" id="kt_wrapper">
                <!--begin::Header-->
                <?php include_once("assets/addon/header.php"); ?>
                <!--end::Header-->

                <!--begin::Container-->
                <div id="kt_content_container" class="d-flex flex-column-fluid align-items-start container-xxl">
                    <!--begin::Post-->
                    <div class="content flex-row-fluid" id="kt_content">

                        <!--begin::Breadcrumb-->
                        <div id="breadcrumb_container"></div>
                        <!--end::Breadcrumb-->

                        <!-- Status Display -->
                        <div class="row mb-4" id="statusDisplaySection" style="display:none;">
                            <div class="col-12">
                                <div class="d-flex justify-content-between align-items-center">
                                    <h4 class="fw-bold mb-0">Tournament: <span id="tournamentTitle"></span></h4>
                                    <span id="statusBadge" class="badge status-badge"></span>
                                </div>
                            </div>
                        </div>

                        <!-- Status Flow Steps -->
                        <div class="row mb-4" id="stepsSection" style="display:none;">
                            <div class="col-12">
                                <div class="steps-container">
                                    <div class="step-item active" data-step="draft">
                                        <i class="fas fa-file-alt me-2"></i>Draft
                                    </div>
                                    <div class="step-divider"></div>
                                    <div class="step-item" data-step="open_registration">
                                        <i class="fas fa-unlock me-2"></i>Open Registration
                                    </div>
                                    <div class="step-divider"></div>
                                    <div class="step-item" data-step="closed_registration">
                                        <i class="fas fa-lock me-2"></i>Closed Registration
                                    </div>
                                    <div class="step-divider"></div>
                                    <div class="step-item" data-step="ongoing">
                                        <i class="fas fa-play me-2"></i>Ongoing
                                    </div>
                                    <div class="step-divider"></div>
                                    <div class="step-item" data-step="finished">
                                        <i class="fas fa-trophy me-2"></i>Finished
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- Section Tabs -->
                        <div class="row mb-3" id="sectionTabsArea" style="display:none;">
                            <div class="col-12">
                                <div class="section-tabs">
                                    <button class="section-tab active" data-section="general">
                                        <i class="fas fa-info-circle me-2"></i>Informasi Umum
                                    </button>
                                    <button class="section-tab" data-section="participants">
                                        <i class="fas fa-users me-2"></i>Daftar Peserta
                                    </button>
                                    <button class="section-tab" data-section="scoreboard" disabled>
                                        <i class="fas fa-table me-2"></i>Scoreboard
                                    </button>
                                </div>
                            </div>
                        </div>

                        <!-- ============================================
                             SECTION 1: GENERAL TOURNAMENT INFO
                             ============================================ -->
                        <div class="row g-5 mb-5" id="generalSection">
                            <div class="d-flex justify-content-between align-items-center mb-3">
                                <h4 class="fw-bold mb-0">
                                    <i class="fas fa-info-circle me-2 text-primary"></i>Informasi Umum Tournament
                                </h4>
                            </div>

                            <div>
                                <span id="generalIndicator" class="section-indicator badge bg-secondary">Dapat diedit
                                    saat: draft</span>
                            </div>

                            <div class="col-12">
                                <div class="card shadow-sm border-0">
                                    <div class="card-body py-5">

                                        <form id="form_tournament_general" enctype="multipart/form-data">

                                            <input type="hidden" name="IDTournament" />

                                            <!-- Row 1: Tournament Names -->
                                            <div class="row mb-5">
                                                <div class="col-md-6">
                                                    <label class="form-label required fw-semibold">Nama
                                                        Tournament</label>
                                                    <input type="text" class="form-control" name="NamaTournament"
                                                        maxlength="150" required />
                                                </div>
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Nama Tournament (EN)</label>
                                                    <input type="text" class="form-control" name="NamaTournamentEN"
                                                        maxlength="150" />
                                                </div>
                                            </div>

                                            <!-- Row 2: Description -->
                                            <div class="row mb-5">
                                                <div class="col-md-12">
                                                    <label class="form-label fw-semibold">Deskripsi</label>
                                                    <textarea class="form-control" name="Description"
                                                        rows="3"></textarea>
                                                </div>
                                            </div>

                                            <!-- Row 3: Location -->
                                            <div class="row mb-5">
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Lokasi</label>
                                                    <input type="text" class="form-control" name="Location"
                                                        maxlength="255" />
                                                </div>
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Google Maps URL</label>
                                                    <input type="url" class="form-control" name="GoogleMapsUrl"
                                                        maxlength="255" />
                                                </div>
                                            </div>

                                            <!-- Row 4: Registration Dates -->
                                            <div class="row mb-5">
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Mulai Registrasi</label>
                                                    <input type="datetime-local" class="form-control"
                                                        name="RegistrationStart" />
                                                </div>
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Akhir Registrasi</label>
                                                    <input type="datetime-local" class="form-control"
                                                        name="RegistrationEnd" />
                                                </div>
                                            </div>

                                            <!-- Row 5: Tournament Dates -->
                                            <div class="row mb-5">
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Mulai Tournament</label>
                                                    <input type="datetime-local" class="form-control"
                                                        name="TournamentStart" />
                                                </div>
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Akhir Tournament</label>
                                                    <input type="datetime-local" class="form-control"
                                                        name="TournamentEnd" />
                                                </div>
                                            </div>

                                            <!-- Row 6: Fees & Prizes -->
                                            <div class="row mb-5">
                                                <div class="col-md-4">
                                                    <label class="form-label fw-semibold">Biaya Registrasi</label>
                                                    <input type="number" class="form-control" name="RegistrationFee"
                                                        step="0.01" min="0" />
                                                </div>
                                                <div class="col-md-4">
                                                    <label class="form-label fw-semibold">Total Hadiah</label>
                                                    <input type="number" class="form-control" name="TotalPrize"
                                                        step="0.01" min="0" />
                                                </div>
                                                <div class="col-md-4">
                                                    <label class="form-label fw-semibold">Max Peserta</label>
                                                    <input type="number" class="form-control" name="MaxParticipant"
                                                        min="0" />
                                                </div>
                                            </div>
                                            <!-- Row 6.2: Tournament Point Setup -->
                                            <div class="card mb-5">
                                                <div class="card-header">
                                                    <h6 class="mb-0">Tournament Point Setup</h6>
                                                </div>
                                                <div class="card-body">
                                                    <div class="row g-3">
                                                        <div class="col-md-3">
                                                            <label class="form-label fw-semibold">Champion 1</label>
                                                            <input type="number" class="form-control"
                                                                name="PointChampion1" value="100" />
                                                        </div>
                                                        <div class="col-md-3">
                                                            <label class="form-label fw-semibold">Champion 2</label>
                                                            <input type="number" class="form-control"
                                                                name="PointChampion2" value="50" />
                                                        </div>
                                                        <div class="col-md-3">
                                                            <label class="form-label fw-semibold">Champion 3</label>
                                                            <input type="number" class="form-control"
                                                                name="PointChampion3" value="25" />
                                                        </div>
                                                        <div class="col-md-3">
                                                            <label class="form-label fw-semibold">Champion 4</label>
                                                            <input type="number" class="form-control"
                                                                name="PointChampion4" value="0" />
                                                        </div>
                                                    </div>
                                                    <div class="row g-3 mt-4">
                                                        <div class="col-md-4">
                                                            <label class="form-label fw-semibold">Penalty - First
                                                                Round</label>
                                                            <input type="number" class="form-control"
                                                                name="PointMinusFirstRound" value="0" />
                                                        </div>
                                                        <div class="col-md-4">
                                                            <label class="form-label fw-semibold">Penalty - Second
                                                                Round</label>
                                                            <input type="number" class="form-control"
                                                                name="PointMinusSecondRound" value="0" />
                                                        </div>
                                                        <div class="col-md-4">
                                                            <label class="form-label fw-semibold">Penalty - Quarter
                                                                Final</label>
                                                            <input type="number" class="form-control"
                                                                name="PointMinusQuarterFinal" value="0" />
                                                        </div>
                                                    </div>
                                                    <div class="row g-3 mt-4">
                                                        <div class="col-md-4">
                                                            <label class="form-label fw-semibold">Point
                                                                Partisipasi</label>
                                                            <input type="number" class="form-control"
                                                                name="PointParticipate" value="0" />
                                                        </div>
                                                    </div>
                                                </div>
                                            </div>
                                            <!-- Row X: Tournament Image -->
                                            <div class="row mb-5">
                                                <div class="col-md-12">
                                                    <label class="form-label fw-semibold">Gambar Tournament</label>
                                                    <input type="file" class="form-control" name="Gambar"
                                                        id="inputTournamentImage" accept="image/*" />
                                                    <div class="mt-2">
                                                        <img id="tournamentImagePreview" src="" alt="Preview"
                                                            style="max-height:150px; display:none;" />
                                                    </div>
                                                </div>
                                            </div>

                                            <!-- Row 6.1: Tournament Format -->
                                            <div class="row mb-5">
                                                <div class="col-md-6">
                                                    <label class="form-label fw-semibold">Format Tournament</label>
                                                    <select class="form-select" name="TournamentFormat"
                                                        id="TournamentFormat">
                                                        <option value="">-- Pilih Format --</option>
                                                        <option value="round_robin">Round Robin</option>
                                                        <option value="single_elimination">Single Elimination</option>
                                                    </select>
                                                </div>
                                            </div>

                                            <!-- Row 7: Rule Document -->
                                            <div class="row mb-5">
                                                <div class="col-md-12">
                                                    <label class="form-label fw-semibold">Dokumen Peraturan</label>
                                                    <input type="file" class="form-control" id="inputRuleDocument"
                                                        name="RuleDocument" accept=".pdf,.doc,.docx" />
                                                    <small class="text-muted">File: PDF, DOC, DOCX max 10MB</small>

                                                    <!-- Preview Alert Container -->
                                                    <div id="ruleDocumentPreview"></div>
                                                </div>
                                            </div>

                                            <!-- Row 8: Tournament Categories & Levels -->
                                            <div class="row mb-5">
                                                <div class="col-md-12">
                                                    <div class="d-flex justify-content-between align-items-center mb-3">
                                                        <label class="form-label fw-semibold mb-0">Kategori & Level
                                                            Tournament</label>
                                                        <button type="button" class="btn btn-sm btn-success"
                                                            id="btnAddCategoryLevel">
                                                            <i class="fas fa-plus me-2"></i>Tambah Kategori & Level
                                                        </button>
                                                    </div>
                                                    <div id="categoryLevelContainer" class="mb-3">
                                                        <!-- Entries akan di-generate oleh JavaScript -->
                                                    </div>
                                                    <input type="hidden" id="tournamentCategoryLevelData"
                                                        name="CategoryLevelData" />
                                                </div>
                                            </div>

                                            <!-- Action Buttons -->
                                            <div class="d-flex justify-content-between gap-2">
                                                <div>
                                                    <button type="button" class="btn btn-light btn-cancel">
                                                        <i class="fas fa-arrow-left me-2"></i>Batal
                                                    </button>
                                                </div>
                                                <div>
                                                    <button type="submit" class="btn btn-primary">
                                                        <i class="fas fa-save me-2"></i>Simpan Informasi
                                                    </button>
                                                </div>
                                            </div>

                                        </form>

                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- ============================================
                                         MODAL: Create Group
                                         ============================================ -->
                        <div class="modal fade" id="modal_create_group" tabindex="-1" role="dialog">
                            <div class="modal-dialog modal-dialog-centered" role="document">
                                <div class="modal-content">
                                    <div class="modal-header">
                                        <h5 class="modal-title">Tambah Group</h5>
                                        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                                    </div>
                                    <div class="modal-body">
                                        <form id="form_create_group">
                                            <div class="mb-3">
                                                <label class="form-label required">Kategori & Level</label>
                                                <select class="form-select" id="groupTCL">
                                                    <option value="">-- Pilih Kategori & Level --</option>
                                                </select>
                                            </div>
                                            <div class="mb-3">
                                                <label class="form-label required">Nama Group</label>
                                                <input type="text" class="form-control" id="groupName" />
                                            </div>
                                        </form>
                                    </div>
                                    <div class="modal-footer">
                                        <button type="button" class="btn btn-secondary"
                                            data-bs-dismiss="modal">Batal</button>
                                        <button type="button" class="btn btn-primary" id="btnSaveGroup">Simpan</button>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- Modal: Registration Detail (persistent, large, scrollable) -->
                        <div class="modal fade" id="modal_registration_detail" data-bs-backdrop="static"
                            data-bs-keyboard="false" tabindex="-1" role="dialog">
                            <div class="modal-dialog modal-dialog-centered modal-xl modal-dialog-scrollable"
                                role="document">
                                <div class="modal-content">
                                    <div class="modal-header">
                                        <h5 class="modal-title">Detail Registration</h5>
                                        <button type="button" class="btn-close" data-bs-dismiss="modal"
                                            aria-label="Close"></button>
                                    </div>
                                    <div class="modal-body">
                                        <div id="registrationDetailContainer">
                                            <!-- sections will be injected here -->
                                        </div>
                                    </div>
                                    <div class="modal-footer">
                                        <button type="button" class="btn btn-secondary"
                                            data-bs-dismiss="modal">Close</button>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- ============================================
                                         MODAL: Assign Team to Group
                                         ============================================ -->
                        <div class="modal fade" id="modal_assign_group_team" tabindex="-1" role="dialog">
                            <div class="modal-dialog modal-dialog-centered" role="document">
                                <div class="modal-content">
                                    <div class="modal-header">
                                        <h5 class="modal-title">Assign Team ke Group</h5>
                                        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                                    </div>
                                    <div class="modal-body">
                                        <form id="form_assign_group_team">
                                            <div class="mb-3">
                                                <label class="form-label required">Group</label>
                                                <select class="form-select" id="assignGroupSelect"></select>
                                            </div>
                                            <div class="mb-3">
                                                <label class="form-label required">Team</label>
                                                <select class="form-select" id="assignTeamSelect"></select>
                                            </div>
                                        </form>
                                    </div>
                                    <div class="modal-footer">
                                        <button type="button" class="btn btn-secondary"
                                            data-bs-dismiss="modal">Batal</button>
                                        <button type="button" class="btn btn-primary" id="btnSaveAssign">Simpan</button>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!--end::General Section-->


                        <!-- Registered Kategori & Level Table -->
                        <div class="col-12 mb-5">
                            <div class="card card-flush shadow-sm">

                                <!-- Header -->
                                <div class="card-header pt-5">
                                    <div class="card-title">
                                        <div class="d-flex align-items-center">
                                            <span class="svg-icon svg-icon-2x svg-icon-primary me-3">
                                                <i class="fas fa-layer-group text-primary fs-2"></i>
                                            </span>
                                            <div>
                                                <h3 class="fw-bold mb-0">Kategori & Level Tournament</h3>
                                                <div class="text-muted fs-7">
                                                    Daftar kategori dan level yang terdaftar pada tournament ini
                                                </div>
                                            </div>
                                        </div>
                                    </div>
                                </div>


                                <!-- Body -->
                                <div class="card-body pt-0">
                                    <div class="table-responsive">
                                        <table class="table align-middle table-row-dashed fs-6 gy-4">
                                            <thead>
                                                <tr class="text-start text-muted fw-bold fs-7 text-uppercase gs-0">
                                                    <th class="min-w-200px">Nama Kategori</th>
                                                    <th class="min-w-150px">Level</th>
                                                </tr>
                                            </thead>
                                            <tbody id="categoryLevelTableBody" class="fw-semibold text-gray-600">

                                                <!-- Empty State -->
                                                <tr>
                                                    <td colspan="2">
                                                        <div class="d-flex flex-column flex-center py-10">
                                                            <i class="fas fa-folder-open text-gray-400 fs-2x mb-3"></i>
                                                            <span class="text-gray-500 fs-6">
                                                                Belum ada kategori & level yang ditambahkan
                                                            </span>
                                                        </div>
                                                    </td>
                                                </tr>


                                            </tbody>
                                        </table>
                                    </div>
                                </div>

                            </div>
                        </div>



                        <!-- ============================================
                             SECTION 2: DAFTAR PESERTA
                             ============================================ -->
                        <div class="row g-5 mb-5 d-none" id="participantsSection">
                            <div class="d-flex justify-content-between align-items-center mb-3">
                                <h4 class="fw-bold mb-0">
                                    <i class="fas fa-users me-2 text-primary"></i>Daftar Peserta
                                </h4>
                                <div>
                                    <span id="participantsIndicator" class="section-indicator badge bg-secondary">Dapat
                                        diedit saat: open_registration, closed_registration</span>
                                </div>
                            </div>

                            <!-- Participants Table -->

                            <div class="col-12">

                                <div class="card shadow-sm border-0">

                                    <div class="card-header py-3 d-flex justify-content-between align-items-center">
                                        <h6 class="m-0">Daftar Tim Terdaftar</h6>
                                        <div>
                                            <button type="button" class="btn btn-sm btn-primary" id="btnAddParticipant"
                                                style="display:none;">
                                                <i class="fas fa-plus me-2"></i>Tambah Peserta
                                            </button>
                                        </div>
                                    </div>

                                    <div class="card-body py-5">


                                        <div id="participantsTableContainer"></div>
                                    </div>
                                </div>
                            </div>

                        </div>
                        <!--end::Participants Section-->

                        <!-- ============================================
                             SECTION 2.5: TOURNAMENT GROUPS (closed_registration)
                             ============================================ -->
                        <div class="row g-5 mb-5 d-none" id="groupsSection">
                            <div class="d-flex justify-content-between align-items-center mb-3">
                                <h4 class="fw-bold mb-0">
                                    <i class="fas fa-layer-group me-2 text-primary"></i>Group Tournament
                                </h4>
                                <div>
                                    <span id="groupsIndicator" class="section-indicator badge bg-secondary">Dapat diedit
                                        saat: closed_registration</span>
                                </div>
                            </div>

                            <div class="col-12">
                                <div class="card shadow-sm border-0">
                                    <div class="card-header py-3 d-flex justify-content-between align-items-center">
                                        <h6 class="m-0">Group</h6>
                                        <div>
                                            <button type="button" class="btn btn-sm btn-primary"
                                                id="btnAutoGenerateGroups">
                                                <i class="fas fa-magic me-1"></i>Generate Otomatis
                                            </button>

                                            <button type="button" class="btn btn-sm btn-primary"
                                                id="btnAutoGenerateGroupsAndTeams">
                                                <i class="fas fa-magic me-1"></i>Generate Otomatis & Assign Team
                                            </button>

                                            <button type="button" class="btn btn-sm btn-outline-primary"
                                                id="btnAddGroup">
                                                <i class="fas fa-plus me-1"></i>Tambah Group
                                            </button>
                                        </div>
                                    </div>
                                    <div class="card-body py-3">
                                        <div id="groupsTableContainer"></div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!--end::Groups Section-->

                        <!-- ============================================
                             SECTION 3: GROUP-TEAM ASSIGNMENT (closed_registration)
                             ============================================ -->
                        <div class="row g-5 mb-5 d-none" id="groupTeamsSection">
                            <div class="d-flex justify-content-between align-items-center mb-3">
                                <h4 class="fw-bold mb-0">
                                    <i class="fas fa-network-wired me-2 text-primary"></i>Group - Team Assignment
                                </h4>
                                <div>
                                    <!-- buttons moved into the card header for consistent placement -->
                                </div>
                            </div>

                            <div class="col-12">
                                <div class="card shadow-sm border-0">
                                    <div class="card-header py-3 d-flex justify-content-between align-items-center">
                                        <h6 class="m-0">Group Teams</h6>
                                        <div>
                                            <button type="button" class="btn btn-sm btn-outline-primary"
                                                id="btnAutoAssignTeams">
                                                <i class="fas fa-magic me-1"></i>Assign Otomatis
                                            </button>
                                            <button type="button" class="btn btn-sm btn-primary" id="btnAddGroupTeam">
                                                <i class="fas fa-plus me-1"></i>Tambah Assignment
                                            </button>
                                        </div>
                                    </div>
                                    <div class="card-body py-3">
                                        <div id="groupTeamsTableContainer"></div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!--end::GroupTeams Section-->

                        <!-- ============================================
                             SECTION 3: SCOREBOARD & MATCHES
                             ============================================ -->
                        <div class="row g-5 mb-5 d-none" id="scoreboardSection">
                            <div class="d-flex justify-content-between align-items-center mb-3">
                                <h4 class="fw-bold mb-0">
                                    <i class="fas fa-table me-2 text-primary"></i>Scoreboard & Pertandingan
                                </h4>
                                <div>
                                    <span id="scoreboardIndicator" class="section-indicator badge bg-secondary">Dapat
                                        diedit saat: ongoing</span>
                                </div>
                                <div class="btn-group">
                                    <button type="button" class="btn btn-sm btn-outline-primary"
                                        id="btnAutoGenerateMatches" style="display:none;">
                                        <i class="fas fa-magic me-2"></i>Generate Matches
                                    </button>
                                    <button type="button" class="btn btn-sm btn-outline-danger" id="btnDeleteAllMatches"
                                        style="display:none;">
                                        <i class="fas fa-trash-alt me-2"></i>Delete All Matches
                                    </button>
                                    <button type="button" class="btn btn-sm btn-outline-warning" id="btnClearAllScores"
                                        style="display:none;">
                                        <i class="fas fa-eraser me-2"></i>Clear All Score Matches
                                    </button>
                                </div>
                            </div>



                            <!-- Matches Table -->
                            <div class="col-12">
                                <div class="card shadow-sm border-0">
                                    <div class="card-header py-3">
                                        <h6 class="m-0">Daftar Pertandingan</h6>
                                    </div>
                                    <div class="card-body p-0">
                                        <div id="matchesTableContainer"></div>
                                    </div>


                                    <div class="card-footer py-3"></div>
                                    <div class="card-body p-3">
                                        <div id="tournamentSummaryContainer"></div>

                                        <div class="my-3"></div>
                                        <div id="tournamentMatchEditorContainer"></div>
                                        <!-- leaderboard container moved to its own section -->
                                    </div>

                                </div>
                            </div>
                        </div>
                        <!--end::Scoreboard Section-->

                        <!-- ============================================
                             SECTION 4: LEADERBOARD
                             ============================================ -->
                        <div class="row g-5 mb-5 d-none" id="leaderboardSection">
                            <div class="col-12">
                                <div class="card shadow-sm border-0">
                                    <div class="card-header py-3">
                                        <h4 class="fw-bold mb-0">
                                            <i class="fas fa-trophy me-2 text-warning"></i>Leaderboard
                                        </h4>
                                    </div>
                                    <div class="card-body p-3">
                                        <div id="tournamentLeaderboardContainer"></div>
                                    </div>
                                </div>
                            </div>
                        </div>
                        <!--end::Leaderboard Section-->



                        <!-- Status Flow Buttons -->
                        <div class="row g-5 mb-5" id="statusFlowSection">
                            <div class="col-12">
                                <div class="card shadow-sm border-0">
                                    <div class="card-body py-4">
                                        <!-- Current Status Indicator -->
                                        <div class="d-flex justify-content-between align-items-center mb-4">
                                            <div>
                                                <h6 class="text-muted mb-2">Status Tournament Saat Ini</h6>
                                                <div>
                                                    <span id="currentStatusIndicator" class="badge status-badge"
                                                        style="font-size: 0.95rem; padding: 0.75rem 1.25rem;">
                                                        Draft
                                                    </span>
                                                </div>
                                            </div>
                                            <div class="text-end">
                                                <small class="text-muted d-block mb-2">Terakhir diubah:</small>
                                                <small id="lastStatusUpdateTime" class="text-muted">-</small>
                                            </div>
                                        </div>

                                        <hr class="my-4" />

                                        <!-- Action Buttons -->
                                        <div class="d-flex justify-content-center gap-2 flex-wrap">
                                            <button type="button" id="btnPrevStep" class="btn btn-outline-secondary"
                                                style="display:none;">
                                                <i class="fas fa-arrow-left me-2"></i>Langkah Sebelumnya
                                            </button>
                                            <button type="button" id="btnNextStep" class="btn btn-primary"
                                                style="display:none;">
                                                <i class="fas fa-arrow-right me-2"></i>Langkah Berikutnya
                                            </button>
                                            <button type="button" id="btnCancelTournament" class="btn btn-danger"
                                                style="display:none;">
                                                <i class="fas fa-ban me-2"></i>Batal Tournament
                                            </button>
                                        </div>
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- floating action at bottom right -->
                        <div id="floatingStatusBtn" style="position:fixed;bottom:20px;right:20px;z-index:1050;">
                            <div class="btn-group dropup">
                                <button type="button" class="btn btn-primary btn-lg" id="fabMainBtn"
                                    data-bs-toggle="tooltip" data-bs-placement="left"
                                    data-bs-title="Status Tournament Saat Ini: Draft"
                                    aria-label="Status Tournament Saat Ini: Draft">
                                    <i class="fas fa-arrow-left"></i>
                                </button>
                                <button type="button"
                                    class="btn btn-primary btn-lg dropdown-toggle dropdown-toggle-split"
                                    data-bs-toggle="dropdown" aria-expanded="false">
                                    <span class="visually-hidden">Toggle</span>
                                </button>
                                <ul class="dropdown-menu">
                                    <li><a class="dropdown-item" href="javascript:void(0)" id="fabPrev"><i
                                                class="fas fa-arrow-left me-2"></i>Langkah Sebelumnya</a></li>
                                    <li><a class="dropdown-item" href="javascript:void(0)" id="fabNext"><i
                                                class="fas fa-arrow-right me-2"></i>Langkah Berikutnya</a></li>
                                    <li><a class="dropdown-item text-danger" href="javascript:void(0)" id="fabCancel"><i
                                                class="fas fa-ban me-2"></i>Batal Tournament</a></li>
                                </ul>
                            </div>
                        </div>

                    </div>
                    <!--end::Post-->
                </div>
                <!--end::Container-->


                <!--begin::Footer-->
                <?php include_once("assets/addon/footer.php"); ?>
                <!--end::Footer-->

            </div>
            <!--end::Wrapper-->
        </div>
        <!--end::Page-->

    </div>
    <!--end::Root-->

    <!--end::Main-->

    <!-- ============================================
     MODAL: Add Participant (BIG MODAL)
     ============================================ -->
    <div class="modal fade" id="modal_add_participant" tabindex="-2" role="dialog" data-bs-backdrop="static">
        <div class="modal-dialog modal-dialog-centered modal-xl" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Tambah Tim Peserta</h5>
                    <div class="d-flex align-items-center gap-2">
                        <button type="button" class="btn btn-sm btn-light" id="btnReloadParticipantData">
                            <i class="fas fa-sync-alt me-1"></i> Reload Data
                        </button>
                        <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                    </div>
                </div>
                <div class="modal-body">
                    <form id="form_add_participant">
                        <div class="row mb-3">
                            <div class="col-md-6">
                                <label class="form-label required">Kategori</label>
                                <select class="form-select" id="participantKategori" required>
                                    <option value="">-- Pilih Kategori --</option>
                                </select>
                            </div>
                            <div class="col-md-6">
                                <label class="form-label required">Level</label>
                                <select class="form-select" id="participantLevel" required>
                                    <option value="">-- Pilih Level --</option>
                                </select>
                            </div>
                        </div>

                        <!-- Player 1 -->
                        <div class="row mb-3" id="player1Container">
                            <div class="col-md-12">
                                <label class="form-label required">Pemain 1</label>
                                <div class="input-group">
                                    <input type="hidden" id="participantPlayer1Id" />
                                    <input type="text" class="form-control" id="participantPlayer1Name"
                                        placeholder="Cari & pilih pemain..." readonly />
                                    <button class="btn btn-primary" type="button" id="btnSearchPlayer1"
                                        title="Cari Pemain">
                                        <i class="fas fa-search"></i>
                                    </button>
                                    <button class="btn btn-danger" type="button" id="btnClearPlayer1"
                                        title="Hapus Pilihan">
                                        <i class="fas fa-times"></i>
                                    </button>
                                </div>
                                <div class="row mt-2">
                                    <div class="col-md-6">
                                        <input type="text" class="form-control" id="participantPlayer1Email"
                                            placeholder="Email" readonly />
                                    </div>
                                    <div class="col-md-6">
                                        <input type="text" class="form-control" id="participantPlayer1Gender"
                                            placeholder="Gender" readonly />
                                    </div>
                                </div>
                            </div>
                        </div>

                        <!-- Player 2 (Double) -->
                        <div class="row mb-3" id="player2Container" style="display:none;">
                            <div class="col-md-12">
                                <label class="form-label required">Pemain 2 (Double)</label>
                                <div class="input-group">
                                    <input type="hidden" id="participantPlayer2Id" />
                                    <input type="text" class="form-control" id="participantPlayer2Name"
                                        placeholder="Cari & pilih pemain..." readonly />
                                    <button class="btn btn-primary" type="button" id="btnSearchPlayer2"
                                        title="Cari Pemain">
                                        <i class="fas fa-search"></i>
                                    </button>
                                    <button class="btn btn-danger" type="button" id="btnClearPlayer2"
                                        title="Hapus Pilihan">
                                        <i class="fas fa-times"></i>
                                    </button>
                                </div>
                                <div class="row mt-2">
                                    <div class="col-md-6">
                                        <input type="text" class="form-control" id="participantPlayer2Email"
                                            placeholder="Email" readonly />
                                    </div>
                                    <div class="col-md-6">
                                        <input type="text" class="form-control" id="participantPlayer2Gender"
                                            placeholder="Gender" readonly />
                                    </div>
                                </div>
                            </div>
                        </div>
                        <div class="row mb-3" id="playerTeamNameSelectContainer">
                            <div class="col-md-12">
                                <label class="form-label required">Nama Tim</label>
                                <input type="text" class="form-control" id="participantTeamName" required />
                            </div>
                        </div>

                        <input type="hidden" id="participantTeamId" name="IDTeam" />
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
                    <button type="button" class="btn btn-primary" id="btnSaveAndClose">Simpan & Tutup</button>
                    <button type="button" class="btn btn-success" id="btnSaveAndContinue">Simpan & Lanjut</button>
                </div>
            </div>
        </div>
    </div>

    <!-- Container untuk PopupDialogSearch -->
    <!-- Container untuk PopupDialogSearch - ditempatkan di luar modal_add_participant -->
    <div id="player1PopupContainer"></div>
    <div id="player2PopupContainer"></div>

    <!-- ============================================
         MODAL: Add Match & Score
         ============================================ -->
    <div class="modal fade" id="modal_add_match" tabindex="-1" role="dialog">
        <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Tambah/Edit Pertandingan</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal"></button>
                </div>
                <div class="modal-body">
                    <form id="form_add_match">
                        <div id="scoreEntriesContainer"></div>
                        <input type="hidden" id="matchId" name="IDTournamentMatch" />
                    </form>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Batal</button>
                    <button type="button" class="btn btn-primary" id="btnSaveMatch">Simpan</button>
                </div>
            </div>
        </div>
    </div>

    <!-- Generic modal: confirm and dynamic (in case callbacks need them) -->
    <div class="modal fade" id="modal_confirm_action" tabindex="-1" role="dialog">
        <div class="modal-dialog modal-dialog-centered" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title">Confirm</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <p id="modal_confirm_message">Are you sure?</p>
                </div>
                <div class="modal-footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Cancel</button>
                    <button type="button" class="btn btn-danger" id="modal_confirm_ok">OK</button>
                </div>
            </div>
        </div>
    </div>

    <div class="modal fade" id="modal_dynamic" tabindex="-1" role="dialog">
        <div class="modal-dialog modal-dialog-centered modal-lg" role="document">
            <div class="modal-content">
                <div class="modal-header">
                    <h5 class="modal-title" id="modal_dynamic_title">Detail</h5>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body" id="modal_dynamic_body">
                    <!-- dynamic content injected by callbacks -->
                </div>
                <div class="modal-footer" id="modal_dynamic_footer">
                    <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                </div>
            </div>
        </div>
    </div>

    <!--begin::Javascript-->
    <?php include_once 'assets/addon/scripts.php'; ?>
    <?php
    $active_namespaces = ['login', 'header', 'generic'];
    include_once 'locales/init.php';
    ?>

    <script src="assets/plugins/custom/datatables/datatables.bundle.js"></script>

    <!--begin::Custom Javascript(used for this page only)-->
    <script type="module">
        import { checkSession, toggleContentOverlay, updateHeaderUser } from './modules/session.js';
        import { getActiveUser } from './col_script/essential/user_helper.js';
        import { setLocales_textContent, initDynamicLanguageHandler } from './col_script/common/locales_helper.js';
        import {
            q_setVisibility, q_setText, q_isValidDatetime, q_setDateTimeToFormat, q_updateMetaData, q_setOptionData,
            q_initFormSubmit, q_getURLParameter, q_fillFormData, q_generateViewContent, q_generateListErrorMessage
        } from './col_script/common/qol.js';
        import { fetch_helper } from "./col_script/common/fetch_helper.js";
        import { generateDatatableHTML } from "./col_script/common/datatable_html.js";
        import { initDatatable } from "./col_script/common/datatable_helper.js";
        import { setBreadcrumb } from "./col_script/common/router_helper.js";
        import { generateTournamentSummary, generateMatchEditor, generateLeaderboard } from './col_script/common/tournament_helper.js';
        import DataTable from './modules/DataTable.js';
        import PopupDialogSearch from './modules/PopupDialogSearch.js';

        // ========================
        // GLOBAL STATE
        // ========================
        let AksesUtama = "Tournament";
        let AksesNeeded = AksesUtama + ".View";
        let AksesModifyNeeded = AksesUtama + ".Modify";
        let AksesDeleteNeeded = AksesUtama + ".Delete";
        let AksesAddParticipantNeeded = AksesUtama + ".AddParticipant";
        let AksesAddMatchNeeded = AksesUtama + ".AddMatch";
        let AksesNextStepNeeded = AksesUtama + ".NextStep";
        let main_pk = "tournament";
        let sumberPath = "m_" + main_pk + ".php";
        let currentTournamentId = null;
        let currentTournamentData = null;
        let currentStatus = "draft";
        var listKategori = [];
        var listLevel = [];
        var listAllAkses = [];
        var listTournamentCategoryLevel = [];
        let playerListData = [];

        const STATUS_FLOW = ["draft", "open_registration", "closed_registration", "ongoing", "finished"];
        const STATUS_LABELS = {
            draft: "Draft",
            open_registration: "Open Registrasi",
            closed_registration: "Registrasi Ditutup",
            ongoing: "Sedang Berlangsung",
            finished: "Selesai",
            cancelled: "Dibatalkan"
        };

        // ========================
        // STATUS MANAGEMENT
        // ========================
        function updateFloatingStatusTooltip() {
            const fabMainBtn = document.getElementById('fabMainBtn');
            if (!fabMainBtn) return;

            const tooltipText = `Status Tournament Saat Ini: ${STATUS_LABELS[currentStatus] || currentStatus}`;
            fabMainBtn.setAttribute('data-bs-title', tooltipText);
            fabMainBtn.setAttribute('title', tooltipText);
            fabMainBtn.setAttribute('aria-label', tooltipText);

            if (window.bootstrap?.Tooltip) {
                const existingTooltip = bootstrap.Tooltip.getInstance(fabMainBtn);
                if (existingTooltip) {
                    existingTooltip.dispose();
                }
                new bootstrap.Tooltip(fabMainBtn, {
                    placement: 'left',
                    trigger: 'hover focus'
                });
            }
        }

        function updateStatusDisplay() {
            const badgeEl = document.getElementById("statusBadge");
            const titleEl = document.getElementById("tournamentTitle");
            const currentStatusIndicator = document.getElementById("currentStatusIndicator");
            const lastStatusUpdateTime = document.getElementById("lastStatusUpdateTime");

            if (!badgeEl || !titleEl) return;

            let badgeClass = "bg-secondary";
            switch (currentStatus) {
                case "draft": badgeClass = "bg-secondary"; break;
                case "open_registration": badgeClass = "bg-light-success"; break;
                case "closed_registration": badgeClass = "bg-light-warning"; break;
                case "ongoing": badgeClass = "bg-light-primary"; break;
                case "finished": badgeClass = "bg-light-dark"; break;
                case "cancelled": badgeClass = "bg-light-danger"; break;
            }

            badgeEl.className = `badge status-badge ${badgeClass}`;
            badgeEl.textContent = STATUS_LABELS[currentStatus] || currentStatus;
            titleEl.textContent = currentTournamentData?.NamaTournament || "Tournament";

            // Update current status indicator
            if (currentStatusIndicator) {
                currentStatusIndicator.className = `badge status-badge ${badgeClass}`;
                currentStatusIndicator.textContent = STATUS_LABELS[currentStatus] || currentStatus;
            }

            // Update last status update time
            if (lastStatusUpdateTime && currentTournamentData?.LastUpdateAt) {
                const updateDate = new Date(currentTournamentData.LastUpdateAt);
                lastStatusUpdateTime.textContent = updateDate.toLocaleString('id-ID');
            }

            updateStepIndicators();
            updateSectionAvailability();
            updateFormReadOnly();
            updateFloatingStatusTooltip();
        }


        function updateStepIndicators() {
            const stepItems = document.querySelectorAll('.step-item');
            const currentIndex = STATUS_FLOW.indexOf(currentStatus);

            stepItems.forEach((item, idx) => {
                item.classList.remove('active', 'disabled');
                if (idx <= currentIndex) {
                    item.classList.add('active');
                } else {
                    item.classList.add('disabled');
                }
            });
        }

        function hasAccess(aksesName) {
            return listAllAkses && listAllAkses.includes(aksesName);
        }

        function canAddParticipant() {
            return ['open_registration', 'closed_registration'].includes(currentStatus) && hasAccess(AksesAddParticipantNeeded);
        }

        function canAddMatch() {
            return currentStatus === 'ongoing' && hasAccess(AksesAddMatchNeeded);
        }

        function canClearMatches() {
            return currentStatus === 'ongoing'
        }

        function canChangeStatus() {
            // Allow status change if user has NextStep access
            // cancelled status cannot move forward/backward
            return currentStatus !== 'cancelled' && hasAccess(AksesNextStepNeeded);
        }

        function showStatusWarning(action) {
            let message = '';
            switch (action) {
                case 'addParticipant':
                    message = 'Status tournament masih ' + currentStatus + '. Silakan buka registrasi terlebih dahulu.';
                    break;
                case 'addMatch':
                    message = 'Status tournament harus "ongoing" untuk menambah hasil pertandingan.';
                    break;
                case 'changeStatus':
                    message = 'Anda tidak memiliki izin untuk mengubah status tournament.';
                    break;
                default:
                    message = 'Aksi tidak diizinkan pada status tournament saat ini.';
            }
            Swal.fire({
                title: 'Aksi Tidak Diizinkan',
                text: message,
                icon: 'warning',
                confirmButtonText: 'OK',
                confirmButtonColor: '#3085d6'
            });
        }

        function updateSectionAvailability() {
            // General section editable only in draft
            const formGeneral = document.getElementById('form_tournament_general');
            const isEditableGeneral = currentStatus === 'draft' && currentTournamentData;

            if (formGeneral) {
                const inputs = formGeneral.querySelectorAll('input, textarea, select');
                inputs.forEach(input => {
                    input.disabled = !isEditableGeneral;
                });
                const submitBtn = formGeneral.querySelector('button[type="submit"]');
                if (submitBtn) submitBtn.style.display = isEditableGeneral ? 'block' : 'none';
            }

            // Participants section available from open_registration AND user has permission
            const btnAddParticipant = document.getElementById('btnAddParticipant');
            const canAddParticipant = ['open_registration', 'closed_registration'].includes(currentStatus) && hasAccess(AksesAddParticipantNeeded);
            if (btnAddParticipant) btnAddParticipant.style.display = canAddParticipant ? 'block' : 'none';

            // Scoreboard section available only during ongoing AND user has permission
            const canAddMatch = currentStatus === 'ongoing' && hasAccess(AksesAddMatchNeeded);
            const btnAutoGenerateMatches = document.getElementById('btnAutoGenerateMatches');
            if (btnAutoGenerateMatches) btnAutoGenerateMatches.style.display = canAddMatch ? 'inline-block' : 'none';

            // delete/clear buttons require clear permission as well
            const canClear = currentStatus === 'ongoing';
            const btnDeleteAll = document.getElementById('btnDeleteAllMatches');
            const btnClearScores = document.getElementById('btnClearAllScores');
            if (btnDeleteAll) btnDeleteAll.style.display = canClear ? 'inline-block' : 'none';
            if (btnClearScores) btnClearScores.style.display = canClear ? 'inline-block' : 'none';

            // Enable scoreboard tab only during ongoing
            const scoreboardTab = document.querySelector('[data-section="scoreboard"]');
            if (scoreboardTab) {
                scoreboardTab.disabled = !canAddMatch;
            }
            // leaderboard tab only available when tournament finished (read-only)
            const leaderboardTab = document.querySelector('[data-section="leaderboard"]');
            if (leaderboardTab) {
                leaderboardTab.disabled = (currentStatus !== 'finished');
            }

            // Update section indicators (show which status allows editing and whether user has access)
            function setIndicator(id, allowedStatuses, hasPermission) {
                const el = document.getElementById(id);
                if (!el) return;
                const allowedText = allowedStatuses.map(s => STATUS_LABELS[s] || s).join(', ');
                const isAllowedNow = allowedStatuses.includes(currentStatus);
                if (isAllowedNow && hasPermission) {
                    el.className = 'section-indicator badge bg-success';
                    el.textContent = 'Dapat diedit saat: ' + allowedText;
                } else if (isAllowedNow && !hasPermission) {
                    el.className = 'section-indicator badge bg-warning text-dark';
                    el.textContent = 'Status memperbolehkan: ' + allowedText + ' (tidak ada akses)';
                } else {
                    el.className = 'section-indicator badge bg-secondary';
                    el.textContent = 'Dapat diedit saat: ' + allowedText;
                }
            }

            setIndicator('generalIndicator', ['draft'], hasAccess(AksesModifyNeeded) || !currentTournamentId);
            setIndicator('participantsIndicator', ['open_registration', 'closed_registration'], hasAccess(AksesAddParticipantNeeded));
            setIndicator('scoreboardIndicator', ['ongoing'], hasAccess(AksesAddMatchNeeded));
            setIndicator('groupsIndicator', ['closed_registration'], hasAccess(AksesModifyNeeded));
        }

        function updateFormReadOnly() {
            const form = document.getElementById('form_tournament_general');
            if (!form) return;

            const isReadOnly = currentStatus !== 'draft';
            const inputs = form.querySelectorAll('input, textarea, select');
            inputs.forEach(input => {
                input.readOnly = isReadOnly;
                input.disabled = isReadOnly;
            });

            const submitBtn = form.querySelector('button[type="submit"]');
            if (submitBtn) submitBtn.style.display = isReadOnly ? 'none' : 'block';
        }

        function updateStatusFlowButtons() {
            const btnNext = document.getElementById('btnNextStep');
            const btnPrev = document.getElementById('btnPrevStep');
            const btnCancel = document.getElementById('btnCancelTournament');
            const fabNext = document.getElementById('fabNext');
            const fabPrev = document.getElementById('fabPrev');
            const fabCancel = document.getElementById('fabCancel');

            const currentIndex = STATUS_FLOW.indexOf(currentStatus);
            const hasNextStepAccess = hasAccess(AksesNextStepNeeded);

            // determine visibility
            const showNext = currentIndex < STATUS_FLOW.length - 1 && hasNextStepAccess;
            const showPrev = currentIndex > 0 && hasNextStepAccess;
            const showCancel = currentStatus !== 'cancelled' && currentStatus !== 'finished' && hasNextStepAccess;

            // Show/hide main buttons
            if (btnNext) btnNext.style.display = showNext ? 'block' : 'none';
            if (btnPrev) btnPrev.style.display = showPrev ? 'block' : 'none';
            if (btnCancel) btnCancel.style.display = showCancel ? 'block' : 'none';

            // mirror to floating action icons
            if (fabNext) fabNext.style.display = showNext ? 'block' : 'none';
            if (fabPrev) fabPrev.style.display = showPrev ? 'block' : 'none';
            if (fabCancel) fabCancel.style.display = showCancel ? 'block' : 'none';
            const floatWrapper = document.getElementById('floatingStatusBtn');
            if (floatWrapper) {
                floatWrapper.style.display = (showNext || showPrev || showCancel) ? 'block' : 'none';
            }
        }

        // ========================
        // INITIALIZATION
        // ========================
        async function init(listU, listA) {
            const aksesNames = listA.map(a => a.AksesName);
            if (!aksesNames.includes(AksesNeeded)) {
                showUnauthorizedAlert(AksesNeeded);
                return;
            }

            // Store akses untuk digunakan di ui functions
            listAllAkses = aksesNames;

            setBreadcrumb("#breadcrumb_container", ["Dashboard", AksesUtama]);

            const id = q_getURLParameter("id", "int");
            currentTournamentId = id;

            if (id) {
                // Load existing tournament
                load(id, listA);
            } else {
                // Create new tournament - show only general section
                launcher(listA, null);
            }
        }

        async function load(id, listA) {
            try {
                const formData = new URLSearchParams();
                formData.append("p_type", main_pk);
                formData.append("p_action", "select");

                const currentFilters = [];
                currentFilters.push(["IDTournament", id, 1]);
                formData.append("filters", JSON.stringify(currentFilters));

                const { result } = await fetch_helper({
                    i18nKey: "",
                    fetchFile: "",
                    formData: formData,
                });

                if (result.Status == 1 && result.list_data && result.list_data.length > 0) {
                    launcher(listA, result.list_data[0]);

                } else {
                    throw new Error("Data Kosong");
                }
            } catch (error) {
                Swal.fire({
                    title: i18next.t(error.message),
                    icon: "error",
                    allowEscapeKey: false,
                    allowOutsideClick: false,
                    confirmButtonText: "OK",
                    didClose: function () {
                        window.location.href = "index.php";
                    },
                });
            }
        }

        async function launcher(listA, listData = null) {
            const formData = new URLSearchParams();
            formData.append("p_type", "launcher");
            formData.append("p_action", "select");
            formData.append("getPerusahaan", "1");

            formData.append("getLevel", "1");
            formData.append("getLevel_StatusLevel", "1");
            formData.append("getLevel_OrderBy", "NamaLevel");
            formData.append("getLevel_OrderType", "ASC");

            formData.append("getKategori", "1");
            formData.append("getKategori_StatusKategori", "1");
            formData.append("getKategori_kategoriOrderBy", "NamaKategori");
            formData.append("getKategori_kategoriOrderType", "ASC");


            // Additional data fetching can be added here
            const id_turnament = q_getURLParameter("id", "int");
            if (id_turnament > 0) {
                formData.append("getTournamentCategoryLevel", "1");
                formData.append("getTournamentCategoryLevel_IDTournament", id_turnament);
                formData.append("getTournamentCategoryLevel_OrderBy", "NamaKategori");
                formData.append("getTournamentCategoryLevel_OrderType", "ASC");


                formData.append("getTournamentMatchSummary", "1");
                formData.append("getTournamentMatch_IDTournament", id_turnament);
            }

            const { result } = await fetch_helper({
                i18nKey: "",
                fetchFile: "",
                formData: formData,
            });

            if (result.Status !== 1) {
                Swal.fire({ text: result.Keterangan, icon: "error", confirmButtonText: "OK" });
                return;
            }

            // Update header with company info
            if (result.listPerusahaan && result.listPerusahaan.length > 0) {
                const item = result.listPerusahaan[0];
                const logo = item.Logo ? `attachments/perusahaan/${item.Logo}` : "icons/logo_placeholder.png";
                const elLogo = document.querySelector('[data-header-element="logo"]');
                if (elLogo) elLogo.src = logo;

                q_updateMetaData({
                    title: `Input ${AksesUtama} – ${item.NamaPerusahaan}`,
                    description: `Input ${AksesUtama}`,
                    image: logo,
                    favicon: logo,
                    url: window.location.href,
                });
            }

            if (result.listLevel && result.listLevel.length > 0) {
                listLevel = result.listLevel;
            }

            if (result.listKategori && result.listKategori.length > 0) {
                listKategori = result.listKategori;
            }

            if (result.listTournamentCategoryLevel && result.listTournamentCategoryLevel.length > 0) {
                listTournamentCategoryLevel = result.listTournamentCategoryLevel;
            }

            if (result.listTournamentMatch) {


                const summaryData = result.listTournamentMatch;
                setMatchesElement(summaryData);
            } else {
                document.getElementById('tournamentSummaryContainer').innerHTML = '<div class="text-muted p-2">Ringkasan tidak tersedia.</div>';
            }


            if (listData != null) {
                // Existing tournament
                currentTournamentData = listData;
                currentStatus = listData.StatusTournament || 'draft';

                q_setVisibility(document.getElementById('statusDisplaySection'), true);
                q_setVisibility(document.getElementById('stepsSection'), true);
                q_setVisibility(document.getElementById('sectionTabsArea'), true);
                q_setVisibility(document.getElementById('statusFlowSection'), true);
                q_setVisibility(document.getElementById('participantsSection'), true);
                q_setVisibility(document.getElementById('groupsSection'), true);
                q_setVisibility(document.getElementById('groupTeamsSection'), true);
                q_setVisibility(document.getElementById('scoreboardSection'), true);
                q_setVisibility(document.getElementById('leaderboardSection'), true);

                q_fillFormData("#form_tournament_general", listData);

                if (listData.Gambar) {
                    let basePath = "attachments/tournament/" + listData.IDTournament + "/";
                    setImagePreviewFromUrl(
                        document.getElementById('tournamentImagePreview'),
                        basePath + listData.Gambar
                    );
                }

                if (listData.RuleDocument) {
                    let basePath = "attachments/tournament/" + listData.IDTournament + "/";
                    setRuleDocumentPreview(
                        document.getElementById('ruleDocumentPreview'),
                        {
                            RuleDocumentPath: basePath + listData.RuleDocument,
                            RuleDocumentName: listData.RuleDocumentName,
                            RuleDocumentUploadedBy: listData.RuleDocumentUploadedBy,
                            RuleDocumentUploadedAt: listData.RuleDocumentUploadedAt
                        }
                    );
                }

                loadCategoryLevelData(listData);
                updateStatusDisplay();
                initSectionTabs();
                initStatusFlowButtons();
                initCategoryLevelHandlers();
                loadParticipantsTable();
                loadGroupsTable();
                loadGroupTeamsTable();
                displayCategoryLevelTable();
            } else {
                // New tournament
                q_setVisibility(document.getElementById('generalSection'), true);
                q_setVisibility(document.getElementById('statusDisplaySection'), false);
                q_setVisibility(document.getElementById('stepsSection'), false);
                q_setVisibility(document.getElementById('sectionTabsArea'), false);
                q_setVisibility(document.getElementById('statusFlowSection'), false);
                initCategoryLevelHandlers();
            }

            initFormHandlers();
            initPlayerPopups();
        }

        function initSectionTabs() {
            const tabButtons = document.querySelectorAll('.section-tab');
            tabButtons.forEach(btn => {
                btn.addEventListener('click', function () {
                    if (this.disabled) return;

                    const section = this.getAttribute('data-section');

                    // Update active tab
                    tabButtons.forEach(b => b.classList.remove('active'));
                    this.classList.add('active');

                    // Show/hide sections
                    document.getElementById('generalSection').classList.toggle('d-none', section !== 'general');
                    document.getElementById('participantsSection').classList.toggle('d-none', section !== 'participants');
                    document.getElementById('scoreboardSection').classList.toggle('d-none', section !== 'scoreboard');
                    document.getElementById('leaderboardSection').classList.toggle('d-none', section !== 'leaderboard');
                    document.getElementById('groupsSection').classList.toggle('d-none', section !== 'groups');
                    document.getElementById('groupTeamsSection').classList.toggle('d-none', section !== 'groupteams');
                });
            });
        }

        function initFormHandlers() {
            // Form general submit
            const formGeneral = document.getElementById('form_tournament_general');
            if (formGeneral) {
                formGeneral.addEventListener('submit', async (e) => {
                    e.preventDefault();
                    await saveGeneralInfo();
                });
            }

            // Cancel buttons
            document.querySelectorAll('.btn-cancel').forEach(btn => {
                btn.addEventListener('click', () => {
                    window.location.href = sumberPath;
                });
            });

            bindRuleDocumentPreview(
                document.getElementById('inputRuleDocument'),
                document.getElementById('ruleDocumentPreview')
            );

            // Image preview for tournament image
            bindImagePreview(
                document.getElementById('inputTournamentImage'),
                document.getElementById('tournamentImagePreview')
            );

            // Participant buttons
            document.getElementById('btnAddParticipant')?.addEventListener('click', () => {
                if (!canAddParticipant()) {
                    showStatusWarning('addParticipant');
                    return;
                }
                showAddParticipantModal();
            });

            // Match buttons
            // delete all matches
            document.getElementById('btnDeleteAllMatches')?.addEventListener('click', async () => {
                if (!canClearMatches()) {
                    showStatusWarning('addMatch');
                    return;
                }
                const conf = await Swal.fire({
                    title: 'Hapus Semua Matches',
                    text: 'Semua pertandingan akan dihapus. Lanjutkan?',
                    icon: 'warning',
                    showCancelButton: true,
                    confirmButtonText: 'Ya, hapus',
                    cancelButtonText: 'Batal'
                });
                if (!conf.isConfirmed) return;

                try {
                    const fd = new URLSearchParams();
                    fd.append('p_type', 'tournament_match');
                    fd.append('p_action', 'clear_matches');
                    fd.append('IDTournament', currentTournamentId || '');
                    Swal.fire({ title: 'Menghapus...', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
                    const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                    Swal.close();
                    if (result && result.Status === 1) {
                        Swal.fire({ icon: 'success', text: result.Keterangan || 'Semua match dihapus' });
                        if (typeof loadMatches === 'function') await loadMatches();
                    } else {
                        throw new Error(result ? result.Keterangan || 'Gagal hapus' : 'Gagal hapus');
                    }
                } catch (err) {
                    Swal.fire({ icon: 'error', text: err.message || err });
                }
            });

            // clear all scores
            document.getElementById('btnClearAllScores')?.addEventListener('click', async () => {
                const canClear = currentStatus === 'ongoing';
                if (!canClear) {
                    showStatusWarning('addMatch');
                    return;
                }
                const conf = await Swal.fire({
                    title: 'Clear All Scores',
                    text: 'Skor semua pertandingan akan dikosongkan. Lanjutkan?',
                    icon: 'warning',
                    showCancelButton: true,
                    confirmButtonText: 'Ya, kosongkan',
                    cancelButtonText: 'Batal'
                });
                if (!conf.isConfirmed) return;

                try {
                    const fd = new URLSearchParams();
                    fd.append('p_type', 'tournament_match');
                    fd.append('p_action', 'clear_all_scores');
                    fd.append('IDTournament', currentTournamentId || '');
                    Swal.fire({ title: 'Mengosongkan...', allowOutsideClick: false, didOpen: () => Swal.showLoading() });
                    const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                    Swal.close();
                    if (result && result.Status === 1) {
                        Swal.fire({ icon: 'success', text: result.Keterangan || 'Skor dihapus' });
                        if (typeof loadMatches === 'function') await loadMatches();
                    } else {
                        throw new Error(result ? result.Keterangan || 'Gagal clear' : 'Gagal clear');
                    }
                } catch (err) {
                    Swal.fire({ icon: 'error', text: err.message || err });
                }
            });

            // Auto-generate matches
            document.getElementById('btnAutoGenerateMatches')?.addEventListener('click', async () => {
                if (!canAddMatch()) {
                    showStatusWarning('addMatch');
                    return;
                }
                const { isConfirmed } = await Swal.fire({
                    title: 'Generate Matches Otomatis',
                    text: 'Anda yakin ingin generate match pertanding otomatis?',
                    icon: 'warning',
                    showCancelButton: true,
                    confirmButtonText: 'Ya, buat',
                    cancelButtonText: 'Batal'
                });
                if (!isConfirmed) return;
                await autoGenerateMatches();
            });

            // Group buttons
            document.getElementById('btnAddGroup')?.addEventListener('click', () => {
                showCreateGroupModal();
            });

            document.getElementById('btnAutoGenerateGroups')?.addEventListener('click', async () => {
                await autoGenerateGroups();
            });

            document.getElementById('btnAutoGenerateGroupsAndTeams')?.addEventListener('click', async () => {
                await autoGenerateGroupsAndTeams();
            });

            // Group-Team assignment buttons
            document.getElementById('btnAddGroupTeam')?.addEventListener('click', () => {
                showAssignTeamModal();
            });

            document.getElementById('btnAutoAssignTeams')?.addEventListener('click', async () => {
                await autoAssignTeamsToGroups();
            });
        }

        function bindImagePreview(imgInput, imgPreview) {
            if (!imgInput || !imgPreview) return;

            if (imgInput.dataset.previewBound === "1") return;
            imgInput.dataset.previewBound = "1";

            imgInput.addEventListener('change', (e) => {
                const file = e.target.files[0];
                if (!file) {
                    imgPreview.src = '';
                    imgPreview.style.display = 'none';
                    return;
                }

                const reader = new FileReader();
                reader.onload = function (evt) {
                    imgPreview.src = evt.target.result;
                    imgPreview.style.display = 'block';
                };
                reader.readAsDataURL(file);
            });
        }

        function setImagePreviewFromUrl(imgPreview, url) {
            if (!imgPreview || !url) return;

            imgPreview.src = url;
            imgPreview.style.display = 'block';

            // kalau pakai ViewerJS
            if (window.Viewer) {
                if (imgPreview._viewer) {
                    imgPreview._viewer.destroy();
                }
                imgPreview._viewer = new Viewer(imgPreview, {
                    toolbar: true,
                    navbar: false
                });
            }
        }

        function bindRuleDocumentPreview(fileInput, previewContainer) {
            if (!fileInput || !previewContainer) return;

            // cegah double bind
            if (fileInput.dataset.ruleBound === "1") return;
            fileInput.dataset.ruleBound = "1";

            fileInput.addEventListener('change', (e) => {
                const file = e.target.files[0];

                previewContainer.innerHTML = '';

                if (!file) return;

                const alertDiv = document.createElement('div');
                alertDiv.className = 'alert alert-info mt-3';
                alertDiv.innerHTML = `
            <strong>File dipilih:</strong> ${file.name}<br>
            <small>File akan diupload saat disimpan.</small>
        `;

                previewContainer.appendChild(alertDiv);
            });
        }

        function setRuleDocumentPreview(previewContainer, data) {
            if (!previewContainer) return;

            previewContainer.innerHTML = '';

            if (!data || !data.RuleDocumentPath) return;

            const alertDiv = document.createElement('div');
            alertDiv.className = 'alert alert-info mt-3';

            const downloadLink = `
                <a href="${data.RuleDocumentPath}"
                target="_blank"
                class="alert-link">
                Download ${data.RuleDocumentName || 'Dokumen'}
                </a>
            `;

            alertDiv.innerHTML = `
                <strong>Dokumen Peraturan Tersedia</strong><br>
                <small>By: ${data.RuleDocumentUploadedBy || 'Unknown'}</small><br>
                <small>At: ${new Date(data.RuleDocumentUploadedAt).toLocaleString()}</small><br>
                ${downloadLink}
            `;

            previewContainer.appendChild(alertDiv);
        }


        function initStatusFlowButtons() {
            const bindControl = (el, action) => {
                if (!el) return;
                el.addEventListener('click', async (e) => {
                    e.preventDefault();
                    if (!canChangeStatus()) {
                        showStatusWarning('changeStatus');
                        return;
                    }
                    if (action === 'next') {
                        const nextStatus = STATUS_FLOW[STATUS_FLOW.indexOf(currentStatus) + 1];
                        await changeStatus(nextStatus);
                    } else if (action === 'prev') {
                        const prevStatus = STATUS_FLOW[STATUS_FLOW.indexOf(currentStatus) - 1];
                        await changeStatus(prevStatus);
                    } else if (action === 'cancel') {
                        await changeStatus('cancelled');
                    }
                });
            };

            bindControl(document.getElementById('btnNextStep'), 'next');
            bindControl(document.getElementById('btnPrevStep'), 'prev');
            bindControl(document.getElementById('btnCancelTournament'), 'cancel');

            // floating buttons
            bindControl(document.getElementById('fabNext'), 'next');
            bindControl(document.getElementById('fabPrev'), 'prev');
            bindControl(document.getElementById('fabCancel'), 'cancel');

            updateStatusFlowButtons();
        }

        // ========================
        // GROUPS & ASSIGN HANDLERS
        // ======================== 

        function showCreateGroupModal() {
            // Populate TCL select
            const sel = document.getElementById('groupTCL');
            sel.innerHTML = '<option value="">-- Pilih Kategori & Level --</option>';
            listTournamentCategoryLevel.forEach(tcl => {
                const opt = document.createElement('option');
                opt.value = tcl.IDTCL || tcl.IDTCL;
                opt.textContent = tcl.NamaKategori + ' - ' + tcl.NamaLevel;
                sel.appendChild(opt);
            });

            const modal = new bootstrap.Modal(document.getElementById('modal_create_group'));
            modal.show();
        }

        document.getElementById('btnSaveGroup')?.addEventListener('click', async () => {
            try {
                const tcl = document.getElementById('groupTCL').value;
                const name = document.getElementById('groupName').value.trim();
                if (!tcl || !name) throw new Error('TCL dan Nama Group harus diisi');

                const formData = new URLSearchParams();
                formData.append('p_type', 'tournament_group');
                formData.append('p_action', 'create_group');
                formData.append('IDTournament', currentTournamentId);
                formData.append('IDTCL', tcl);
                formData.append('GroupName', name);

                const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData });
                if (result.Status === 1) {
                    bootstrap.Modal.getInstance(document.getElementById('modal_create_group')).hide();
                    await loadGroupsTable();
                    await loadGroupTeamsTable();
                    Swal.fire({ text: result.Keterangan, icon: 'success' });
                } else {
                    throw new Error(result.Keterangan || 'Gagal membuat group');
                }
            } catch (err) {
                Swal.fire({ text: err.message, icon: 'error' });
            }
        });

        async function autoGenerateGroups() {
            try {

                const confirm = await Swal.fire({
                    title: "Generate Groups?",
                    text: "Yakin ingin melakukan generate group otomatis?",
                    icon: "question",
                    showCancelButton: true,
                    confirmButtonText: "Ya, Generate",
                    cancelButtonText: "Batal",
                    buttonsStyling: false,
                    customClass: {
                        confirmButton: "btn btn-primary",
                        cancelButton: "btn btn-light"
                    }
                });

                if (!confirm.isConfirmed) return;

                const formData = new URLSearchParams();
                formData.append('p_type', 'tournament_group');
                formData.append('p_action', 'generate_automatic');
                formData.append('IDTournament', currentTournamentId);

                const { result } = await fetch_helper({ formData });

                if (result.Status === 1) {

                    await loadGroupsTable();
                    await loadGroupTeamsTable();

                    if (result.listErrorMessage?.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "ID TCL", value: "IDTCL" },
                            { display: "Keterangan", value: "Keterangan" }
                        ]);
                    } else {
                        await Swal.fire({ text: result.Keterangan, icon: 'success' });
                    }

                } else {

                    if (result.listErrorMessage?.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "ID TCL", value: "IDTCL" },
                            { display: "Keterangan", value: "Keterangan" }
                        ]);
                    } else {
                        throw new Error(result.Keterangan);
                    }
                }

            } catch (err) {
                Swal.fire({ text: err.message, icon: 'error' });
            }
        }
        async function autoGenerateGroupsAndTeams() {
            try {

                const confirm = await Swal.fire({
                    title: "Generate Groups & Teams?",
                    text: "Yakin ingin generate group dan distribusi team otomatis?",
                    icon: "question",
                    showCancelButton: true,
                    confirmButtonText: "Ya, Generate",
                    cancelButtonText: "Batal",
                    buttonsStyling: false,
                    customClass: {
                        confirmButton: "btn btn-primary",
                        cancelButton: "btn btn-light"
                    }
                });

                if (!confirm.isConfirmed) return;

                const formData = new URLSearchParams();
                formData.append('p_type', 'tournament_group');
                formData.append('p_action', 'generate_auto_and_team');
                formData.append('IDTournament', currentTournamentId);

                const { result } = await fetch_helper({ formData });

                if (result.Status === 1) {

                    await loadGroupsTable();
                    await loadGroupTeamsTable();

                    if (result.listErrorMessage?.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "ID TCL", value: "IDTCL" },
                            { display: "Keterangan", value: "Keterangan" }
                        ]);
                    } else {
                        await Swal.fire({ text: result.Keterangan, icon: 'success' });
                    }

                } else {

                    if (result.listErrorMessage?.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "ID TCL", value: "IDTCL" },
                            { display: "Keterangan", value: "Keterangan" }
                        ]);
                    } else {
                        throw new Error(result.Keterangan);
                    }
                }

            } catch (err) {
                Swal.fire({ text: err.message, icon: 'error' });
            }
        }

        function showAssignTeamModal() {
            // populate groups and teams
            const gsel = document.getElementById('assignGroupSelect');
            const tsel = document.getElementById('assignTeamSelect');
            gsel.innerHTML = '';
            tsel.innerHTML = '';

            listTournamentCategoryLevel; // ensure exists

            // load groups synchronously from backend
            (async () => {
                const fd = new URLSearchParams();
                fd.append('p_type', 'launcher');
                fd.append('p_action', 'select');

                fd.append("getTournamentGroup", "1");
                fd.append("getTournamentGroup_IDTournament", currentTournamentId);
                fd.append("getTournamentGroup_OrderBy", "GroupName");
                fd.append("getTournamentGroup_OrderType", "ASC");

                fd.append("getTournamentRegistration", "1");
                fd.append("getTournamentRegistration_Status", "active");
                fd.append("getTournamentRegistration_IDTournament", currentTournamentId);
                fd.append("getTournamentRegistration_OrderBy", "TeamName");
                fd.append("getTournamentRegistration_OrderType", "ASC");

                fd.append('IDTournament', currentTournamentId);
                const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                if (result.Status === 1) {

                    if (result.listTournamentGroup) {
                        result.listTournamentGroup.forEach(g => {
                            const o = document.createElement('option'); o.value = g.IDGroup; o.textContent = g.GroupName; gsel.appendChild(o);
                        });
                    }

                    if (result.listTournamentRegistration) {
                        result.listTournamentRegistration.forEach(t => {
                            const o = document.createElement('option'); o.value = t.IDRegistration; o.textContent = t.TeamName; tsel.appendChild(o);
                        });

                    }
                }

                /*
            const fd = new URLSearchParams();
            fd.append('p_type', 'tournament_group');
            fd.append('p_action', 'select');
            fd.append('IDTournament', currentTournamentId);
            const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
            if (result.Status === 1 && result.list_data) {
                result.list_data.forEach(g => {
                    const o = document.createElement('option'); o.value = g.IDGroup; o.textContent = g.GroupName; gsel.appendChild(o);
                });
            }

            // teams
            const fd2 = new URLSearchParams();
            fd2.append('p_type', 'tournament_registration');
            fd2.append('p_action', 'select');
            fd2.append('IDTournament', currentTournamentId);
            const res2 = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd2 });
            if (res2.result && res2.result.Status === 1 && res2.result.list_data) {
                res2.result.list_data.forEach(t => {
                    const o = document.createElement('option'); o.value = t.IDRegistration; o.textContent = t.TeamName; tsel.appendChild(o);
                });
            }*/

                const modal = new bootstrap.Modal(document.getElementById('modal_assign_group_team'));
                modal.show();
            })();
        }

        document.getElementById('btnSaveAssign')?.addEventListener('click', async () => {
            try {
                const gid = document.getElementById('assignGroupSelect').value;
                const tid = document.getElementById('assignTeamSelect').value;
                if (!gid || !tid) throw new Error('Group dan Team harus dipilih');

                const fd = new URLSearchParams();
                fd.append('p_type', 'tournament_group_team');
                fd.append('p_action', 'update');
                fd.append('IDGroup', gid);
                fd.append('IDRegistration', tid);

                const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                if (result.Status === 1) {
                    bootstrap.Modal.getInstance(document.getElementById('modal_assign_group_team')).hide();
                    Swal.fire({ text: result.Keterangan, icon: 'success' });
                    // reload group teams
                    await loadGroupTeamsTable();
                } else {
                    throw new Error(result.Keterangan || 'Gagal assign');
                }
            } catch (err) {
                Swal.fire({ text: err.message, icon: 'error' });
            }
        });

        async function autoAssignTeamsToGroups() {
            try {

                const confirm = await Swal.fire({
                    title: "Assign Teams Otomatis?",
                    text: "Yakin ingin mendistribusikan team ke semua group yang tersedia?",
                    icon: "question",
                    showCancelButton: true,
                    confirmButtonText: "Ya, Assign",
                    cancelButtonText: "Batal",
                    buttonsStyling: false,
                    customClass: {
                        confirmButton: "btn btn-primary",
                        cancelButton: "btn btn-light"
                    }
                });

                if (!confirm.isConfirmed) return;

                const fd = new URLSearchParams();
                fd.append('p_type', 'tournament_group_team');
                fd.append('p_action', 'generate_automatic');
                fd.append('IDTournament', currentTournamentId);

                const { result } = await fetch_helper({ formData: fd });

                if (result.Status === 1) {

                    await loadGroupTeamsTable();

                    if (result.listErrorMessage?.length > 0) {

                        await q_generateListErrorMessage(result, [
                            { display: "ID TCL", value: "IDTCL" },
                            { display: "Keterangan", value: "Keterangan" }
                        ]);

                    } else {

                        await Swal.fire({
                            text: result.Keterangan || "Teams berhasil di-assign.",
                            icon: "success",
                            buttonsStyling: false,
                            confirmButtonText: "Ok",
                            customClass: { confirmButton: "btn btn-primary" }
                        });

                    }

                } else {

                    if (result.listErrorMessage?.length > 0) {

                        await q_generateListErrorMessage(result, [
                            { display: "ID TCL", value: "IDTCL" },
                            { display: "Keterangan", value: "Keterangan" }
                        ]);

                    } else {

                        throw new Error(result.Keterangan || "Gagal assign teams");

                    }
                }

            } catch (err) {

                await Swal.fire({
                    text: err.message,
                    icon: "error",
                    buttonsStyling: false,
                    confirmButtonText: "Ok",
                    customClass: { confirmButton: "btn btn-primary" }
                });

            }
        }

        async function autoGenerateMatches() {
            try {
                const fd = new URLSearchParams();
                fd.append('p_type', 'tournament_match');
                fd.append('p_action', 'generate_match');
                fd.append('IDTournament', currentTournamentId);

                const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                if (result.Status === 1) {
                    Swal.fire({ text: result.Keterangan || 'Matches generated', icon: 'success' });
                    // reload matches if function exists
                    if (typeof loadMatches === 'function') await loadMatches();
                } else {
                    throw new Error(result.Keterangan || 'Gagal generate matches');
                }
            } catch (err) {
                Swal.fire({ text: err.message, icon: 'error' });
            }
        }

        // ========================
        // MATCH LIST & SETS
        // ========================
        async function loadMatches() {
            if (!currentTournamentId) return;
            // prefer selected TCL
            let IDTCL = '';

            const fd = new URLSearchParams();
            fd.append('p_type', 'tournament_match');
            fd.append('p_action', 'get_summary');
            fd.append('IDTCL', IDTCL);
            fd.append('IDTournament', currentTournamentId);

            const { result } = await fetch_helper({ formData: fd });

            if (result.Status !== 1) throw new Error(result.Keterangan || 'Gagal load matches');


            setMatchesElement(result);
        }

        function setMatchesElement(listData) {
            // container is the matches table wrapper inside scoreboard section
            const container = document.getElementById('matchesTableContainer');
            if (listData) {

                // ensure summary container exists (placed above matches table)
                let summaryContainer = document.getElementById('tournamentSummaryContainer');
                if (!summaryContainer) {
                    summaryContainer = document.createElement('div');
                    summaryContainer.id = 'tournamentSummaryContainer';
                    if (container && container.parentNode) container.parentNode.insertBefore(summaryContainer, container);
                }

                // use backend-provided structure if available
                const summaryData = listData;
                generateTournamentSummary(summaryData, '#tournamentSummaryContainer', { tournamentFormat: summaryData?.TournamentFormat || summaryData?.TournamentInfo?.TournamentFormat });



                // mulai editor
                // ensure editor container exists and render editor when tournament is ongoing
                try {
                    let editorContainer = document.getElementById('tournamentMatchEditorContainer');
                    if (!editorContainer) {
                        editorContainer = document.createElement('div');
                        editorContainer.id = 'tournamentMatchEditorContainer';
                        container.parentNode.insertBefore(editorContainer, container.nextSibling);
                    }

                    // default callbacks for match editor (can be overridden by passing custom callbacks)
                    const edit_action_callback = async (payload) => {
                        // payload: { ids: [id], match }
                        try {
                            const match = payload.match;
                            if (match) {
                                // existing helper to open edit modal
                                showEditMatchSets(match);
                            }
                            return { Status: 1 };
                        } catch (err) {
                            console.error('edit_action_callback error', err);
                            return { Status: 0, Keterangan: err.message };
                        }
                    };

                    const set_action_callback = async (payload) => {
                        try {
                            const match = payload.match;
                            if (match) setMatchSets(match);
                            return { Status: 1 };
                        } catch (err) {
                            console.error('set_action_callback error', err);
                            return { Status: 0, Keterangan: err.message };
                        }
                    };

                    const delete_action_callback = async (payload) => {
                        // show confirm modal, then call backend to delete
                        try {
                            const ids = payload.ids || [];
                            if (!ids.length) return { Status: 0, Keterangan: 'No ids' };

                            // show confirm modal
                            const msgEl = document.getElementById('modal_confirm_message');
                            msgEl.textContent = 'Anda yakin ingin menghapus pertandingan ini?';
                            const confirmModal = new bootstrap.Modal(document.getElementById('modal_confirm_action'));

                            const okBtn = document.getElementById('modal_confirm_ok');
                            return await new Promise((resolve) => {
                                const onOk = async () => {
                                    okBtn.removeEventListener('click', onOk);
                                    confirmModal.hide();

                                    try {
                                        const formData = new URLSearchParams();
                                        formData.append('p_type', 'tournament_match');
                                        formData.append('p_action', 'delete_score');
                                        formData.append('IDMatch', ids[0]);

                                        const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData });
                                        if (result) {
                                            if (result.listErrorMessage && result.listErrorMessage.length > 0) {
                                                await q_generateListErrorMessage(result, [
                                                    { display: 'Nama', value: 'NamaTournament' },
                                                    { display: 'Keterangan', value: 'Keterangan' },
                                                ]);
                                            } else {
                                                Swal.fire({ text: result.Keterangan || 'Pertandingan berhasil dihapus', icon: result.Status === 1 ? 'success' : 'error', confirmButtonText: 'OK' });
                                            }
                                        }
                                        // refresh matches
                                        await loadMatches();
                                        resolve(result || { Status: 1 });
                                    } catch (err) {
                                        console.error('delete action failed', err);
                                        resolve({ Status: 0, Keterangan: err.message });
                                    }
                                };

                                okBtn.addEventListener('click', onOk);
                                confirmModal.show();
                            });
                        } catch (err) {
                            console.error('delete_action_callback error', err);
                            return { Status: 0, Keterangan: err.message };
                        }
                    };

                    const afterAction = async (info) => {
                        // info: { action, id, result }
                        // refresh matches by default
                        try { await loadMatches(); } catch (e) { }
                    };


                    // callback to open shuffle/edit modal for a group
                    const onShuffleGroup = async (payload) => {
                        try {
                            const IDGroup = payload.IDGroup;
                            const group = payload.group || {};
                            const summary = summaryData;

                            // collect teams for the group
                            const gTeams = (summary.listGroupTeams || []).filter(t => String(t.IDGroup) === String(IDGroup)).map(t => ({ id: t.IDRegistration || t.IDTeam || t.id, name: t.TeamName || t.Team || t.name }));

                            // collect matches for the group
                            let gm = (summary.listMatches || []).filter(m => String(m.IDGroup) === String(IDGroup));
                            gm.sort((a, b) => (a.RoundNumber - b.RoundNumber) || (a.MatchNumber - b.MatchNumber));

                            const formatType = (summary.TournamentFormat || summary.TournamentInfo?.TournamentFormat || 'round_robin').toLowerCase();

                            // validation: disallow editing if already played matches exist (round-robin) or round1 already played (single elimination)
                            const anyPlayed = gm.some(m => { const s = String(m.Status || '').toLowerCase(); return s && s !== 'pending'; });

                            if (formatType === 'round_robin' && anyPlayed) {

                                const result = await Swal.fire({
                                    icon: 'warning',
                                    text: 'Tidak bisa mengedit karena sudah ada pertandingan yang selesai pada beberapa ronde.',
                                    confirmButtonText: 'OK'
                                });

                                if (result.isConfirmed) {
                                    return {
                                        Status: 0,
                                        Keterangan: 'Matches already played'
                                    };
                                }

                            }

                            if (formatType === 'single_elimination') {

                                const round1Played = gm
                                    .filter(m => Number(m.RoundNumber) === 1)
                                    .some(m => {
                                        const s = String(m.Status || '').toLowerCase();
                                        return s && s !== 'pending';
                                    });

                                if (round1Played) {

                                    const result = await Swal.fire({
                                        icon: 'warning',
                                        text: 'Tidak bisa mengedit ronde 1 karena sudah ada pertandingan yang selesai.',
                                        confirmButtonText: 'OK'
                                    });

                                    if (result.isConfirmed) {
                                        return { Status: 0, Keterangan: 'Round1 already played' };
                                    }

                                }
                            }

                            // create modal if not exists
                            let modalEl = document.getElementById('modal_shuffle_matches');
                            if (!modalEl) {
                                modalEl = document.createElement('div');
                                modalEl.id = 'modal_shuffle_matches';
                                modalEl.className = 'modal fade';
                                modalEl.tabIndex = -1;
                                modalEl.role = 'dialog';
                                modalEl.innerHTML = `
                                    <div class="modal-dialog modal-lg modal-dialog-centered" role="document">
                                        <div class="modal-content">
                                            <div class="modal-header">
                                                <h5 class="modal-title">Edit Matches - <span id="modal_shuffle_title"></span></h5>
                                                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                                            </div>
                                            <div class="modal-body">
                                                <div id="modal_shuffle_body"></div>
                                            </div>
                                            <div class="modal-footer">
                                                <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
                                                <button type="button" class="btn btn-primary" id="modal_shuffle_save">Save changes</button>
                                            </div>
                                        </div>
                                    </div>`;
                                document.body.appendChild(modalEl);
                            }

                            // populate modal content
                            document.getElementById('modal_shuffle_title').textContent = group.GroupName || ('Group ' + IDGroup);
                            const body = document.getElementById('modal_shuffle_body');
                            body.innerHTML = '';

                            // TCL info
                            const tclInfo = document.createElement('div');
                            tclInfo.className = 'mb-3';
                            tclInfo.innerHTML = '<strong>Group:</strong> ' + (group.GroupName || '') + '<br/>';
                            body.appendChild(tclInfo);

                            // Build editable table
                            const tableWrap = document.createElement('div');
                            tableWrap.className = 'table-responsive';
                            const tbl = document.createElement('table'); tbl.className = 'table table-sm table-bordered';
                            const thead = document.createElement('thead'); thead.className = 'table-light';
                            thead.innerHTML = '<tr><th style="width:60px">No</th><th style="width:90px">Ronde</th><th>Team 1</th><th>Team 2</th><th style="width:200px">Match Date</th></tr>';
                            tbl.appendChild(thead);
                            const tbody = document.createElement('tbody');

                            // choose rows to render
                            let rowsToRender = gm;
                            if (formatType === 'single_elimination') {
                                rowsToRender = gm.filter(m => Number(m.RoundNumber) === 1);
                            }

                            rowsToRender.forEach((m, idx) => {
                                const tr = document.createElement('tr');
                                tr.dataset.id = m.IDMatch;
                                const tdNo = document.createElement('td'); tdNo.textContent = idx + 1;
                                const tdRound = document.createElement('td'); tdRound.textContent = m.RoundNumber || '';
                                const tdA = document.createElement('td');
                                const selA = document.createElement('select'); selA.className = 'form-select form-select-sm select-team-a';
                                const phA = document.createElement('option'); phA.value = ''; phA.textContent = '-- Team 1 --'; selA.appendChild(phA);
                                gTeams.forEach(t => { const o = document.createElement('option'); o.value = t.id; o.textContent = t.name || ('Team ' + t.id); if (String(t.id) === String(m.TeamA)) o.selected = true; selA.appendChild(o); });
                                tdA.appendChild(selA);

                                const tdB = document.createElement('td');
                                const selB = document.createElement('select'); selB.className = 'form-select form-select-sm select-team-b';
                                const phB = document.createElement('option'); phB.value = ''; phB.textContent = '-- Team 2 --'; selB.appendChild(phB);
                                gTeams.forEach(t => { const o = document.createElement('option'); o.value = t.id; o.textContent = t.name || ('Team ' + t.id); if (String(t.id) === String(m.TeamB)) o.selected = true; selB.appendChild(o); });
                                tdB.appendChild(selB);

                                const tdDate = document.createElement('td');
                                const inp = document.createElement('input'); inp.type = 'datetime-local'; inp.className = 'form-control form-control-sm match-date-input';
                                if (m.MatchDate) {
                                    const d = new Date(m.MatchDate);
                                    const pad = (n) => String(n).padStart(2, '0');
                                    const val = d.getFullYear() + '-' + pad(d.getMonth() + 1) + '-' + pad(d.getDate()) + 'T' + pad(d.getHours()) + ':' + pad(d.getMinutes());
                                    inp.value = val;
                                }
                                tdDate.appendChild(inp);

                                tr.appendChild(tdNo); tr.appendChild(tdRound); tr.appendChild(tdA); tr.appendChild(tdB); tr.appendChild(tdDate);
                                tbody.appendChild(tr);
                            });

                            tbl.appendChild(tbody);
                            tableWrap.appendChild(tbl);
                            body.appendChild(tableWrap);

                            // show modal
                            const bsModal = new bootstrap.Modal(modalEl);
                            bsModal.show();

                            // save handler
                            const saveBtn = document.getElementById('modal_shuffle_save');
                            const onSave = async () => {
                                try {
                                    // gather rows
                                    const rows = Array.from(tbody.querySelectorAll('tr'));
                                    const payloadMatches = [];
                                    const roundsMapLocal = {};
                                    let invalid = null;
                                    for (const row of rows) {
                                        const id = row.dataset.id;
                                        const teamA = row.querySelector('.select-team-a').value;
                                        const teamB = row.querySelector('.select-team-b').value;
                                        const dt = row.querySelector('.match-date-input').value;
                                        const round = row.children[1].textContent || '';

                                        if (!teamA || !teamB) { invalid = 'Semua baris harus memiliki Team 1 dan Team 2.'; break; }
                                        if (teamA === teamB) { invalid = 'Team 1 dan Team 2 tidak boleh sama.'; break; }

                                        // per-round checks
                                        roundsMapLocal[round] = roundsMapLocal[round] || { teams: {}, pairs: {} };
                                        // count team occurrences
                                        roundsMapLocal[round].teams[teamA] = (roundsMapLocal[round].teams[teamA] || 0) + 1;
                                        roundsMapLocal[round].teams[teamB] = (roundsMapLocal[round].teams[teamB] || 0) + 1;
                                        // pair key (unordered)
                                        const pairKey = [teamA, teamB].sort().join('::');
                                        roundsMapLocal[round].pairs[pairKey] = (roundsMapLocal[round].pairs[pairKey] || 0) + 1;

                                        payloadMatches.push({ IDMatch: id, TeamA: teamA, TeamB: teamB, MatchDate: dt, RoundNumber: round });
                                    }

                                    if (invalid) {
                                        Swal.fire({ icon: 'error', text: invalid });
                                        return;
                                    }

                                    // validate rules
                                    for (const rn of Object.keys(roundsMapLocal)) {
                                        const info = roundsMapLocal[rn];
                                        // no team should appear more than once in same round
                                        for (const tId of Object.keys(info.teams)) {
                                            if (info.teams[tId] > 1) {
                                                Swal.fire({ icon: 'error', text: 'Satu team tampil lebih dari sekali pada ronde ' + rn });
                                                return;
                                            }
                                        }
                                        // pairs duplication
                                        for (const pk of Object.keys(info.pairs)) {
                                            if (info.pairs[pk] > 1) {
                                                Swal.fire({ icon: 'error', text: 'Pertandingan duplikat pada ronde ' + rn });
                                                return;
                                            }
                                        }
                                    }

                                    // send to backend
                                    const formData = new URLSearchParams();
                                    formData.append('p_type', 'tournament_match');
                                    formData.append('p_action', 'save_matches_bulk');
                                    formData.append('IDTournament', currentTournamentId || '');
                                    formData.append('IDGroup', IDGroup || '');
                                    formData.append('matches', JSON.stringify(payloadMatches));

                                    const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData });
                                    if (result && result.Status === 1) {
                                        bsModal.hide();
                                        await loadMatches();
                                        if (typeof afterAction === 'function') await afterAction({ action: 'shuffle-save', id: IDGroup, result });
                                    } else {
                                        Swal.fire({ icon: 'error', text: result?.Keterangan || 'Gagal menyimpan' });
                                    }
                                } catch (err) {
                                    console.error('save shuffle error', err);
                                    Swal.fire({ icon: 'error', text: err.message || 'Error' });
                                }
                            };

                            // bind once
                            saveBtn.removeEventListener('click', onSave);
                            saveBtn.addEventListener('click', onSave);

                            return { Status: 1 };
                        } catch (err) {
                            console.error('onShuffleGroup error', err);
                            return { Status: 0, Keterangan: err.message };
                        }
                    };

                    const onNextRound = async ({ IDGroup, RoundNumber }) => {
                        try {

                            Swal.fire({
                                title: "Processing...",
                                allowOutsideClick: false,
                                didOpen: () => Swal.showLoading(),
                            });

                            const fd = new URLSearchParams();
                            fd.append("p_type", "tournament_match");
                            fd.append("p_action", "generate_next_round");
                            fd.append("IDTournament", currentTournamentId || "");
                            fd.append("IDGroup", IDGroup);
                            fd.append("RoundNumber", RoundNumber);

                            const { result } = await fetch_helper({
                                i18nKey: "",
                                fetchFile: "",
                                formData: fd,
                            });

                            Swal.close();

                            if (result.Status !== 1) {
                                throw new Error(result.Keterangan || "Failed generate next round");
                            }

                            await Swal.fire({
                                icon: "success",
                                title: "Success",
                                text: result.Keterangan || "Next round created successfully.",
                            });

                            await loadMatches();

                            return result;

                        } catch (err) {
                            Swal.fire({
                                icon: "error",
                                title: "Error",
                                text: err.message || err,
                            });

                            return { Status: 0, Keterangan: err.message };
                        }
                    };

                    const onCancelRound = async ({ IDGroup, RoundNumber }) => {
                        try {

                            Swal.fire({
                                title: "Processing...",
                                allowOutsideClick: false,
                                didOpen: () => Swal.showLoading(),
                            });

                            const fd = new URLSearchParams();
                            fd.append("p_type", "tournament_match");
                            fd.append("p_action", "cancel_round");
                            fd.append("IDTournament", currentTournamentId || "");
                            fd.append("IDGroup", IDGroup);
                            fd.append("RoundNumber", RoundNumber);

                            const { result } = await fetch_helper({
                                i18nKey: "",
                                fetchFile: "",
                                formData: fd,
                            });

                            Swal.close();

                            if (result.Status !== 1) {
                                throw new Error(result.Keterangan || "Failed cancel round");
                            }

                            await Swal.fire({
                                icon: "success",
                                title: "Cancelled",
                                text: result.Keterangan || "Round successfully cancelled.",
                            });

                            await loadMatches();

                            return result;

                        } catch (err) {
                            Swal.fire({
                                icon: "error",
                                title: "Error",
                                text: err.message || err,
                            });

                            return { Status: 0, Keterangan: err.message };
                        }
                    };

                    generateMatchEditor(summaryData, '#tournamentMatchEditorContainer', {
                        tournamentFormat: summaryData?.TournamentFormat || summaryData?.TournamentInfo?.TournamentFormat,
                        onEditMatch: edit_action_callback,
                        onDeleteMatch: delete_action_callback,
                        onSetMatch: set_action_callback,
                        onShuffleGroup: onShuffleGroup,
                        onNextRound: onNextRound,
                        onCancelRound: onCancelRound,
                        onAfterAction: afterAction
                    });


                    // Leaderboard container (read-only summary). locate inside leaderboardSection if available.
                    let leaderboardContainer = document.getElementById('tournamentLeaderboardContainer');
                    if (!leaderboardContainer) {
                        leaderboardContainer = document.createElement('div');
                        leaderboardContainer.id = 'tournamentLeaderboardContainer';
                        leaderboardContainer.className = 'mt-4';
                        const hostSection = document.getElementById('leaderboardSection');
                        if (hostSection) {
                            const body = hostSection.querySelector('.card-body');
                            if (body) body.appendChild(leaderboardContainer);
                            else hostSection.appendChild(leaderboardContainer);
                        } else if (editorContainer && editorContainer.parentNode) {
                            editorContainer.parentNode.insertBefore(leaderboardContainer, editorContainer.nextSibling);
                        }
                    }

                    try {
                        if (summaryData.TournamentInfo.StatusTournament === 'finished') {
                            // add generate report button
                            const btnWrap = document.createElement('div');
                            btnWrap.className = 'mb-3';
                            // Show report info if available
                            if (summaryData.TournamentInfo.ReportGeneratedName) {
                                const infoDiv = document.createElement('div');
                                infoDiv.className = 'alert alert-info mb-3';
                                const reportPath = `<?php echo $baseUrl ?>admin/attachments/tournament/${currentTournamentId}/${summaryData.TournamentInfo.ReportGeneratedName}`;
                                const downloadLink = `<a href="${summaryData.TournamentInfo.ReportGeneratedPath}" target="_blank" class="alert-link">Download Report</a>`;
                                infoDiv.innerHTML = `
                                    <strong>Report Generated</strong><br>
                                    <small>By: ${summaryData.TournamentInfo.ReportGeneratedBy || 'Unknown'}</small><br>
                                    <small>At: ${new Date(summaryData.TournamentInfo.ReportGeneratedAt).toLocaleString()}</small><br>
                                    ${downloadLink}
                                `;
                                btnWrap.appendChild(infoDiv);
                            }

                            // Generate button
                            const genBtn = document.createElement('div');
                            genBtn.className = 'd-flex justify-content-end';
                            genBtn.innerHTML = `<button id="btnGenerateReport" class="btn btn-sm btn-primary">Generate Excel Report</button>`;
                            btnWrap.appendChild(genBtn);

                            leaderboardContainer.innerHTML = '';
                            leaderboardContainer.appendChild(btnWrap);

                            // render leaderboard (generateLeaderboard provided by tournament_helper.js)
                            if (typeof generateLeaderboard === 'function') {
                                const boardDiv = document.createElement('div');
                                boardDiv.id = 'tournamentLeaderboardContent';
                                leaderboardContainer.appendChild(boardDiv);
                                generateLeaderboard(summaryData, '#tournamentLeaderboardContent', { tournamentFormat: summaryData?.TournamentFormat || summaryData?.TournamentInfo?.TournamentFormat });
                            } else {
                                const div = document.createElement('div');
                                div.className = 'text-muted p-2';
                                div.textContent = 'Leaderboard tidak tersedia.';
                                leaderboardContainer.appendChild(div);
                            }

                            // bind button
                            setTimeout(() => {
                                const gb = document.getElementById('btnGenerateReport');
                                if (gb) gb.addEventListener('click', async () => {
                                    try {
                                        const conf = await Swal.fire({
                                            title: 'Generate Report',
                                            text: 'Buat report Excel untuk seluruh kategori & level?',
                                            icon: 'question',
                                            showCancelButton: true,
                                            confirmButtonText: 'Ya, buat',
                                            cancelButtonText: 'Batal'
                                        });

                                        if (!conf.isConfirmed) return;

                                        const fd = new URLSearchParams();
                                        fd.append('p_type', 'tournament');
                                        fd.append('p_action', 'generate_report');
                                        fd.append('IDTournament', currentTournamentId);

                                        Swal.fire({
                                            title: 'Generating...',
                                            allowOutsideClick: false,
                                            didOpen: () => Swal.showLoading()
                                        });

                                        const { result } = await fetch_helper({
                                            i18nKey: '',
                                            fetchFile: '',
                                            formData: fd
                                        });

                                        Swal.close();

                                        if (result && result.Status === 1) {

                                            await Swal.fire({
                                                title: 'Selesai',
                                                text: 'Report berhasil dibuat',
                                                icon: 'success'
                                            });

                                            // 🔥 Panggil function tanpa reload
                                            if (typeof loadMatches === 'function') {
                                                await loadMatches();
                                            }

                                        } else {
                                            throw new Error(result ? result.Keterangan || 'Gagal generate report' : 'Gagal generate report');
                                        }

                                    } catch (err) {
                                        Swal.fire({
                                            text: err.message || err,
                                            icon: 'error'
                                        });
                                    }
                                });
                            }, 50);
                        } else {
                            leaderboardContainer.innerHTML = '';
                        }
                    } catch (err) {
                        console.error('Failed to render leaderboard', err);
                    }
                } catch (e) {
                    console.error('Failed to render match editor', e);
                }
            } else {
                document.getElementById('tournamentSummaryContainer').innerHTML = '<div class="text-muted p-2">Ringkasan tidak tersedia.</div>';
            }
        }

        function showEditMatchSets(match) {
            // populate modal fields for edit OR for manual add (if match is null)
            const container = document.getElementById('scoreEntriesContainer');
            container.innerHTML = '';

            const isEdit = !!match;

            const info = document.createElement('div');
            info.className = 'mb-3';
            info.innerHTML = `<div class="mb-2"><strong>${isEdit ? 'Match ' + (match.MatchNumber || '') : 'Tambah Pertandingan Manual'}</strong> ${isEdit ? (' — ' + (match.TeamAName || '-') + ' vs ' + (match.TeamBName || '-')) : ''}</div>`;
            container.appendChild(info);

            // TCL select (single combined field)
            const tclRow = document.createElement('div');
            tclRow.className = 'row mb-3';
            const selWrapper = document.createElement('div');
            selWrapper.className = 'col-md-12';
            const lbl = document.createElement('label'); lbl.className = 'form-label required'; lbl.textContent = 'Kategori & Level';
            const sel = document.createElement('select'); sel.id = 'modalMatchTCL'; sel.className = 'form-select';
            const ph = document.createElement('option'); ph.value = ''; ph.textContent = '-- Pilih Kategori & Level --'; sel.appendChild(ph);
            const selectedTCL = (match && (match.IDTCL || match.IDTCL)) || '';
            (listTournamentCategoryLevel || []).forEach(tcl => {
                const opt = document.createElement('option');
                opt.value = tcl.IDTCL;
                opt.textContent = (tcl.NamaKategori || '') + ' - ' + (tcl.NamaLevel || '');
                if (String(tcl.IDTCL) === String(selectedTCL)) opt.selected = true;
                sel.appendChild(opt);
            });
            selWrapper.appendChild(lbl);
            selWrapper.appendChild(sel);
            tclRow.appendChild(selWrapper);
            container.appendChild(tclRow);

            // Team selects (populated from backend tournament_registration)
            const teamsRow = document.createElement('div');
            teamsRow.className = 'row mb-3';
            teamsRow.innerHTML = `<div class="col-md-6"><label class="form-label required">Tim A</label><select id="modalTeamA" class="form-select"><option value="">-- Pilih Tim --</option></select></div>
                                  <div class="col-md-6"><label class="form-label required">Tim B</label><select id="modalTeamB" class="form-select"><option value="">-- Pilih Tim --</option></select></div>`;
            container.appendChild(teamsRow);

            // Match date (single)
            const dateRow = document.createElement('div');
            dateRow.className = 'row mb-3';
            dateRow.innerHTML = `<div class="col-md-12"><label class="form-label">Tanggal Pertandingan</label><input type="datetime-local" id="modalMatchDate" class="form-control" value="${isEdit && match.MatchDate ? new Date(match.MatchDate).toISOString().slice(0, 16) : ''}" /></div>`;
            container.appendChild(dateRow);

            // Winner select (Team A/B/Draw/null)
            const winRow = document.createElement('div');
            winRow.className = 'row mb-3';
            winRow.innerHTML = `<div class="col-md-12"><label class="form-label">Pemenang</label><select id="modalWinnerSelect" class="form-select"><option value="">-- Pilih Pemenang --</option><option value="0">Draw</option></select></div>`;
            container.appendChild(winRow);

            // populate team options via backend
            (async () => {
                try {
                    const fd = new URLSearchParams();
                    fd.append('p_type', 'tournament_registration');
                    fd.append('p_action', 'select');
                    fd.append('IDTournament', currentTournamentId);
                    const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                    const selA = document.getElementById('modalTeamA');
                    const selB = document.getElementById('modalTeamB');
                    if (result && result.Status === 1 && result.list_data) {
                        result.list_data.forEach(reg => {
                            const opt = document.createElement('option');
                            opt.value = reg.IDRegistration || reg.IDTeam || reg.IDRegistration;
                            opt.textContent = reg.TeamName || reg.Team || opt.value;
                            selA.appendChild(opt.cloneNode(true));
                            selB.appendChild(opt.cloneNode(true));
                        });

                        // if edit, set selected and disable
                        if (isEdit) {
                            if (match.TeamA) selA.value = match.TeamA;
                            if (match.TeamB) selB.value = match.TeamB;
                            selA.disabled = true;
                            selB.disabled = true;
                            // disable TCL selection when editing
                            document.getElementById('modalMatchTCL').disabled = true;
                        }

                        // populate winner select now that team options exist
                        const winnerSel = document.getElementById('modalWinnerSelect');
                        const updateWinnerOptions = () => {
                            // keep placeholder and Draw (value 0), remove other options
                            const keep = ['', '0'];
                            Array.from(winnerSel.options).forEach(opt => {
                                if (!keep.includes(opt.value)) opt.remove();
                            });
                            const teamAVal2 = selA.value || '';
                            const teamBVal2 = selB.value || '';
                            if (teamAVal2) {
                                const optA = document.createElement('option'); optA.value = teamAVal2; optA.textContent = (selA.options[selA.selectedIndex] || {}).text || 'Team A';
                                winnerSel.appendChild(optA);
                            }
                            if (teamBVal2) {
                                const optB = document.createElement('option'); optB.value = teamBVal2; optB.textContent = (selB.options[selB.selectedIndex] || {}).text || 'Team B';
                                winnerSel.appendChild(optB);
                            }
                        };

                        selA.addEventListener('change', updateWinnerOptions);
                        selB.addEventListener('change', updateWinnerOptions);

                        updateWinnerOptions();

                        // set winner value if exists (0 means draw, '' means null)
                        if (isEdit && (match.WinnerTeam === 0 || match.WinnerTeam === '0')) winnerSel.value = '0';
                        else if (isEdit && match.WinnerTeam) winnerSel.value = match.WinnerTeam;
                    }
                } catch (e) {
                    console.error('Failed to load tournament registrations', e);
                }
            })();

            // existing scores (editable, can be empty when editing)
            const scores = (match && match.Scores) || [];
            const maxSets = Math.max(3, scores.length);
            for (let s = 1; s <= maxSets; s++) {
                const row = document.createElement('div');
                row.className = 'row mb-2';
                const valA = (scores.find(x => x.SetNumber == s) || {}).ScoreTeamA || '';
                const valB = (scores.find(x => x.SetNumber == s) || {}).ScoreTeamB || '';
                row.innerHTML = `<div class="col-2 align-self-center">Set ${s}</div>
                    <div class="col-5"><input type="number" min="0" class="form-control set-score-a" data-set="${s}" placeholder="Skor A" value="${valA}" /></div>
                    <div class="col-5"><input type="number" min="0" class="form-control set-score-b" data-set="${s}" placeholder="Skor B" value="${valB}" /></div>`;
                container.appendChild(row);
            }

            // store match id (if edit)
            document.getElementById('matchId').value = isEdit ? match.IDMatch : '';

            // configure save button dataset
            const saveBtn = document.getElementById('btnSaveMatch');
            if (saveBtn) {
                if (isEdit) {
                    saveBtn.dataset.matchId = match.IDMatch;
                    delete saveBtn.dataset.requireScores;
                } else {
                    delete saveBtn.dataset.matchId;
                    delete saveBtn.dataset.requireScores;
                }
            }

            const modal = new bootstrap.Modal(document.getElementById('modal_add_match'));
            modal.show();
        }

        function setMatchSets(match) {
            // simpler modal: only sets inputs (3) and required
            const container = document.getElementById('scoreEntriesContainer');
            container.innerHTML = '';

            const info = document.createElement('div');
            info.className = 'mb-3';
            info.innerHTML = `<div class="mb-2"><strong>Set Scores — ${match.TeamAName || '-'} vs ${match.TeamBName || '-'}</strong></div>`;
            container.appendChild(info);

            const scores = match.Scores || [];
            for (let s = 1; s <= 3; s++) {
                const row = document.createElement('div');
                row.className = 'row mb-2';
                const valA = (scores.find(x => x.SetNumber == s) || {}).ScoreTeamA || '';
                const valB = (scores.find(x => x.SetNumber == s) || {}).ScoreTeamB || '';
                row.innerHTML = `<div class="col-2 align-self-center">Set ${s}</div>
                    <div class="col-5"><input type="number" min="0" class="form-control set-score-a" data-set="${s}" placeholder="Skor ${match.TeamAName || 'A'}" value="${valA}" /></div>
                    <div class="col-5"><input type="number" min="0" class="form-control set-score-b" data-set="${s}" placeholder="Skor ${match.TeamBName || 'B'}" value="${valB}" /></div>`;
                container.appendChild(row);
            }

            // store match id
            document.getElementById('matchId').value = match.IDMatch;
            const saveBtn = document.getElementById('btnSaveMatch');
            if (saveBtn) {
                saveBtn.dataset.matchId = match.IDMatch;
                saveBtn.dataset.requireScores = '1';
            }

            const modal = new bootstrap.Modal(document.getElementById('modal_add_match'));
            modal.show();
        }

        document.getElementById('btnSaveMatch')?.addEventListener('click', async (ev) => {
            try {
                const btn = ev.currentTarget;
                const dataset = (btn && btn.dataset) ? btn.dataset : {};
                let matchId = dataset.matchId || (document.getElementById('matchId') ? document.getElementById('matchId').value : '');
                const requireScores = dataset.requireScores === '1';

                // collect sets
                const scoresA = Array.from(document.querySelectorAll('.set-score-a'));
                const sets = [];
                for (const inp of scoresA) {
                    const s = parseInt(inp.getAttribute('data-set'));
                    const aVal = inp.value;
                    const bInp = document.querySelector(`.set-score-b[data-set="${s}"]`);
                    const bVal = bInp ? bInp.value : '';
                    if (requireScores && (aVal === '' || bVal === '')) throw new Error('Semua skor harus diisi');
                    if (aVal === '' && bVal === '') continue; // skip empty
                    const a = aVal === '' ? 0 : Number(aVal);
                    const b = bVal === '' ? 0 : Number(bVal);
                    sets.push({ SetNumber: s, ScoreTeamA: a, ScoreTeamB: b });
                }

                if (requireScores && sets.length === 0) throw new Error('Skor wajib diisi');

                const winnerVal = document.getElementById('modalWinnerSelect') ? document.getElementById('modalWinnerSelect').value : '';
                const matchDate = document.getElementById('modalMatchDate') ? document.getElementById('modalMatchDate').value : null;

                // if no matchId -> create match first
                if (!matchId) {
                    const fdCreate = new URLSearchParams();
                    fdCreate.append('p_type', 'tournament_match');
                    fdCreate.append('p_action', 'create');
                    fdCreate.append('IDTournament', currentTournamentId);
                    const tclSel = document.getElementById('modalMatchTCL');
                    if (tclSel && tclSel.value) fdCreate.append('IDTCL', tclSel.value);
                    const ta = document.getElementById('modalTeamA');
                    const tb = document.getElementById('modalTeamB');
                    if (ta && ta.value) fdCreate.append('TeamA', ta.value);
                    if (tb && tb.value) fdCreate.append('TeamB', tb.value);
                    if (matchDate) fdCreate.append('MatchDate', matchDate);

                    const { result: resCreate } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fdCreate });
                    if (!(resCreate && resCreate.Status === 1)) throw new Error(resCreate ? resCreate.Keterangan || 'Gagal membuat match' : 'Gagal membuat match');
                    matchId = resCreate.IDMatch || resCreate.ID || resCreate.insertId || resCreate.lastInsertId || resCreate.LastInsertId;
                    if (!matchId) throw new Error('ID match tidak diterima dari server');
                }

                // if sets provided, update scores
                if (sets.length > 0) {
                    const fd = new URLSearchParams();
                    fd.append('p_type', 'tournament');
                    fd.append('p_action', 'update_match_score');
                    fd.append('IDMatch', matchId);
                    fd.append('Scores', JSON.stringify(sets));
                    fd.append('WinnerTeam', winnerVal !== '' ? winnerVal : '');
                    const { result } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd });
                    if (!(result && result.Status === 1)) throw new Error(result ? result.Keterangan || 'Gagal menyimpan score' : 'Gagal menyimpan score');
                }

                // update match metadata
                const fd2 = new URLSearchParams();
                fd2.append('p_type', 'tournament');
                fd2.append('p_action', 'update_match');
                fd2.append('IDMatch', matchId);
                if (matchDate) fd2.append('MatchDate', matchDate);
                if (winnerVal !== '') fd2.append('WinnerTeam', winnerVal === '0' ? '0' : winnerVal);
                if (sets.length > 0) fd2.append('Status', 'finished');
                const { result: res2 } = await fetch_helper({ i18nKey: '', fetchFile: '', formData: fd2 });
                if (!(res2 && res2.Status === 1)) throw new Error(res2 ? res2.Keterangan || 'Gagal update match' : 'Gagal update match');

                bootstrap.Modal.getInstance(document.getElementById('modal_add_match')).hide();
                Swal.fire({ text: 'Operasi berhasil', icon: 'success' });
                await loadMatches();
            } catch (err) {
                Swal.fire({ text: err.message, icon: 'error' });
            }
        });

        async function changeStatus(newStatus) {
            const { isConfirmed } = await Swal.fire({
                title: 'Konfirmasi Perubahan Status',
                text: `Ubah status tournament menjadi ${STATUS_LABELS[newStatus]}?`,
                icon: 'warning',
                showCancelButton: true,
                confirmButtonText: 'Ya, ubah',
                cancelButtonText: 'Batal',
            });

            if (!isConfirmed) return;

            try {
                const formData = new URLSearchParams();
                formData.append("p_type", main_pk);
                formData.append("p_action", "update_status");
                formData.append("IDTournament", currentTournamentId);
                formData.append("StatusTournament", newStatus);

                // If changing from finished to ongoing, delete tournament standing
                if (currentStatus === 'finished' && newStatus === 'ongoing') {
                    formData.append("clearStanding", "1");
                }

                const { result } = await fetch_helper({
                    i18nKey: "",
                    fetchFile: "",
                    formData: formData,
                });

                if (result.Status === 1) {
                    currentStatus = newStatus;
                    updateStatusDisplay();
                    updateStatusFlowButtons();

                    // Reload matches to refresh UI if standing was cleared
                    if (typeof loadMatches === 'function') {
                        await loadMatches();
                    }

                    Swal.fire({
                        text: "Status tournament berhasil diubah",
                        icon: "success",
                        confirmButtonText: "OK",
                    });
                } else {
                    throw new Error(result.Keterangan);
                }
            } catch (error) {
                Swal.fire({
                    text: error.message,
                    icon: "error",
                    confirmButtonText: "OK",
                });
            }
        }

        // ========================
        // CATEGORY & LEVEL MANAGEMENT
        // ========================
        let categoryLevelEntries = [];

        function initCategoryLevelHandlers() {
            document.getElementById('btnAddCategoryLevel')?.addEventListener('click', function () {
                addCategoryLevelEntry();
            });
        }

        function displayCategoryLevelTable() {
            const filterKategoriSelect = document.getElementById('filterKategori');
            const filterLevelSelect = document.getElementById('filterLevel');
            const tableBody = document.getElementById('categoryLevelTableBody');

            if (!tableBody || !listTournamentCategoryLevel) {
                return;
            }

            const selectedKategoriId = filterKategoriSelect?.value;
            const selectedLevelId = filterLevelSelect?.value;

            // Filter data
            let filteredData = listTournamentCategoryLevel;

            if (selectedKategoriId) {
                filteredData = filteredData.filter(item => item.IDKategori == selectedKategoriId);
            }

            if (selectedLevelId) {
                filteredData = filteredData.filter(item => item.IDLevel == selectedLevelId);
            }

            // Render table
            if (filteredData.length === 0) {
                tableBody.innerHTML = `
                    <tr>
                        <td colspan="2" class="text-center text-muted py-3">Belum ada data</td>
                    </tr>
                `;
                return;
            }

            let html = '';
            filteredData.forEach(item => {
                html += `
                    <tr>
                        <td>${item.NamaKategori}</td>
                        <td>${item.NamaLevel}</td>
                    </tr>
                `;
            });

            tableBody.innerHTML = html;
        }


        function addCategoryLevelEntry() {
            categoryLevelEntries.push({
                id: Date.now(),
                kategori: '',
                level: ''
            });
            renderCategoryLevelEntries();
        }



        function removeCategoryLevelEntry(entryId) {
            categoryLevelEntries = categoryLevelEntries.filter(entry => entry.id !== entryId);
            renderCategoryLevelEntries();
        }

        function renderCategoryLevelEntries() {
            const container = document.getElementById('categoryLevelContainer');

            if (categoryLevelEntries.length === 0) {
                container.innerHTML = `
                    <div class="empty-category-level-message">
                        <i class="fas fa-info-circle me-2"></i>Belum ada kategori & level yang ditambahkan
                    </div>
                `;
                return;
            }

            let html = '';
            categoryLevelEntries.forEach((entry, idx) => {
                html += `
                    <div class="category-level-entry" data-entry-id="${entry.id}">
                        <div class="col">
                            <label class="form-label">Kategori</label>
                            <select class="form-select kategori-select" data-entry-id="${entry.id}">
                                <option value="">-- Pilih Kategori --</option>
                `;

                listKategori.forEach(kat => {
                    const selected = entry.kategori === kat.IDKategori ? 'selected' : '';
                    html += `<option value="${kat.IDKategori}" ${selected}>${kat.NamaKategori}</option>`;
                });

                html += `
                            </select>
                        </div>
                        <div class="col">
                            <label class="form-label">Level</label>
                            <select class="form-select level-select" data-entry-id="${entry.id}">
                                <option value="">-- Pilih Level --</option>
                `;

                listLevel.forEach(lvl => {
                    const selected = entry.level === lvl.IDLevel ? 'selected' : '';
                    html += `<option value="${lvl.IDLevel}" ${selected}>${lvl.NamaLevel}</option>`;
                });

                html += `
                            </select>
                        </div>
                        <button type="button" class="btn btn-sm btn-danger btn-remove-entry" data-entry-id="${entry.id}">
                            <i class="fas fa-trash"></i>
                        </button>
                    </div>
                `;
            });

            container.innerHTML = html;

            // Add event listeners to dropdowns and remove buttons
            container.querySelectorAll('.kategori-select').forEach(select => {
                select.addEventListener('change', function () {
                    const entryId = parseInt(this.dataset.entryId);
                    const entry = categoryLevelEntries.find(e => e.id === entryId);
                    if (entry) entry.kategori = parseInt(this.value) || '';
                });
            });

            container.querySelectorAll('.level-select').forEach(select => {
                select.addEventListener('change', function () {
                    const entryId = parseInt(this.dataset.entryId);
                    const entry = categoryLevelEntries.find(e => e.id === entryId);
                    if (entry) entry.level = parseInt(this.value) || '';
                });
            });

            container.querySelectorAll('.btn-remove-entry').forEach(btn => {
                btn.addEventListener('click', function () {
                    const entryId = parseInt(this.dataset.entryId);
                    removeCategoryLevelEntry(entryId);
                });
            });
        }

        function loadCategoryLevelData(tournamentData) {
            // Load existing category-level data jika ada
            // Format: [{"IDKategori": 5, "IDLevel": 9}, ...]
            if (tournamentData.CategoryLevelData) {
                try {
                    const data = typeof tournamentData.CategoryLevelData === 'string'
                        ? JSON.parse(tournamentData.CategoryLevelData)
                        : tournamentData.CategoryLevelData;

                    if (Array.isArray(data)) {
                        categoryLevelEntries = data.map((item, idx) => ({
                            id: Date.now() + idx,
                            kategori: item.IDKategori || item.kategori || '',
                            level: item.IDLevel || item.level || ''
                        }));
                    }
                } catch (e) {
                    console.log("Error parsing CategoryLevelData:", e);
                    categoryLevelEntries = [];
                }
            } else {
                categoryLevelEntries = [];
            }
            renderCategoryLevelEntries();
        }

        function collectCategoryLevelData() {
            const data = categoryLevelEntries.map(entry => ({
                IDKategori: entry.kategori ? parseInt(entry.kategori) : null,
                IDLevel: entry.level ? parseInt(entry.level) : null
            })).filter(item => item.IDKategori && item.IDLevel);

            return data.length > 0 ? JSON.stringify(data) : '';
        }

        function validateCategoryLevelDuplicates() {
            // Validate: kategori boleh sama tetapi level harus berbeda
            if (categoryLevelEntries.length === 0) {
                return { valid: true, message: '' };
            }

            const seen = new Map();
            const errors = [];

            categoryLevelEntries.forEach((entry, idx) => {
                const categoriId = parseInt(entry.kategori);
                const levelId = parseInt(entry.level);

                if (!categoriId || !levelId) return; // Skip invalid entries

                const key = `${categoriId}-${levelId}`;

                if (seen.has(key)) {
                    const firstIndex = seen.get(key);
                    const categoriName = listKategori.find(k => k.IDKategori == categoriId)?.NamaKategori || 'Unknown';
                    const levelName = listLevel.find(l => l.IDLevel == levelId)?.NamaLevel || 'Unknown';
                    errors.push(`Duplikat ditemukan: Kategori "${categoriName}" dengan Level "${levelName}" muncul di entry ${firstIndex + 1} dan ${idx + 1}`);
                } else {
                    seen.set(key, idx);
                }
            });

            // Cek kategori yang sama tapi level berbeda - ini dibolehkan
            // Tapi kita perlu cek apakah kategori + level sama yang dilarang
            if (errors.length > 0) {
                return {
                    valid: false,
                    message: 'Terdapat kombinasi Kategori & Level yang sama:\n\n' + errors.join('\n\n')
                };
            }

            return { valid: true, message: '' };
        }

        async function saveGeneralInfo() {
            try {
                // Validasi kategori-level duplikat terlebih dahulu
                const validationResult = validateCategoryLevelDuplicates();
                if (!validationResult.valid) {
                    await Swal.fire({
                        title: 'Validasi Gagal',
                        text: validationResult.message,
                        icon: 'warning',
                        confirmButtonText: 'OK',
                    });
                    return; // Cancel submit
                }

                // Konfirmasi sebelum simpan
                const { isConfirmed } = await Swal.fire({
                    title: 'Konfirmasi Penyimpanan',
                    text: 'Apakah Anda yakin ingin menyimpan informasi tournament ini?',
                    icon: 'question',
                    showCancelButton: true,
                    confirmButtonText: 'Ya, Simpan',
                    cancelButtonText: 'Batal',
                });

                if (!isConfirmed) return; // User membatalkan

                const formData = new FormData(document.getElementById('form_tournament_general'));

                // Add collected category-level data (as JSON string)
                const categoryLevelData = collectCategoryLevelData();
                if (categoryLevelData) {
                    formData.append("CategoryLevelData", categoryLevelData);
                }

                formData.append("p_type", main_pk);
                formData.append("p_action", "update");
                formData.append("StatusTournament", currentStatus || "draft");

                const { result } = await fetch_helper({
                    i18nKey: "",
                    fetchFile: "",
                    formData: formData,
                });

                if (result.Status === 1) {
                    Swal.fire({
                        text: "Informasi tournament berhasil disimpan",
                        icon: "success",
                        confirmButtonText: "OK",
                    }).then(() => {
                        if (!currentTournamentId) {
                            window.location.href = sumberPath;
                        } else {
                            window.location.reload();
                        }
                    });
                } else {
                    throw new Error(result.Keterangan);
                }
            } catch (error) {
                Swal.fire({
                    text: error.message,
                    icon: "error",
                    confirmButtonText: "OK",
                });
            }
        }

        // HANDLE Participant
        let part_categoryLevelData = [];   // tampung data kategori + level
        let part_playerListData = [];      // tampung data player
        let part_addParticipantModal = null;

        async function showAddParticipantModal() {
            if (!part_addParticipantModal) {
                part_addParticipantModal = new bootstrap.Modal(
                    document.getElementById('modal_add_participant'),
                    {
                        backdrop: 'static',
                        keyboard: false
                    }
                );
            }

            // Reset form
            resetParticipantForm();

            if (part_categoryLevelData.length === 0 || part_playerListData.length === 0) {
                await reloadParticipantData();
            }

            part_addParticipantModal.show();
        }



        function resetParticipantForm() {
            document.getElementById('participantKategori').value = '';
            document.getElementById('participantLevel').innerHTML = '<option value="">-- Pilih Level --</option>';
            document.getElementById('participantPlayer1Id').value = '';
            document.getElementById('participantPlayer1Name').value = '';
            document.getElementById('participantPlayer1Email').value = '';
            document.getElementById('participantPlayer2Id').value = '';
            document.getElementById('participantPlayer2Name').value = '';
            document.getElementById('participantPlayer2Email').value = '';
            document.getElementById('participantTeamName').value = '';
            document.getElementById('player2Container').style.display = 'none';
        }

        function resetPlayerFields() {
            document.getElementById('participantPlayer1Id').value = '';
            document.getElementById('participantPlayer1Name').value = '';
            document.getElementById('participantPlayer1Email').value = '';
            document.getElementById('participantPlayer2Id').value = '';
            document.getElementById('participantPlayer2Name').value = '';
            document.getElementById('participantPlayer2Email').value = '';
            document.getElementById('participantTeamName').value = '';
        }

        async function reloadParticipantData() {

            try {
                // =========================
                // LOAD KATEGORI + LEVEL
                // =========================
                const formData = new URLSearchParams();
                formData.append("p_type", "tournament_category_level");
                formData.append("p_action", "select");
                formData.append("filters", JSON.stringify([
                    ["IDTournament", currentTournamentId, 1]
                ]));

                const { result } = await fetch_helper({
                    i18nKey: "",
                    fetchFile: "",
                    formData: formData,
                });

                if (result.Status !== 1) {
                    throw new Error("Gagal load kategori");
                }

                part_categoryLevelData = result.list_data || [];

                populateKategoriDropdown();



            } catch (error) {
                Swal.fire({
                    text: error.message,
                    icon: "error",
                    confirmButtonText: "OK",
                });
            }
        }

        function populateKategoriDropdown() {

            const kategoriSelect = document.getElementById('participantKategori');
            kategoriSelect.innerHTML = '<option value="">-- Pilih Kategori --</option>';

            const uniqueKategori = {};

            part_categoryLevelData.forEach(row => {
                if (!uniqueKategori[row.IDKategori]) {
                    uniqueKategori[row.IDKategori] = row;
                }
            });

            Object.values(uniqueKategori).forEach(cat => {
                const opt = document.createElement('option');
                opt.value = cat.IDKategori;
                opt.textContent = cat.NamaKategori;
                opt.dataset.tipe = cat.TipeKategori;
                kategoriSelect.appendChild(opt);
            });
        }

        document.getElementById('participantKategori')
            .addEventListener('change', function () {

                const selectedOpt = this.options[this.selectedIndex];
                const tipeKategori = selectedOpt.dataset.tipe;
                const kategoriId = this.value;

                document.getElementById('player2Container').style.display =
                    tipeKategori === 'double' ? 'block' : 'none';

                const levelSelect = document.getElementById('participantLevel');
                levelSelect.innerHTML = '<option value="">-- Pilih Level --</option>';

                part_categoryLevelData.forEach(level => {
                    if (level.IDKategori == kategoriId) {
                        const opt = document.createElement('option');
                        opt.value = level.IDTCL;
                        opt.textContent = level.NamaLevel;
                        levelSelect.appendChild(opt);
                    }
                });
            });

        // Inisialisasi PopupDialogSearch untuk Player 1 
        let player1Popup = null;
        let player2Popup = null;

        function initPlayerPopups() {
            const filterConfigs = [
                {
                    key: "StatusMembership",
                    label: "Status Membership",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        { display: "Active", value: "active" },
                        { display: "Inactive", value: "inactive" },
                        { display: "Expired", value: "expired" }
                    ]
                },
                {
                    key: "PaymentStatus",
                    label: "Status Payment",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        { display: "Waiting", value: "waiting" },
                        { display: "Approved", value: "approved" },
                        { display: "Rejected", value: "rejected" },
                    ]
                },
                {
                    key: "gender",
                    label: "Gender",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        { display: "Male", value: "male" },
                        { display: "Female", value: "female" },
                    ]
                },
            ];

            // === BASE CONFIG UNTUK PLAYER ===
            const basePlayerConfig = {
                columns: [
                    { columnName: 'IDPlayer', displayedName: 'ID' },
                    { columnName: 'full_name', displayedName: 'Nama Lengkap' },
                    { columnName: 'email', displayedName: 'Email' },
                    { columnName: 'MembershipNumber', displayedName: 'Membership' },
                ],
                filterConfigs: filterConfigs,
                fetchData: async (params) => {
                    const formData = new URLSearchParams();
                    formData.append('p_type', 'player');
                    formData.append('p_action', 'select_general');
                    formData.append('search', params.search);
                    formData.append('page_number', params.page);
                    formData.append('rows_per_page', params.rowsPerPage);

                    if (params.filters && Array.isArray(params.filters)) {
                        const validFilters = params.filters.filter(f =>
                            Array.isArray(f) && f.length === 3 && typeof f[0] === 'string'
                        );
                        if (validFilters.length > 0) {
                            formData.append('filters', JSON.stringify(validFilters));
                        }
                    }

                    const { result } = await fetch_helper({ formData });
                    return {
                        data: result.list_data || [],
                        totalData: result.total_rows || 0,
                        totalPage: result.total_page || 1,
                    };
                },
                additionalElements: [],
                rowsPerPage: 25,
                rowsPerPageOptions: [5, 10, 25, 50, 100],
            };

            // === PLAYER 1 ===
            if (!player1Popup) {
                let container1 = document.getElementById('player1PopupContainer');
                if (!container1) {
                    container1 = document.createElement('div');
                    container1.id = 'player1PopupContainer';
                    document.body.appendChild(container1);
                }

                // === PLAYER 1 ===
                player1Popup = new PopupDialogSearch({
                    containerId: 'player1PopupContainer',
                    targetButtonId: 'btnSearchPlayer1',
                    clearButtonId: 'btnClearPlayer1',
                    clearCallback: () => {
                        document.getElementById('participantPlayer1Id').value = '';
                        document.getElementById('participantPlayer1Name').value = '';
                        document.getElementById('participantPlayer1Email').value = '';
                        document.getElementById('participantPlayer1Gender').value = '';
                        updateTeamName();
                    },
                    title: 'Cari Player 1',
                    ...basePlayerConfig,
                    onPick: (row) => {
                        document.getElementById('participantPlayer1Id').value = row.IDPlayer;
                        document.getElementById('participantPlayer1Name').value = row.full_name;
                        document.getElementById('participantPlayer1Email').value = row.email;
                        document.getElementById('participantPlayer1Gender').value = row.gender || '-';
                        updateTeamName();
                    },
                });


                player1Popup.init();
            }

            // === PLAYER 2 ===
            if (!player2Popup) {
                let container2 = document.getElementById('player2PopupContainer');
                if (!container2) {
                    container2 = document.createElement('div');
                    container2.id = 'player2PopupContainer';
                    document.body.appendChild(container2);
                }

                // === PLAYER 2 ===
                player2Popup = new PopupDialogSearch({
                    containerId: 'player2PopupContainer',
                    targetButtonId: 'btnSearchPlayer2',
                    clearButtonId: 'btnClearPlayer2',
                    clearCallback: () => {
                        document.getElementById('participantPlayer2Id').value = '';
                        document.getElementById('participantPlayer2Name').value = '';
                        document.getElementById('participantPlayer2Email').value = '';
                        document.getElementById('participantPlayer2Gender').value = '';
                        updateTeamName();
                    },
                    title: 'Cari Player 2',
                    ...basePlayerConfig,
                    onPick: (row) => {
                        document.getElementById('participantPlayer2Id').value = row.IDPlayer;
                        document.getElementById('participantPlayer2Name').value = row.full_name;
                        document.getElementById('participantPlayer2Email').value = row.email;
                        document.getElementById('participantPlayer2Gender').value = row.gender || '-';
                        updateTeamName();
                    },
                });
                player2Popup.init();
            }
        }

        function updateTeamName() {
            const player1Name = document.getElementById('participantPlayer1Name').value;
            const player2Name = document.getElementById('participantPlayer2Name').value;
            const teamNameInput = document.getElementById('participantTeamName');

            if (player1Name && player2Name) {
                teamNameInput.value = player1Name + ' & ' + player2Name;
            } else if (player1Name) {
                teamNameInput.value = player1Name;
            } else {
                teamNameInput.value = '';
            }
        }


        document.getElementById('btnReloadParticipantData')
            .addEventListener('click', async function () {

                part_categoryLevelData = [];
                part_playerListData = [];

                await reloadParticipantData();

                Swal.fire({
                    text: "Data berhasil di-refresh",
                    icon: "success",
                    timer: 1200,
                    showConfirmButton: false
                });
            });




        // === Save & Close ===
        document.getElementById('btnSaveAndClose')?.addEventListener('click', async function () {
            const success = await saveParticipant();
            if (success) {
                // Tutup modal setelah sukses
                if (part_addParticipantModal) {
                    part_addParticipantModal.hide();
                }
                loadParticipantsTable();
            }
        });

        // === Save & Continue ===
        document.getElementById('btnSaveAndContinue')?.addEventListener('click', async function () {
            const success = await saveParticipant();
            if (success) {
                // Reset player fields saja, tanpa reset kategori & level
                resetPlayerFields();
                await loadParticipantsTable();
            }
        });

        // Fungsi save participant yang dipisah
        async function saveParticipant() {
            const kategoriId = document.getElementById('participantKategori').value;
            const levelId = document.getElementById('participantLevel').value;
            const player1Id = document.getElementById('participantPlayer1Id').value;
            const player2Id = document.getElementById('participantPlayer2Id').value;
            const teamName = document.getElementById('participantTeamName').value.trim();
            const tipeKategori = document.querySelector('#participantKategori option:checked')?.dataset.tipe || 'single';

            try {
                if (!kategoriId || !levelId || !player1Id) {
                    throw new Error("Kategori, Level, dan Player 1 harus dipilih");
                }

                if (tipeKategori === 'double' && !player2Id) {
                    throw new Error("Untuk kategori double, kedua pemain harus dipilih");
                }

                if (tipeKategori === 'double' && player1Id === player2Id) {
                    throw new Error("Player 1 dan Player 2 tidak boleh sama");
                }

                if (!teamName) {
                    throw new Error("Nama tim tidak boleh kosong");
                }

                const formData = new URLSearchParams();
                formData.append("p_type", "tournament");
                formData.append("p_action", "add_participant");
                formData.append("IDTournament", currentTournamentId);
                formData.append("IDTCL", levelId);
                formData.append("TeamName", teamName);
                formData.append("IDTeam", "");
                formData.append("IDPlayer1", player1Id);
                if (tipeKategori === 'double') {
                    formData.append("IDPlayer2", player2Id);
                }

                const { result } = await fetch_helper({
                    i18nKey: "",
                    fetchFile: "",
                    formData: formData,
                });

                if (result.Status === 1) {
                    Swal.fire({
                        text: "Peserta berhasil ditambahkan",
                        icon: "success",
                        timer: 1500,
                        showConfirmButton: false,
                    });
                    return true;
                } else {
                    throw new Error(result.Keterangan);
                }
            } catch (error) {
                Swal.fire({
                    text: error.message,
                    icon: "error",
                    confirmButtonText: "OK",
                });
                return false;
            }
        }

        function showAddMatchModal() {
            // TODO: Load match data and show modal
            const modal = new bootstrap.Modal(document.getElementById('modal_add_match'));
            modal.show();
        }

        async function loadParticipantsTable() {
            // === Konfigurasi Display Columns ===
            const displayColumns = [
                { columnName: "IDRegistration", displayedName: "ID", isShown: false, dataType: "numeric" },
                { columnName: "TeamName", displayedName: "Nama Team", dataType: "text" },
                { columnName: "Players", displayedName: "Daftar Pemain", dataType: "text" },
                { columnName: "NamaKategori", displayedName: "Kategori", dataType: "text" },
                { columnName: "NamaLevel", displayedName: "Level", dataType: "text" },
                {
                    columnName: "Status",
                    displayedName: "Status",
                    dataType: "enum",
                    enumFormat: (val) => {
                        const badgeMap = {
                            'active': '<span class="badge text-bg-success">Active</span>',
                            'cancelled': '<span class="badge text-bg-danger">Cancelled</span>',
                            'disqualified': '<span class="badge text-bg-warning">Disqualified</span>',
                            'waiting': '<span class="badge text-bg-info">Waiting</span>',
                        };
                        return badgeMap[val] || `<span class="badge text-bg-secondary">${val || '-'}</span>`;
                    }
                },
                { columnName: "LastUpdateBy", dataType: "text" },
                { columnName: "LastUpdateAt", dataType: "datetime", dateFormat: "dd-MM-yyyy HH:mm:ss" },
            ];

            // === Konfigurasi Filter ===
            const filterConfigs = [
                {
                    key: "IDKategori",
                    label: "Filter Kategori",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        ...listKategori.map(kat => ({ display: kat.NamaKategori, value: kat.IDKategori }))
                    ]
                },
                {
                    key: "IDLevel",
                    label: "Filter Level",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        ...listLevel.map(lvl => ({ display: lvl.NamaLevel, value: lvl.IDLevel }))
                    ]
                },
                {
                    key: "Status",
                    label: "Filter Status",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        { display: "Active", value: "active" },
                        { display: "Cancelled", value: "cancelled" },
                        { display: "Disqualified", value: "disqualified" },
                        { display: "Waiting", value: "waiting" },
                    ]
                }
            ];

            // === Action Buttons ===
            const actionButtons = [
                {
                    key: 'detail_registration_callback',
                    buttonType: 'Custom',
                    actionType: 'Callback',
                    label: 'Detail Registration',
                    iconClass: '<i class="fa fa-info-circle"></i>',
                    callbackFunction: async (row) => {
                        await openRegistrationDetailModal(row.IDRegistration);
                    }
                },
                {
                    key: 'delete',
                    buttonType: 'Delete',
                    actionType: 'Callback',
                    callbackFunction: async (row) => {
                        const result = await Swal.fire({
                            text: `Yakin ingin menghapus data ${row.TeamName || row.Team}?`,
                            icon: 'warning',
                            showCancelButton: true,
                            confirmButtonText: 'Ya, Hapus',
                            cancelButtonText: 'Batal',
                        });

                        if (result.isConfirmed) {
                            const formData = new URLSearchParams();
                            formData.append("p_type", "tournament_registration");
                            formData.append("p_action", "delete");
                            formData.append("IDRegistration", row.IDRegistration);

                            const { result: deleteResult } = await fetch_helper({
                                formData: formData,
                            });

                            if (deleteResult.listErrorMessage && deleteResult.listErrorMessage.length > 0) {
                                await q_generateListErrorMessage(deleteResult, [
                                    { display: "Nama", value: "TeamName" },
                                    { display: "Keterangan", value: "Keterangan" },
                                ]);
                            } else {
                                Swal.fire({
                                    text: deleteResult.Keterangan || "Peserta berhasil dihapus",
                                    icon: deleteResult.Status === 1 ? "success" : "error",
                                    confirmButtonText: "OK",
                                });
                            }

                            if (deleteResult.Status === 1) {
                                dtInstance.loadData();
                            }
                        }
                    }
                }
            ];

            // === Bulk Actions ===
            const bulkActions = [
                {
                    key: 'delete_multiple',
                    label: 'Hapus Terpilih',
                    icon: 'fa-trash',
                    confirm: 'Yakin ingin menghapus data terpilih?',
                    callback: async (selectedData, selectedIds) => {
                        const formData = new URLSearchParams();
                        formData.append("p_type", "tournament_registration");
                        formData.append("p_action", "delete");
                        formData.append("IDRegistration", selectedIds.join(','));

                        const { result: deleteResult } = await fetch_helper({ formData });

                        if (deleteResult.listErrorMessage && deleteResult.listErrorMessage.length > 0) {
                            await q_generateListErrorMessage(deleteResult, [
                                { display: "Nama", value: "TeamName" },
                                { display: "Keterangan", value: "Keterangan" },
                            ]);
                        } else {
                            Swal.fire({
                                text: deleteResult.Keterangan || "Peserta berhasil dihapus",
                                icon: deleteResult.Status === 1 ? "success" : "error",
                                confirmButtonText: "OK",
                            });
                        }

                        if (deleteResult.Status === 1) {
                            dtInstance.loadData();
                        }
                    }
                }
            ];

            // === Inisialisasi DataTable ===
            const formData = new URLSearchParams();
            formData.append("p_type", "tournament_registration");
            formData.append("p_action", "select");

            const dtInstance = new DataTable({
                containerId: 'participantsTableContainer',
                formData: formData,
                displayColumns: displayColumns,
                filterConfigs: filterConfigs,
                actionButtons: actionButtons,
                bulkActions: bulkActions,
                orderColumnList: [
                    { display: 'Nama Team', columnName: 'TeamName' },
                    { display: 'Kategori', columnName: 'NamaKategori' },
                    { display: 'Level', columnName: 'NamaLevel' },
                    { display: 'Status', columnName: 'Status' },
                ],
                rowSelection: {
                    enabled: true,
                    rowKey: 'IDRegistration',
                },
                fetchHelper: fetch_helper,
                defaultRowsPerPage: 25,
                rowsPerPageOptions: [10, 25, 50, 100, 250, 500],
                exportOptions: {
                    copy: true,
                    csv: true,
                    excel: true,
                    pdf: false,
                },
                allowFilter: true,
                allowOrder: true,
                allowPaging: true,
                allowExport: true,
                // Additional filter parameter (IDTournament)
                additionalFilterParameter: [
                    ["IDTournament", currentTournamentId, 1]
                ]
            });

            // === Render dan Load Data ===
            dtInstance.render();

            // Simpan instance ke variabel global jika perlu
            window.participantsTableInstance = dtInstance;
        }

        async function loadParticipantsTable_old() {
            const type = "tournament_registration";
            const IDName = "IDRegistration";

            const formData = new URLSearchParams();
            formData.append("p_type", type);
            formData.append("p_action", "select");




            const allowAction = true;

            const filterKolom = [
                ["IDKategori", "Filter Kategori", "options", [
                    { display: "Semua", value: "" },
                    ...listKategori.map(kat => ({ display: kat.NamaKategori, value: kat.IDKategori }))
                ]],
                ["IDLevel", "Filter Level", "options", [
                    { display: "Semua", value: "" },
                    ...listLevel.map(lvl => ({ display: lvl.NamaLevel, value: lvl.IDLevel }))
                ]],
                ["Status", "Filter Status", "options", [
                    { display: "Semua", value: "" },
                    { display: "Active", value: "active" },
                    { display: "Cancelled", value: "cancelled" },
                    { display: "Disqualified", value: "disqualified" },
                    { display: "Waiting", value: "waiting" },
                ]],
            ];


            const { tableId } = generateDatatableHTML({
                targetSelector: "#participantsTableContainer",
                allowAction: allowAction,
                filters: filterKolom
            });

            const delete_action_callback = async (ids) => {
                console.log("Delete callback:", ids);

                const formData = new URLSearchParams();
                formData.append("p_type", type);
                formData.append("p_action", "delete");
                formData.append(IDName, ids);

                const { result } = await fetch_helper({
                    i18nKey: "", // ganti jika key i18next-nya berbeda
                    fetchFile: "",
                    formData: formData,
                });

                if (result) {
                    if (result.listErrorMessage && result.listErrorMessage.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "Nama", value: "NamaTournament" },
                            { display: "Keterangan", value: "Keterangan" },
                        ]);
                    } else {
                        Swal.fire({
                            text: result.Keterangan || "Peserta berhasil dihapus",
                            icon: result.Status === 1 ? "success" : "error",
                            confirmButtonText: "OK",
                        });
                    }
                }



                // ⚡ return result ke handler agar bisa dicek Status
                return result;
            };

            const dt = await initDatatable({
                tableId,
                formData,
                displayColumns: [
                    { columnName: IDName, displayedName: "ID", IsShown: false },
                    { columnName: "TeamName", displayedName: "Nama Team" },

                    { columnName: "Players", displayedName: "Daftar Pemain" },
                    {
                        columnName: "NamaKategori",
                        displayedName: "Kategori"
                    },
                    {
                        columnName: "NamaLevel",
                        displayedName: "Level"
                    },
                    {
                        columnName: "Status",
                        displayedName: "Status",
                        dataType: "enum",
                        displayedValue: (value, row) => {

                            const badgeMap = {
                                active: ["badge-light-success", "Active"],
                                cancelled: ["badge-light-danger", "Cancelled"],
                                disqualified: ["badge-light-warning", "Disqualified"],
                                waiting: ["badge-light-info", "Waiting"],
                            };

                            const data = badgeMap[value];

                            if (!data)
                                return `<span class="badge badge-light-dark">Unknown</span>`;

                            return `<span class="badge ${data[0]} fw-bold">${data[1]}</span>`;
                        }
                    },
                    { columnName: "LastUpdateBy" },
                    {
                        columnName: "LastUpdateAt",
                        dataType: "datetime",
                        displayedValue: {
                            format: "dd-MM-yyyy HH:mm:ss",
                        },
                    },
                ],
                allowAction: allowAction,
                delete_action_callback: delete_action_callback,
                // custom action buttons
                custom_action_callback: [
                    {
                        name: 'detail_registration_callback',
                        display: 'Detail Registration'
                    }
                ],
                filterKolom: filterKolom,
                additionalFilterParameter: [
                    ["IDTournament", currentTournamentId, 1]
                ]
            });

            // attach handler for detail button (in case not using inline callback)
            $(`#${tableId}`).on('click', '.custom-action', async function (e) {
                e.preventDefault();
                const id = $(this).data('id');
                const action = $(this).data('action');
                if (action === 'detail_registration_callback') {
                    await openRegistrationDetailModal(id);
                }
            });
        }

        // simple escape helper
        function escapeHtml(str) {
            if (str === null || str === undefined) return '';
            return String(str).replace(/[&<>"]+/g, function (s) {
                return ({ '&': '&amp;', '<': '&lt;', '>': '&gt;', '"': '&quot;' })[s] || s;
            });
        }

        // Fetch registration detail from backend and render modal
        async function getRegistrationDetailFromServer(IDRegistration) {
            const formData = new URLSearchParams();
            formData.append('p_type', 'tournament');
            formData.append('p_action', 'getRegistrationDetail');
            formData.append('IDRegistration', IDRegistration);

            const { result } = await fetch_helper({ fetchFile: '', formData });
            return result;
        }

        let registrationModalInstance = null;

        async function openRegistrationDetailModal(IDRegistration) {
            const modalEl = document.getElementById('modal_registration_detail');

            // Tutup modal yang ada jika terbuka
            if (registrationModalInstance) {
                registrationModalInstance.hide();
                // Tunggu sebentar agar modal benar-benar tertutup
                await new Promise(resolve => setTimeout(resolve, 300));
            }

            // Buat instance baru
            registrationModalInstance = new bootstrap.Modal(modalEl);

            // Reset backdrop jika ada masalah
            document.querySelectorAll('.modal-backdrop').forEach(el => el.remove());
            document.body.classList.remove('modal-open');
            document.body.style.paddingRight = '';

            document.getElementById('registrationDetailContainer').innerHTML = '<div class="text-center py-5">Loading...</div>';
            registrationModalInstance.show();

            const res = await getRegistrationDetailFromServer(IDRegistration);
            if (!res || res.Status !== 1) {
                document.getElementById('registrationDetailContainer').innerHTML = `<div class="alert alert-danger">${res?.Keterangan || 'Failed to load'}</div>`;
                return;
            }

            const data = res.data;
            const reg = data.registration;
            const members = data.team_members || [];

            // build HTML
            let html = '';

            // Section: Tournament Data
            html += `<h5>Data Tournament</h5>`;
            html += `<div class="mb-3"><strong>${escapeHtml(reg.NamaTournament || '')}</strong></div>`;
            html += `<div class="row mb-4">
                                <div class="col-md-4"><label>Registration Fee</label><div>${reg.TournamentRegistrationFee || reg.CategoryRegistrationFee || '-'}</div></div>
                                <div class="col-md-4"><label>Kategori</label><div>${escapeHtml(reg.NamaKategori || '')}</div></div>
                                <div class="col-md-4"><label>Level</label><div>${escapeHtml(reg.NamaLevel || '')}</div></div>
                        </div>`;

            // Partner 1 & 2 (assume first two team members as partner1 and partner2)
            const p1 = members[0] || null;
            const p2 = members[1] || null;

            function memberSection(title, member) {
                if (!member) return `<div class="card mb-3"><div class="card-body"><strong>${title}</strong><div class="text-muted">No data</div></div></div>`;
                return `<div class="card mb-3"><div class="card-body">
                                        <h6>${title}</h6>
                                        <div class="row">
                                            <div class="col-md-4"><label>Email</label><div>${escapeHtml(member.email || '')}</div></div>
                                            <div class="col-md-4"><label>Full Name</label><div>${escapeHtml(member.full_name || '')}</div></div>
                                            <div class="col-md-4"><label>Phone</label><div>${escapeHtml(member.phone || '')}</div></div>
                                        </div>
                                        <div class="row mt-2">
                                            <div class="col-md-4"><label>Membership Number</label><div>${escapeHtml(member.MembershipNumber || '')}</div></div>
                                            <div class="col-md-4"><label>Membership Status</label><div>${escapeHtml(member.MembershipStatus || '')}</div></div>
                                            <div class="col-md-4"><label>Membership End</label><div>${escapeHtml(member.MembershipEndDate || '')}</div></div>
                                        </div>
                                </div></div>`;
            }

            html += `<h5>Partner Pertama</h5>` + memberSection('Partner 1', p1);
            html += `<h5>Partner Kedua</h5>` + memberSection('Partner 2', p2);

            html += `<h5>Kategori & Level</h5>`;
            const currentCategory = reg.NamaKategori ? escapeHtml(reg.NamaKategori) : '<span class="text-muted">Belum dipilih</span>';
            const currentLevel = reg.NamaLevel ? escapeHtml(reg.NamaLevel) : '<span class="text-muted">Belum dipilih</span>';
            html += `<div class="card mb-3"><div class="card-body">
                        <div class="row mb-3">
                            <div class="col-md-4"><label>Current Kategori</label><div>${currentCategory}</div></div>
                            <div class="col-md-4"><label>Current Level</label><div>${currentLevel}</div></div>
                        </div>
                        <div class="row align-items-end">
                            <div class="col-md-5">
                                <label class="form-label">Pilih Kategori & Level</label>
                                <select id="regCategoryLevelSelect" class="form-select form-select-sm">
                                    <option value="">-- Pilih Kategori & Level --</option>
                                </select>
                            </div>
                            <div class="col-md-3">
                                <button id="btnSetRegistrationTCL" class="btn btn-sm btn-primary">Set Kategori dan Level Tournament</button>
                            </div>
                        </div>
                        <div id="registrationTCLInfo" class="mt-2 text-muted"></div>
                    </div></div>`;

            // Payment section
            html += `<h5>Payment</h5>`;
            const proof = reg.PaymentProof ? `<img src="${reg.PaymentProof}" class="img-fluid viewer-image" style="max-width:200px;cursor:pointer" />` : '<div class="text-muted">No proof</div>';
            // badge color
            const payStatus = reg.PaymentStatus || 'pending';
            const payBadgeClass = payStatus === 'paid' ? 'bg-primary text-light' : (payStatus === 'rejected' ? 'bg-danger text-light' : 'bg-warning text-dark');
            html += `<div class="card mb-3"><div class="card-body">
                                <div class="row">
                                    <div class="col-md-4"><label>Payment Proof</label><div>${proof}</div></div>
                                    <div class="col-md-4"><label>Payment Status</label><div><span id="paymentStatusBadge" class="badge ${payBadgeClass}">${escapeHtml(payStatus)}</span></div></div>
                                    <div class="col-md-4"><label>Action</label>
                                        <div class="d-flex gap-2">
                                            <select id="regPaymentStatusSelect" class="form-select form-select-sm">
                                                <option value="pending">pending</option>
                                                <option value="paid">paid</option>
                                                <option value="rejected">rejected</option>
                                            </select>
                                            <button id="btnSetPaymentApproval" class="btn btn-sm btn-primary">Set Approval Payment</button>
                                        </div>
                                        <div id="paymentRemarksContainer" class="mt-2" style="display:none;">
                                            <label class="form-label">PaymentRemarks</label>
                                            <textarea id="paymentRemarks" class="form-control" placeholder="Alasan reject"></textarea>
                                        </div>
                                    </div>
                                </div>
                        </div></div>`;

            // Status participant section
            const status = reg.Status || 'active';
            const statusClass = status === 'active' ? 'text-primary' : (status === 'waiting' ? 'text-warning' : 'text-danger');
            const statusRemarks = reg.StatusRemarks || '';
            html += `<h5>Status Participant</h5>`;
            html += `<div class="card mb-3"><div class="card-body">
                                <div class="mb-2"><strong id="regStatusBadge" class="${statusClass}" style="font-size:1.2rem">${escapeHtml(status)}</strong></div>
                                <div id="statusRemarksDisplay" class="mb-3">${(status === 'active' || status === 'waiting') ? '<em>-</em>' : `<div><strong>StatusRemarks:</strong> ${escapeHtml(statusRemarks)}</div>`}</div>
                                <div class="d-flex gap-2 align-items-center">
                                    <select id="regStatusSelect" class="form-select form-select-sm" style="width:200px;">
                                        <option value="active">active</option>
                                        <option value="cancelled">cancelled</option>
                                        <option value="disqualified">disqualified</option>
                                        <option value="waiting">waiting</option>
                                    </select>
                                    <button id="btnSetRegistrationStatus" class="btn btn-sm btn-primary">Set Status Participant</button>
                                </div>
                                <div id="statusRemarksContainer" class="mt-2" style="display:none;">
                                    <label class="form-label">Alasan</label>
                                    <textarea id="statusRemarks" class="form-control" placeholder="Alasan perubahan status"></textarea>
                                </div>
                        </div></div>`;



            document.getElementById('registrationDetailContainer').innerHTML = html;

            // init viewer for image zoom
            setTimeout(() => {
                try { new Viewer(document.querySelector('#modal_registration_detail'), { navbar: false, toolbar: true, title: false }); } catch (e) { }
            }, 100);

            // wire payment actions
            // set initial values and handlers
            document.getElementById('regPaymentStatusSelect').value = reg.PaymentStatus || 'pending';
            // show remarks if rejected or existing remarks
            if ((reg.PaymentStatus && reg.PaymentStatus === 'rejected') || (reg.PaymentRemarks && reg.PaymentRemarks.trim() !== '')) {
                document.getElementById('paymentRemarksContainer').style.display = '';
            }
            document.getElementById('paymentRemarks').value = reg.PaymentRemarks || '';
            // update badge when select changes
            document.getElementById('regPaymentStatusSelect').addEventListener('change', function () {
                const v = this.value;
                const badge = document.getElementById('paymentStatusBadge');
                if (badge) {
                    badge.textContent = v;
                    badge.className = 'badge ' + (v === 'paid' ? 'bg-primary text-light' : 'bg-warning text-dark');
                }
                if (v === 'rejected') document.getElementById('paymentRemarksContainer').style.display = '';
                else document.getElementById('paymentRemarksContainer').style.display = 'none';
            });

            document.getElementById('btnSetPaymentApproval').addEventListener('click', async function () {
                const status = document.getElementById('regPaymentStatusSelect').value;
                const remarks = document.getElementById('paymentRemarks').value || '';

                // Tampilkan konfirmasi terlebih dahulu
                const confirmResult = await Swal.fire({
                    title: 'Konfirmasi Approval Payment',
                    text: `Anda akan mengubah status payment menjadi "${status}"${remarks ? ' dengan remarks: ' + remarks : ''}`,
                    icon: 'question',
                    showCancelButton: true,
                    confirmButtonColor: '#3085d6',
                    cancelButtonColor: '#d33',
                    confirmButtonText: 'Ya, Lanjutkan!',
                    cancelButtonText: 'Batal'
                });

                if (!confirmResult.isConfirmed) {
                    return; // Batalkan jika user klik batal
                }

                const form = new URLSearchParams();
                form.append('p_type', 'tournament');
                form.append('p_action', 'setRegistrationPaymentApproval');
                form.append('IDRegistration', IDRegistration);
                form.append('PaymentStatus', status);
                form.append('PaymentRemarks', remarks);

                const { result } = await fetch_helper({ fetchFile: '', formData: form });

                // Debug: console log result
                console.log('Debug setRegistrationPaymentApproval result:', result);

                // Log email debug info jika ada
                if (result?.debug) {
                    console.log('Email Debug Info:', result.debug);
                    if (result.debug.failed_emails) {
                        console.warn('Failed emails:', result.debug.failed_emails);
                    }
                }

                if (result && result.Status === 1) {
                    // reload detail and table
                    await openRegistrationDetailModal(IDRegistration);
                    await loadParticipantsTable();

                    // Tampilkan success message dengan info email jika ada
                    let message = 'Status payment berhasil diupdate';
                    if (result.email_warning) {
                        message += '\n\n' + result.email_warning;
                    }

                    Swal.fire({
                        icon: 'success',
                        title: 'Berhasil!',
                        text: message,
                        timer: 3000,
                        showConfirmButton: true
                    });
                } else {
                    Swal.fire('Error', result?.Keterangan || 'Failed', 'error');
                }
            });

            // wire status actions
            document.getElementById('regStatusSelect').value = status;
            // show statusRemarks container if initial status is cancelled/disqualified and fill
            if (status === 'cancelled' || status === 'disqualified') {
                document.getElementById('statusRemarksContainer').style.display = '';
                document.getElementById('statusRemarks').value = statusRemarks || '';
            } else {
                document.getElementById('statusRemarksContainer').style.display = 'none';
            }

            document.getElementById('regStatusSelect').addEventListener('change', function () {
                const v = this.value;
                const badgeEl = document.getElementById('regStatusBadge');
                if (badgeEl) {
                    const cls = v === 'active' ? 'text-primary' : (v === 'waiting' ? 'text-warning' : 'text-danger');
                    badgeEl.className = cls;
                    badgeEl.textContent = v;
                }
                // update display of statusRemarksDisplay
                const display = document.getElementById('statusRemarksDisplay');
                if (v === 'active' || v === 'waiting') {
                    display.innerHTML = '<em>-</em>';
                } else {
                    display.innerHTML = `<div><strong>StatusRemarks:</strong> </div>`;
                }

                if (v === 'cancelled' || v === 'disqualified') document.getElementById('statusRemarksContainer').style.display = '';
                else document.getElementById('statusRemarksContainer').style.display = 'none';
            });

            document.getElementById('btnSetRegistrationStatus').addEventListener('click', async function () {
                const statusVal = document.getElementById('regStatusSelect').value;
                const remarks = document.getElementById('statusRemarks').value || '';

                // Tampilkan konfirmasi terlebih dahulu
                const statusLabels = {
                    'active': 'Aktif',
                    'cancelled': 'Dibatalkan',
                    'disqualified': 'Diskualifikasi',
                    'waiting': 'Menunggu'
                };

                const statusText = statusLabels[statusVal] || statusVal;
                const confirmMessage = `Anda akan mengubah status participant menjadi "${statusText}"${remarks ? ' dengan alasan: ' + remarks : ''}`;

                const confirmResult = await Swal.fire({
                    title: 'Konfirmasi Ubah Status Participant',
                    text: confirmMessage,
                    icon: 'question',
                    showCancelButton: true,
                    confirmButtonColor: '#3085d6',
                    cancelButtonColor: '#d33',
                    confirmButtonText: 'Ya, Ubah Status!',
                    cancelButtonText: 'Batal'
                });

                if (!confirmResult.isConfirmed) {
                    return; // Batalkan jika user klik batal
                }

                // Tampilkan loading
                this.disabled = true;
                this.textContent = 'Processing...';

                try {
                    const form = new URLSearchParams();
                    form.append('p_type', 'tournament');
                    form.append('p_action', 'setRegistartionTournamentStatus');
                    form.append('IDRegistration', IDRegistration);
                    form.append('Status', statusVal);
                    form.append('StatusRemarks', remarks);

                    const { result } = await fetch_helper({ fetchFile: '', formData: form });

                    // Debug: console log result
                    console.log('Debug setRegistartionTournamentStatus result:', result);

                    // Log email debug info jika ada
                    if (result?.debug) {
                        console.log('Email Debug Info:', result.debug);
                        if (result.debug.failed_emails) {
                            console.warn('Failed emails:', result.debug.failed_emails);
                        }
                        if (result.debug.invalid_recipients) {
                            console.warn('Invalid recipients:', result.debug.invalid_recipients);
                        }
                    }

                    if (result && result.Status === 1) {
                        // reload detail and table
                        await openRegistrationDetailModal(IDRegistration);
                        await loadParticipantsTable();

                        // Tampilkan success message dengan info email jika ada
                        let message = `Status participant berhasil diubah menjadi "${statusText}"`;
                        if (result.email_warning) {
                            message += '\n\n⚠️ ' + result.email_warning;
                        }

                        Swal.fire({
                            icon: 'success',
                            title: 'Berhasil!',
                            text: message,
                            timer: 3000,
                            showConfirmButton: true
                        });
                    } else {
                        Swal.fire('Error', result?.Keterangan || 'Failed to update status', 'error');
                    }
                } catch (error) {
                    console.error('Error in status update:', error);
                    Swal.fire('Error', 'Terjadi kesalahan: ' + error.message, 'error');
                } finally {
                    this.disabled = false;
                    this.textContent = 'Set Status Participant';
                }
            });

            const categoryLevelSelect = document.getElementById('regCategoryLevelSelect');
            const registrationTCLInfo = document.getElementById('registrationTCLInfo');
            if (categoryLevelSelect) {
                categoryLevelSelect.innerHTML = '<option value="">-- Pilih Kategori & Level --</option>';
                (listTournamentCategoryLevel || []).forEach(tcl => {
                    const opt = document.createElement('option');
                    opt.value = tcl.IDTCL;
                    opt.textContent = `${tcl.NamaKategori || 'Unknown'} - ${tcl.NamaLevel || 'Unknown'}`;
                    if (String(tcl.IDTCL) === String(reg.IDTCL || '')) {
                        opt.selected = true;
                    }
                    categoryLevelSelect.appendChild(opt);
                });

                categoryLevelSelect.addEventListener('change', function () {
                    if (registrationTCLInfo) {
                        registrationTCLInfo.textContent = this.value
                            ? 'Klik tombol untuk menyimpan perubahan kategori/level.'
                            : 'Pilih kategori/level terlebih dahulu.';
                    }
                });
            }

            document.getElementById('btnSetRegistrationTCL')?.addEventListener('click', async function () {
                const selectedTCL = document.getElementById('regCategoryLevelSelect').value;
                if (!selectedTCL) {
                    Swal.fire({ icon: 'warning', text: 'Pilih Kategori & Level terlebih dahulu' });
                    return;
                }

                const confirmResult = await Swal.fire({
                    title: 'Konfirmasi Set Kategori / Level',
                    text: 'Apakah Anda yakin ingin mengubah kategori/level registrasi ini?',
                    icon: 'question',
                    showCancelButton: true,
                    confirmButtonText: 'Ya, Set',
                    cancelButtonText: 'Batal'
                });

                if (!confirmResult.isConfirmed) {
                    return;
                }

                try {
                    const form = new URLSearchParams();
                    form.append('p_type', 'tournament');
                    form.append('p_action', 'setRegistrationTCL');
                    form.append('IDRegistration', IDRegistration);
                    form.append('IDTCL', selectedTCL);

                    const { result } = await fetch_helper({ fetchFile: '', formData: form });
                    if (result && result.Status === 1) {
                        await openRegistrationDetailModal(IDRegistration);
                        await loadParticipantsTable();
                        Swal.fire({ icon: 'success', text: result.Keterangan || 'Kategori/level berhasil diassign' });
                    } else {
                        throw new Error(result?.Keterangan || 'Gagal assign kategori/level');
                    }
                } catch (error) {
                    Swal.fire({ icon: 'error', text: error.message || error });
                }
            });
        }


        async function loadGroupsTable() {
            // === Konfigurasi Display Columns ===
            const displayColumns = [
                { columnName: "IDGroup", displayedName: "ID", isShown: false, dataType: "numeric" },
                { columnName: "GroupName", displayedName: "Nama Group", dataType: "text" },
                { columnName: "NamaKategori", displayedName: "Kategori", dataType: "text" },
                { columnName: "NamaLevel", displayedName: "Level", dataType: "text" },
                {
                    columnName: "TotalTeam",
                    displayedName: "Total Team",
                    dataType: "numeric",
                    decorationText: { suffix: " team" }
                },
                { columnName: "LastUpdateBy", dataType: "text" },
                { columnName: "LastUpdateAt", dataType: "datetime", dateFormat: "dd-MM-yyyy HH:mm:ss" },
            ];

            // === Konfigurasi Filter ===
            const filterConfigs = [
                {
                    key: "IDKategori",
                    label: "Filter Kategori",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        ...listKategori.map(kat => ({ display: kat.NamaKategori, value: kat.IDKategori }))
                    ]
                },
                {
                    key: "IDLevel",
                    label: "Filter Level",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        ...listLevel.map(lvl => ({ display: lvl.NamaLevel, value: lvl.IDLevel }))
                    ]
                }
            ];

            // === Action Buttons ===
            const actionButtons = [
                {
                    key: 'delete',
                    buttonType: 'Delete',
                    actionType: 'Callback',
                    callbackFunction: async (row) => {
                        const result = await Swal.fire({
                            text: `Yakin ingin menghapus group ${row.GroupName}?`,
                            icon: 'warning',
                            showCancelButton: true,
                            confirmButtonText: 'Ya, Hapus',
                            cancelButtonText: 'Batal',
                        });

                        if (result.isConfirmed) {
                            const formData = new URLSearchParams();
                            formData.append("p_type", "tournament_group");
                            formData.append("p_action", "delete");
                            formData.append("IDGroup", row.IDGroup);

                            const { result: deleteResult } = await fetch_helper({
                                formData: formData,
                            });

                            if (deleteResult.listErrorMessage && deleteResult.listErrorMessage.length > 0) {
                                await q_generateListErrorMessage(deleteResult, [
                                    { display: "Nama Group", value: "GroupName" },
                                    { display: "Keterangan", value: "Keterangan" },
                                ]);
                            } else {
                                Swal.fire({
                                    text: deleteResult.Keterangan || "Group berhasil dihapus",
                                    icon: deleteResult.Status === 1 ? "success" : "error",
                                    confirmButtonText: "OK",
                                });
                            }

                            if (deleteResult.Status === 1) {
                                dtInstance.loadData();
                            }
                        }
                    }
                }
            ];

            // === Bulk Actions ===
            const bulkActions = [
                {
                    key: 'delete_multiple',
                    label: 'Hapus Terpilih',
                    icon: 'fa-trash',
                    confirm: 'Yakin ingin menghapus data terpilih?',
                    callback: async (selectedData, selectedIds) => {
                        const formData = new URLSearchParams();
                        formData.append("p_type", "tournament_group");
                        formData.append("p_action", "delete");
                        formData.append("IDGroup", selectedIds.join(','));

                        const { result: deleteResult } = await fetch_helper({ formData });

                        if (deleteResult.listErrorMessage && deleteResult.listErrorMessage.length > 0) {
                            await q_generateListErrorMessage(deleteResult, [
                                { display: "Nama Group", value: "GroupName" },
                                { display: "Keterangan", value: "Keterangan" },
                            ]);
                        } else {
                            Swal.fire({
                                text: deleteResult.Keterangan || "Group berhasil dihapus",
                                icon: deleteResult.Status === 1 ? "success" : "error",
                                confirmButtonText: "OK",
                            });
                        }

                        if (deleteResult.Status === 1) {
                            dtInstance.loadData();
                        }
                    }
                }
            ];

            // === Inisialisasi DataTable ===
            const formData = new URLSearchParams();
            formData.append("p_type", "tournament_group");
            formData.append("p_action", "select");

            const dtInstance = new DataTable({
                containerId: 'groupsTableContainer',
                formData: formData,
                displayColumns: displayColumns,
                filterConfigs: filterConfigs,
                actionButtons: actionButtons,
                bulkActions: bulkActions,
                orderColumnList: [
                    { display: 'Nama Group', columnName: 'GroupName' },
                    { display: 'Kategori', columnName: 'NamaKategori' },
                    { display: 'Level', columnName: 'NamaLevel' },
                    { display: 'Total Team', columnName: 'TotalTeam' },
                ],
                rowSelection: {
                    enabled: true,
                    rowKey: 'IDGroup',
                },
                fetchHelper: fetch_helper,
                defaultRowsPerPage: 25,
                rowsPerPageOptions: [10, 25, 50, 100, 250, 500],
                exportOptions: {
                    copy: true,
                    csv: true,
                    excel: true,
                    pdf: false,
                },
                allowFilter: true,
                allowOrder: true,
                allowPaging: true,
                allowExport: true,
                additionalFilterParameter: [
                    ["IDTournament", currentTournamentId, 1]
                ]
            });

            // === Render dan Load Data ===
            dtInstance.render();

            // Simpan instance ke variabel global jika perlu
            window.groupsTableInstance = dtInstance;
        }

        async function loadGroupsTable_old() {
            const type = "tournament_group";
            const IDName = "IDGroup";

            const formData = new URLSearchParams();
            formData.append("p_type", type);
            formData.append("p_action", "select");



            const allowAction = true;

            const filterKolom = [
                ["IDKategori", "Filter Kategori", "options", [
                    { display: "Semua", value: "" },
                    ...listKategori.map(kat => ({ display: kat.NamaKategori, value: kat.IDKategori }))
                ]],
                ["IDLevel", "Filter Level", "options", [
                    { display: "Semua", value: "" },
                    ...listLevel.map(lvl => ({ display: lvl.NamaLevel, value: lvl.IDLevel }))
                ]]
            ];


            const { tableId } = generateDatatableHTML({
                targetSelector: "#groupsTableContainer",
                allowAction: allowAction,
                filters: filterKolom
            });

            const delete_action_callback = async (ids) => {
                console.log("Delete callback:", ids);

                const formData = new URLSearchParams();
                formData.append("p_type", type);
                formData.append("p_action", "delete");
                formData.append(IDName, ids);

                const { result } = await fetch_helper({
                    i18nKey: "", // ganti jika key i18next-nya berbeda
                    fetchFile: "",
                    formData: formData,
                });

                if (result) {
                    if (result.listErrorMessage && result.listErrorMessage.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "Nama", value: "NamaTournament" },
                            { display: "Keterangan", value: "Keterangan" },
                        ]);
                    } else {
                        Swal.fire({
                            text: result.Keterangan || "Peserta berhasil dihapus",
                            icon: result.Status === 1 ? "success" : "error",
                            confirmButtonText: "OK",
                        });
                    }
                }



                // ⚡ return result ke handler agar bisa dicek Status
                return result;
            };

            const dt = await initDatatable({
                tableId,
                formData,
                displayColumns: [
                    { columnName: IDName, displayedName: "ID", IsShown: false },
                    { columnName: "GroupName", displayedName: "Nama Group" },

                    { columnName: "NamaKategori", displayedName: "Kategori" },
                    { columnName: "NamaLevel", displayedName: "Level" },

                    { columnName: "TotalTeam", displayedName: "Total Team" },

                    { columnName: "LastUpdateBy" },
                    {
                        columnName: "LastUpdateAt",
                        dataType: "datetime",
                        displayedValue: {
                            format: "dd-MM-yyyy HH:mm:ss",
                        },
                    },
                ],
                allowAction: allowAction,
                delete_action_callback: delete_action_callback,
                filterKolom: filterKolom,
                additionalFilterParameter: [
                    ["IDTournament", currentTournamentId, 1]
                ]

            });
        }

        async function loadGroupTeamsTable() {
            // === Konfigurasi Display Columns ===
            const displayColumns = [
                { columnName: "IDGroupTeam", displayedName: "ID", isShown: false, dataType: "numeric" },
                { columnName: "GroupName", displayedName: "Nama Group", dataType: "text" },
                { columnName: "TeamName", displayedName: "Nama Team", dataType: "text" },
                { columnName: "NamaKategori", displayedName: "Kategori", dataType: "text" },
                { columnName: "NamaLevel", displayedName: "Level", dataType: "text" },
                { columnName: "LastUpdateBy", dataType: "text" },
                { columnName: "LastUpdateAt", dataType: "datetime", dateFormat: "dd-MM-yyyy HH:mm:ss" },
            ];

            // === Konfigurasi Filter ===
            const filterConfigs = [
                {
                    key: "IDKategori",
                    label: "Filter Kategori",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        ...listKategori.map(kat => ({ display: kat.NamaKategori, value: kat.IDKategori }))
                    ]
                },
                {
                    key: "IDLevel",
                    label: "Filter Level",
                    type: "options",
                    options: [
                        { display: "Semua", value: "" },
                        ...listLevel.map(lvl => ({ display: lvl.NamaLevel, value: lvl.IDLevel }))
                    ]
                }
            ];

            // === Action Buttons ===
            const actionButtons = [
                {
                    key: 'delete',
                    buttonType: 'Delete',
                    actionType: 'Callback',
                    callbackFunction: async (row) => {
                        const result = await Swal.fire({
                            text: `Yakin ingin menghapus assignment ${row.GroupName} - ${row.TeamName}?`,
                            icon: 'warning',
                            showCancelButton: true,
                            confirmButtonText: 'Ya, Hapus',
                            cancelButtonText: 'Batal',
                        });

                        if (result.isConfirmed) {
                            const formData = new URLSearchParams();
                            formData.append("p_type", "tournament_group_team");
                            formData.append("p_action", "delete");
                            formData.append("IDGroupTeam", row.IDGroupTeam);

                            const { result: deleteResult } = await fetch_helper({
                                formData: formData,
                            });

                            if (deleteResult.listErrorMessage && deleteResult.listErrorMessage.length > 0) {
                                await q_generateListErrorMessage(deleteResult, [
                                    { display: "Nama Group", value: "GroupName" },
                                    { display: "Keterangan", value: "Keterangan" },
                                ]);
                            } else {
                                Swal.fire({
                                    text: deleteResult.Keterangan || "Assignment berhasil dihapus",
                                    icon: deleteResult.Status === 1 ? "success" : "error",
                                    confirmButtonText: "OK",
                                });
                            }

                            if (deleteResult.Status === 1) {
                                dtInstance.loadData();
                            }
                        }
                    }
                }
            ];

            // === Bulk Actions ===
            const bulkActions = [
                {
                    key: 'delete_multiple',
                    label: 'Hapus Terpilih',
                    icon: 'fa-trash',
                    confirm: 'Yakin ingin menghapus data terpilih?',
                    callback: async (selectedData, selectedIds) => {
                        const formData = new URLSearchParams();
                        formData.append("p_type", "tournament_group_team");
                        formData.append("p_action", "delete");
                        formData.append("IDGroupTeam", selectedIds.join(','));

                        const { result: deleteResult } = await fetch_helper({ formData });

                        if (deleteResult.listErrorMessage && deleteResult.listErrorMessage.length > 0) {
                            await q_generateListErrorMessage(deleteResult, [
                                { display: "Nama Group", value: "GroupName" },
                                { display: "Keterangan", value: "Keterangan" },
                            ]);
                        } else {
                            Swal.fire({
                                text: deleteResult.Keterangan || "Assignment berhasil dihapus",
                                icon: deleteResult.Status === 1 ? "success" : "error",
                                confirmButtonText: "OK",
                            });
                        }

                        if (deleteResult.Status === 1) {
                            dtInstance.loadData();
                        }
                    }
                }
            ];

            // === Inisialisasi DataTable ===
            const formData = new URLSearchParams();
            formData.append("p_type", "tournament_group_team");
            formData.append("p_action", "select");

            const dtInstance = new DataTable({
                containerId: 'groupTeamsTableContainer',
                formData: formData,
                displayColumns: displayColumns,
                filterConfigs: filterConfigs,
                actionButtons: actionButtons,
                bulkActions: bulkActions,
                orderColumnList: [
                    { display: 'Nama Group', columnName: 'GroupName' },
                    { display: 'Nama Team', columnName: 'TeamName' },
                    { display: 'Kategori', columnName: 'NamaKategori' },
                    { display: 'Level', columnName: 'NamaLevel' },
                ],
                rowSelection: {
                    enabled: true,
                    rowKey: 'IDGroupTeam',
                },
                fetchHelper: fetch_helper,
                defaultRowsPerPage: 25,
                rowsPerPageOptions: [10, 25, 50, 100, 250, 500],
                exportOptions: {
                    copy: true,
                    csv: true,
                    excel: true,
                    pdf: false,
                },
                allowFilter: true,
                allowOrder: true,
                allowPaging: true,
                allowExport: true,
                additionalFilterParameter: [
                    ["IDTournament", currentTournamentId, 1]
                ]
            });

            // === Render dan Load Data ===
            dtInstance.render();

            // Simpan instance ke variabel global jika perlu
            window.groupTeamsTableInstance = dtInstance;
        }

        async function loadGroupTeamsTable_old() {
            const type = "tournament_group_team";
            const IDName = "IDGroupTeam";

            const formData = new URLSearchParams();
            formData.append("p_type", type);
            formData.append("p_action", "select");




            const allowAction = true;

            const filterKolom = [
                ["IDKategori", "Filter Kategori", "options", [
                    { display: "Semua", value: "" },
                    ...listKategori.map(kat => ({ display: kat.NamaKategori, value: kat.IDKategori }))
                ]],
                ["IDLevel", "Filter Level", "options", [
                    { display: "Semua", value: "" },
                    ...listLevel.map(lvl => ({ display: lvl.NamaLevel, value: lvl.IDLevel }))
                ]]
            ];


            const { tableId } = generateDatatableHTML({
                targetSelector: "#groupTeamsTableContainer",
                allowAction: allowAction,
                filters: filterKolom
            });

            const delete_action_callback = async (ids) => {
                console.log("Delete callback:", ids);

                const formData = new URLSearchParams();
                formData.append("p_type", type);
                formData.append("p_action", "delete");
                formData.append(IDName, ids);

                const { result } = await fetch_helper({
                    i18nKey: "", // ganti jika key i18next-nya berbeda
                    fetchFile: "",
                    formData: formData,
                });

                if (result) {
                    if (result.listErrorMessage && result.listErrorMessage.length > 0) {
                        await q_generateListErrorMessage(result, [
                            { display: "Nama", value: "NamaTournament" },
                            { display: "Keterangan", value: "Keterangan" },
                        ]);
                    } else {
                        Swal.fire({
                            text: result.Keterangan || "Peserta berhasil dihapus",
                            icon: result.Status === 1 ? "success" : "error",
                            confirmButtonText: "OK",
                        });
                    }
                }



                // ⚡ return result ke handler agar bisa dicek Status
                return result;
            };

            const dt = await initDatatable({
                tableId,
                formData,
                displayColumns: [
                    { columnName: IDName, displayedName: "ID", IsShown: false },
                    { columnName: "GroupName", displayedName: "Nama Group" },
                    { columnName: "TeamName", displayedName: "Nama Team" },

                    { columnName: "NamaKategori", displayedName: "Kategori" },
                    { columnName: "NamaLevel", displayedName: "Level" },

                    { columnName: "LastUpdateBy" },
                    {
                        columnName: "LastUpdateAt",
                        dataType: "datetime",
                        displayedValue: {
                            format: "dd-MM-yyyy HH:mm:ss",
                        },
                    },
                ],
                allowAction: allowAction,
                delete_action_callback: delete_action_callback,
                filterKolom: filterKolom,
                additionalFilterParameter: [
                    ["IDTournament", currentTournamentId, 1]
                ]
            });
        }


        // ========================
        // DOM READY
        // ========================
        KTUtil.onDOMContentLoaded(function () {
            window.onI18nReadyCallbacks = window.onI18nReadyCallbacks || [];
            if (window.i18nReady) {
                starting();
            } else {
                window.onI18nReadyCallbacks.push(starting());
            }
        });

        async function starting() {
            let ses_res = null;

            try {
                const res = await checkSession(true);
                if (res?.Status === 1) {
                    ses_res = res;
                }
            } catch (err) {
                console.warn("checkSession failed:", err);
            }

            if (ses_res) {



                updateHeaderUser(ses_res.listU || {}, ses_res.listA || {});
                initDynamicLanguageHandler(["header", "generic"]);
                toggleContentOverlay("off");
                init(ses_res.listU || {}, ses_res.listA || {});
            }
        }

    </script>

    <!--end::Custom Javascript-->
    <!--end::Javascript-->
</body>
<!--end::Body-->

</html>