<?php

ini_set('display_errors', 1);

if (!isset($segments) || !defined('APP_ROUTER')) {
    http_response_code(403);
    include $baseDir . "/error-pages/403.php";
    exit;
}

$type = $segments[1] ?? null;
$slug = $segments[2] ?? null;

$allowed_types = ["programm", "live"];

if ($type !== null && !in_array($type, $allowed_types)) {
    http_response_code(400);
    include $baseDir . "/error-pages/400.html";
    exit;
}

$baseDir = $_SERVER['DOCUMENT_ROOT'];

require $baseDir . '/../scripts/db/db-verbindung-script-guest.php';

require $baseDir . "/../scripts/db/db-tables.php";
require $baseDir . "/../scripts/db/db-functions.php";

$rankLive_public = db_get_variable($guest, $db_tabelle_var, ['rankLivePublic']) ?? 0;

require $baseDir . '/../scripts/websocket/ws-create-token.php';

require_once $baseDir . '/../scripts/session_functions.php';

ini_wkvs_session(true);

$csrf_token = $_SESSION['csrf_token'] ?? '';

if (!$rankLive_public) {
    check_user_permission('wk_leitung', false, true);
}

$is_live = $type === 'live';

if ($slug !== null && !$is_live) {

    $alle_programme_db = db_select($guest, $db_tabelle_kategorien, '`programm`', 'aktiv = ?', ['1']);
    $raw_programme = array_column($alle_programme_db, 'programm', 'programm');

    $alle_programme = [];
    foreach ($raw_programme as $prog) {
        $normalized_key = str_replace(' ', '-', strtolower($prog));
        $alle_programme[$normalized_key] = $prog;
    }

    $req_prog = str_replace(' ', '-', strtolower($slug));

    if (!isset($alle_programme[$req_prog])) {
        http_response_code(400);
        $message = 'Das gesuchte Programm kann nicht gefunden werden';
        include $baseDir . "/error-pages/400.php";
        exit;
    }

    $validated_programm_name = $alle_programme[$req_prog];
}

$selectedFreigabeId = 'A';

$json_type = $is_live ? 'rankLive-geraet' : 'rankLive-overview';

$jsonstr = db_select($guest, $db_tabelle_tabellen_konfiguration, 'json', 'type_slug = ?', [$json_type], '', 1);

$data = json_decode($jsonstr[0]['json'], true);

$headers = $data['header'] ?? [];
$bodyColumns = $data['body'] ?? [];

$alle_programme_db = db_select($guest, $db_tabelle_kategorien, '`programm`, `id`', 'aktiv = ?', ['1']);
$indexedProgrammes = array_column($alle_programme_db, 'programm', 'id');

$personData = [
    'geburtsdatum' => 'Geburtsdatum',
    'name' => 'Name',
    'vorname' => 'Vorname',
    'verein' => 'Verein',
    'programm' => 'Programm'
];

$disciplines = db_select($guest, $db_tabelle_disziplinen, '*', '', [], 'start_index ASC');

$indexedArrayGeraete = array_column($disciplines, 'name', 'id');

if ($is_live) {
    $indexed_array_geraete_id_index = array_column($disciplines, 'start_index', 'id');
    
    $indexed_array_geraete_index_id = array_flip($indexed_array_geraete_id_index);
    
    $abt = (int) (db_get_variable($guest, $db_tabelle_var, ['wk_panel_current_abt']) ?? 1);
    $akt_subabt = (int) (db_get_variable($guest, $db_tabelle_var, ['wk_panel_current_subabt_admin']) ?? 1);

    $max_subabt = count($disciplines);

    $stmt = $guest->prepare("SELECT 
        t.id,
        t.name, 
        t.vorname, 
        t.programm,
        t.verein,
        t.geburtsdatum,
        p.id AS programm_id,
        tabt.`turnerin_index` AS start_index,
        tabt.`geraet_id` AS startgeraet,
        tabt.`abteilung_id` AS abt_id
    FROM $db_tabelle_teilnehmende t
    LEFT JOIN $db_tabelle_kategorien p ON p.programm = t.programm
    INNER JOIN $db_tabelle_teilnehmende_gruppen tabt ON tabt.`turnerin_id` = t.`id`
    INNER JOIN $db_tabelle_gruppen abt ON abt.`id` = tabt.`abteilung_id`
    WHERE (t.bezahlt = 4 OR t.bezahltoverride = 4) AND abt.`order_index` = ?");

    $stmt->bind_param("i", $abt);
} elseif ($type === 'programm' && $slug !== null) {
    $stmt = $guest->prepare("SELECT 
        u.id,
        u.name, 
        u.vorname, 
        u.programm,
        u.verein,
        u.geburtsdatum,
        p.id AS programm_id
    FROM $db_tabelle_teilnehmende u
    LEFT JOIN $db_tabelle_kategorien p ON p.programm = u.programm
    WHERE (u.bezahlt = 4 OR u.bezahltoverride = 4) AND u.programm = ?");

    $stmt->bind_param("s", $validated_programm_name);
} else {
    $stmt = $guest->prepare("SELECT 
        u.id,
        u.name, 
        u.vorname, 
        u.programm,
        u.verein,
        u.geburtsdatum,
        p.id AS programm_id
    FROM $db_tabelle_teilnehmende u
    LEFT JOIN $db_tabelle_kategorien p ON p.programm = u.programm
    WHERE (u.bezahlt = 4 OR u.bezahltoverride = 4)");
}

$stmt->execute();

$result = $stmt->get_result();
$tures = $result->fetch_all(MYSQLI_ASSOC);

$stmt->close();

$indexedTures = [];

foreach ($tures as $s_tures) {
    $indexedTures[$s_tures['programm_id']][$s_tures['id']] = $s_tures;
}

$current_wk_id = (int) db_get_variable($guest, $db_tabelle_var, ['current_wk_id']) ?: 0;

$stmt = $guest->prepare("SELECT `note_bezeichnung_id`, `geraet_id`, `person_id`, `run_number`, `public_value`
FROM $db_tabelle_wertungen
  WHERE `is_public` = 1
  AND `wk_id` = ?");

$stmt->bind_param("i", $current_wk_id);

$stmt->execute();

$result = $stmt->get_result();
$noten = $result->fetch_all(MYSQLI_ASSOC);

$stmt->close();

$indexedNoten = [];

$stmt = $guest->prepare("SELECT `id`, `geraete_json`, `pro_geraet`, `anzahl_laeufe_json`, `name`, `default_value` FROM $db_tabelle_wertungstypen");

$stmt->execute();

$result = $stmt->get_result();
$notenConfig = $result->fetch_all(MYSQLI_ASSOC);

$stmt->close();

$disciplines = db_select($guest, $db_tabelle_disziplinen, '*', '', [], 'start_index ASC');

$indexedNotenConfig = array_column($notenConfig, null, 'id');

$rangNote = intval(db_get_var($guest, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['rangNote']));

$orderBestRang = db_get_var($guest, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['orderBestRang']);

$okValuesOrderBestRang = ["ASC", "DESC"];

$rangOrderOk = in_array($orderBestRang, $okValuesOrderBestRang) && intval($rangNote) > 0;

$notenIndexed = [];

foreach ($noten as $sn) {
    $notenIndexed[$sn['person_id']][$sn['geraet_id']][$sn['note_bezeichnung_id']][$sn['run_number']] = $sn['public_value'];
}

$disciplinesExtended = array_merge(
    [["id" => 0, "name" => "None"]],
    $disciplines
);

$arrayIndexedNoten = [];


$wkName = db_get_var($guest, "SELECT `value` FROM $db_tabelle_var WHERE `name` = ?", ['wkName']);

$grouped = [];

function groop_by_key($array, $array_key, bool $int = false): array
{
    $grouped = [];
    if ($int) {
        foreach ($array as $entry) {
            $key = (int) $entry[$array_key];
            $grouped[$key][] = $entry;
        }
    } else {
        foreach ($array as $entry) {
            $key = $entry[$array_key];
            $grouped[$key][] = $entry;
        }
    }
    return $grouped;
}

if ($is_live) {

    $grouped = groop_by_key($tures, 'startgeraet', true);

} else {

    $grouped = groop_by_key($tures, 'programm');

    foreach ($grouped as $key => $group) {
        $orderIndexes[$key] = $indexedProgramme[$key]['order_index'] ?? 10000;
    }

    if (isset($orderIndexes)) {
        uksort($grouped, function ($a, $b) use ($orderIndexes) {
            return $orderIndexes[$a] <=> $orderIndexes[$b];
        });
    }

}

foreach ($grouped as $entry_key => $entries_group):

    
endforeach;

$timeZone = new \DateTimeZone('Europe/Zurich');

$formatter = new \IntlDateFormatter(
    'de_CH',
    \IntlDateFormatter::FULL,
    \IntlDateFormatter::NONE,
    $timeZone
);

$display_over_array = [];

function constructSingleValueSpanPublic($token, $type, $row, $selected_geraet_id = 0)
{
    global $formatter;
    global $personData;
    global $arrayIndexedNoten;
    global $timeZone;
    global $display_over_array;
    global $indexedNotenConfig;
    global $indexedProgramme;

    $text = '';
    $classes = 'singleValueSpan';

    $bold = $token['bold'] ?? false;

    $font_size = intval($token['fontSize'] ?? 0);

    $min_display_width = intval($token['minDisplayWidth'] ?? 1) - 1;

    $linked_el_uid = (int) ($token['linkedElUid'] ?? 0);

    $uid = (int) ($token['uid'] ?? 0);
            

    $style = '';

    if ($font_size > 0) {
        $style = ' style="font-size: ' . $font_size . 'px"';
    }

    if ($min_display_width > 0) {
        $classes .= ' displayOver' . $min_display_width . 'px';
        $display_over_array[] = $min_display_width;
    }

    $dataAttributes = 'data-bold="' . htmlspecialchars($bold) . '" data-uid="'. $uid .'"';

    if ($linked_el_uid > 0) {
        $dataAttributes .= ' data-linked-el-uid="' . $linked_el_uid . '"';
    }

    switch ($type) {
        case 'text':
            $text = $token['text'] ?? '';
            $classes .= ' staticText';
            break;

        case 'sortData':
            $column = $token['column'] ?? '';
            switch ($column) {
                case "rang":
                    $classes .= ' rangField';
                    break;
                case "startindex":
                    $text = $row['calculedstartindex'];
                    break;
            }
            break;

        case 'personData':
            $column = $token['column'] ?? '';

            if ($column === 'jahrgang') {
                $geburtsdatum = $row['geburtsdatum'] ?? '';
                $date = new \DateTimeImmutable($geburtsdatum, $timeZone);
                $formatter->setPattern('yyyy');

                $text = $formatter->format($date);
            } else {
                $text = array_key_exists($column, $personData) ? $row[$column] ?? '' : '';

                if ($column === 'geburtsdatum') {
                    $date = new \DateTimeImmutable($text, $timeZone);
                    $formatter->setPattern(($token['phpDateFormat'] ?? '' !== '') ? $token['phpDateFormat'] : 'd. MMMM YYYY');

                    $text = $formatter->format($date);
                }
            }

            break;

        case 'notenGeraetData':

            $field_type_id = intval($token['field-type-id'] ?? 0);
            $run = intval($token['run'] ?? 0);
            $person_id = $row['id'];

            $programm_id = $indexedProgramme[$row['programm']]['id'] ?? 0;

            $runsJSON = json_decode($indexedNotenConfig[$field_type_id]['anzahl_laeufe_json'] ?? '', true) ?? [];

            $max_run = $runsJSON[$selected_geraet_id][$programm_id] ?? $runsJSON[$selected_geraet_id]['all'] ?? $runsJSON['default'] ?? 0;

            if ($run > $max_run) {
                $classes .= ' nonExistentEl';

            } else {
                $notenNullable = ($token['notenNullable'] ?? 'false') === 'true';

                $dataAttributes .= ' data-field-type-id="' . $field_type_id . '"';
                $dataAttributes .= ' data-geraet-id="' . $selected_geraet_id . '"';
                $dataAttributes .= ' data-person-id="' . $person_id . '"';
                $dataAttributes .= ' data-run="' . $run . '"';
                $dataAttributes .= ' data-noten-nullable="' . (($notenNullable) ? "true" : "false") . '"';

                $text = $arrayIndexedNoten[$person_id][$selected_geraet_id][$field_type_id][$run]['value'] ?? null;

                if ($notenNullable && $text !== null && floatval($text) === 0.0) {
                    $text = ' ';
                }

                if ($text === null) {
                    $classes .= ' emtyPlaceholder';
                    $text = '-';
                }

                $classes .= ' changebleValue';
            }


            break;

            
        case 'notenData':
            $field_type_id = intval($token['field-type-id'] ?? 0);
            $geraet_id = intval($token['geraet-id'] ?? 0);
            $run = intval($token['run'] ?? 0);
            $person_id = $row['id'];
            $notenNullable = ($token['notenNullable'] ?? 'false') === 'true';

            $dataAttributes .= ' data-field-type-id="' . $field_type_id . '"';
            $dataAttributes .= ' data-geraet-id="' . $geraet_id . '"';
            $dataAttributes .= ' data-person-id="' . $person_id . '"';
            $dataAttributes .= ' data-run="' . $run . '"';
            $dataAttributes .= ' data-noten-nullable="' . (($notenNullable) ? "true" : "false") . '"';

            $text = $arrayIndexedNoten[$person_id][$geraet_id][$field_type_id][$run]['value'] ?? null;

            if ($notenNullable && $text !== null && floatval($text) === 0.0) {
                $text = ' ';
            }

            if ($text === null) {
                $classes .= ' emtyPlaceholder';
                $text = '-';
            }

            $classes .= ' changebleValue';

            break;
    }
    ?>
    <span class="<?= $classes ?>" <?= $dataAttributes; ?><?= $style ?>><?= htmlspecialchars($text); ?></span>
<?php }

?>
<!DOCTYPE html>
<html lang="de-ch">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="icon" type="png" href="/intern/img/icon.png">
    <link rel="stylesheet" href="/intern/css/custom-msg-display.css">
    <link href="/files/fonts/fonts.css" rel="stylesheet">
    <link rel="stylesheet" href="/css/custom-display-editor-required-css.css">
    <link rel="stylesheet" href="/css/rank-live.css">
    <link rel="stylesheet" href="/css/header.css">
    <script src="/intern/js/jquery/jquery-3.7.1.min.js"></script>
    <script src="/intern/js/custom-msg-display.js"></script>
    <script src="/js/header.js"></script>
    <title>RankLive - <?= htmlspecialchars($wkName) ?></title>
</head>

<body>
    <section class="bgSection">
        <?php include $baseDir . '/../scripts/public-elements/rankLive-header.php'; ?>
        <?php if (count($indexedTures) < 1) : ?>
            <h3>Noch keine Daten verfügbar</h3>
            <?php exit; ?>
        <?php endif; ?>
        <div class="headerWrapper">
            <h2 class="headerMain">RankLive</h2>
            <?php if ($is_live) : ?>
                <h4>Gruppe: <?= (int) $abt ?></h4>
                <h4>Rotation: <?= (int) $akt_subabt ?></h4>
            <?php elseif ($type === 'programm' && $slug !== null) : ?>
                <h4><?= htmlspecialchars($validated_programm_name) ?></h4>
            <?php endif; ?>
        </div>
        <div class="allAbtContainer">
            <?php foreach ($grouped as $entry_key => $entries_group):

                $table_data_geraet_label = '';
                $extra_table_classes = '';

                if ($is_live) {
                    $entries_with_calculated_index = [];

                    // Optional: Vorab-Caching der MAX-Indices, um DB-Abfragen im Loop zu vermeiden
                    // (Nur aktivieren, wenn $entries_group sehr groß ist und Performance-Probleme auftreten)
                    $maxStartIndexCache = [];

                    foreach ($entries_group as $row) {
                        $old_geraet_id = $row['startgeraet'];
                        
                        $old_geraet_index = $indexed_array_geraete_id_index[$row['startgeraet']];
                        $shifted_geraet_index = $old_geraet_index + $akt_subabt - 1;
                        if ($shifted_geraet_index > $max_subabt) {
                            $shifted_geraet_index -= $max_subabt;
                        }
                        $row['startgeraet'] = $indexed_array_geraete_index_id[$shifted_geraet_index];
                        
                        $rohstartindex = intval($row['start_index']);
                        $abtId = intval($row['abt_id']);

                        // Hole maxStartIndex (mit Caching-Logik optional)
                        if (!isset($maxStartIndexCache["$abtId-$old_geraet_id "])) {
                            $maxStartIndexCache["$abtId-$old_geraet_id"] = db_get_var($guest, "SELECT COUNT(*) FROM `$db_tabelle_teilnehmende_gruppen` WHERE abteilung_id = ? AND geraet_id = ?", [$abtId, $old_geraet_id]);
                        }

                        $maxstartindex = $maxStartIndexCache["$abtId-$old_geraet_id"];

                        // Sicherheit: Vermeiden Sie Division durch Null oder Modulo durch 0
                        if ($maxstartindex < 1) {
                            $maxstartindex = 1;
                        }

                        // The order shift depends on the number of rotations the group has made
                        $rotation_shift = $akt_subabt - 1;

                        $calculedstartindex = $rohstartindex - $rotation_shift;

                        // Sicherstellen, dass das Ergebnis positiv ist (PHP Modulo kann negative Ergebnisse liefern)
                        // Wenn das Ergebnis negativ ist, addieren wir maxstartindex
                        if ($calculedstartindex < 1) {
                            $calculedstartindex += $maxstartindex;
                        }

                        // Kopie der Zeile erstellen, um Originaldaten nicht zu verändern
                        $row['calculedstartindex'] = $calculedstartindex;
                        $entries_with_calculated_index[] = $row;
                    }

                    // Sortieren nach dem berechneten Startindex
                    usort($entries_with_calculated_index, fn($a, $b) => $a['calculedstartindex'] <=> $b['calculedstartindex']);

                    $entries_to_display = $entries_with_calculated_index;

                    $shifted_geraet_index = $indexed_array_geraete_id_index[$entry_key] + $akt_subabt - 1;
                    if ($shifted_geraet_index > $max_subabt) {
                        $shifted_geraet_index -= $max_subabt;
                    }
                    $shifted_geraet_id = $indexed_array_geraete_index_id[$shifted_geraet_index];

                    $table_data_geraet_label = ' data-geraet-index="' . $shifted_geraet_index . '"';
                    $extra_table_classes = ' shiftedGeraetTable';
                } else {
                    $entries_to_display = $entries_group;
                }

                foreach ($entries_to_display as $row):
                    $rangNotenArray[$entry_key][$row['id']] = isset($notenIndexed[$row['id']][0][$rangNote][1]) ? floatval($notenIndexed[$row['id']][0][$rangNote][1]) : null;
                    foreach ($disciplinesExtended as $discipline):
                        foreach ($notenConfig as $snC):

                            if (intval($snC['pro_geraet']) === 1 && intval($discipline['id']) === 0) {
                                continue;
                            }

                            if (intval($snC['pro_geraet']) !== 1) {
                                $allowedGeraete = !empty($snC['geraete_json']) ? json_decode($snC['geraete_json'], true) : [];
                                if (!in_array($discipline['id'], $allowedGeraete)) {
                                    continue;
                                }
                            }

                            $runsJSON = !empty($snC['anzahl_laeufe_json']) ? json_decode($snC['anzahl_laeufe_json'], true) : [];

                            $runs = $runsJSON[$discipline['id']][$entry_key] ?? $runsJSON[$discipline['id']]['all'] ?? $runsJSON["default"] ?? 1;

                            for ($r = 1; $r <= $runs; $r++):
                                $note = $notenIndexed[$row['id']][$discipline['id']][$snC['id']][$r] ?? null;
                                $normalizedNote = ($note !== null) ? number_format($note, $snC['nullstellen'] ?? 2) : null;

                                $arrayIndexedNoten[intval($row['id'])][intval($discipline['id'])][intval($snC['id'])][intval($r)] = ["value" => $normalizedNote];
                            endfor;
                        endforeach;
                    endforeach;
                endforeach; ?>
                <div class="singleAbtDiv<?= $extra_table_classes ?>" <?= $table_data_geraet_label ?>>
                    <?php if (!($type === 'programm' && $slug !== null)) : ?>
                        <h2 class="headerAbt"><?= ($is_live) ? $indexedArrayGeraete[$shifted_geraet_id] ?? '' : $entry_key ?? '' ?></h2>
                    <?php endif; ?>
                    <?php $geraet_id_for_live_view = $is_live ? $shifted_geraet_id : 0 ?>
                    <div class="tableWraper">
                        <table class="customDisplayEditorTable">
                            <thead>
                                <tr>
                                    <?php foreach ($headers as $header_data): ?>
                                        <?php 
                                        $min_display_width = ($header_data['minDisplayWidth'] ?? 1) - 1;

                                        $class = "";

                                        if ($min_display_width > 0) {
                                            $class = 'displayOver' . $min_display_width . 'px';
                                            $display_over_array[] = $min_display_width;
                                        }
                                        ?>
                                        
                                        <th class="<?= $class ?>">
                                            <?= htmlspecialchars($header_data['title']) ?>
                                        </th>
                                    <?php endforeach; ?>
                                </tr>
                            </thead>
                            <tbody <?= !$is_live ? 'data-programm-id="'. $entry_key .'"' : ''?>>
                                <?php foreach ($entries_to_display as $row): ?>
                                    <tr data-person-id="<?= $row['id'] ?>">
                                        <?php foreach ($bodyColumns as $ind => $columnTokens): ?>
                                            <?php 
                                            $class = '';

                                            if (isset($headers[$ind]['minDisplayWidth']) && $headers[$ind]['minDisplayWidth'] > 1) {
                                                $min_display_width = ($headers[$ind]['minDisplayWidth'] ?? 1) - 1;

                                                $class = 'displayOver' . $min_display_width . 'px';
                                                $display_over_array[] = $min_display_width;
                                            }
                                            ?>
                                            <td class=<?= $class ?>>
                                                <span class="tdSpan">

                                                    <?php
                                                    foreach ($columnTokens as $token):
                                                        $type = $token['type'] ?? '';
                                                        if ($type === 'layoutEls') :
                                                            $column = $token['column'];
                                                            $content = $token['content'] ?? []; ?>
                                                            <div class="<?= $column ?>LayoutEl">
                                                                <?php foreach ($content as $layout_row) : ?>
                                                                    <span class="<?= $column ?>LayoutElRow">
                                                                        <?php foreach ($layout_row as $el) :
                                                                            constructSingleValueSpanPublic($el, $el['type'], $row, $geraet_id_for_live_view);
                                                                        endforeach; ?>
                                                                    </span>
                                                                <?php endforeach; ?>
                                                            </div>
                                                        <?php else:
                                                            constructSingleValueSpanPublic($token, $type, $row, $geraet_id_for_live_view);
                                                        endif;                                            
                                                    endforeach; ?>
                                                </span>
                                            </td>
                                        <?php endforeach; ?>
                                    </tr>
                                <?php endforeach; ?>
                            </tbody>

                        </table>
                    </div>
                </div>
            <?php endforeach; ?>
        </div>
        <div class="tableCutter"></div>
    </section>
    <style>
        <?php 
        $unique_display_over_array = array_unique($display_over_array);
        
        foreach ($unique_display_over_array as $s_size): 
            $s_size = (int)$s_size; 
        ?>
            @media (max-width: <?= $s_size ?>px) {
                .displayOver<?= $s_size ?>px {
                    display: none !important;
                }
            }
        <?php endforeach; ?>
    </style>
    <script>
        window.FREIGABE = "<?= $selectedFreigabeId; ?>";
        window.CSDR_TOKEN = "<?= $csrf_token; ?>";
        window.WS_ACCESS_TOKEN = "<?= generateWSReadToken('rankLive', $selectedFreigabeId) ?>";
        window.AKTUELLES_JAHR = "<?= $current_wk_id ?>";
        window.RANG_NOTEN_ARRAY = '<?= json_encode($rangNotenArray, JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT); ?>';
        window.RANG_SORT = "<?= $orderBestRang ?>";
        window.RANG_NOTE_ID = <?= $rangNote ?>;
        window.LIVE = <?= (int) $is_live ?>;
    </script>

    <script src="/RankLive/js/script.js"></script>

</body>