jQuery(document).ready(function($) {
    const csrf_token = window.CSDR_TOKEN;

    const allowedRanglistenTypes = ['downloadRangliste', 'updateServerRangliste'];

    $('.ranglisteExport').on('click', function() {
        const $button = $(this);
        const progId = $button.data('id');
        const fieldType = $button.data('field_type');

        if (!allowedRanglistenTypes.includes(fieldType)) {
            displayMsg(0, "Dieser Button besitzt eine fehlerhafte Konfiguration");
            return;
        }

        // Visual feedback (optional but recommended)
        $button.addClass('opacity50');

        const url = '/intern/scripts/kampfrichter/ajax/ajax-neu_rangliste.php';

        fetch(url, {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                csrf_token,
                prog: progId,
                type: fieldType
            })
        })
        .then(res => {
            if (!res.ok) throw new Error('Network response was not ok');
            
            // Return both the response and the blob/json promise 
            // to keep the chain clean, or handle them based on fieldType here.
            if (fieldType === 'downloadRangliste') {
                return res.blob().then(blob => ({ type: 'blob', data: blob }));
            } else {
                return res.json().then(json => ({ type: 'json', data: json }));
            }
        })
        .then(result => {
            if (result.type === 'blob') {
                const url = window.URL.createObjectURL(result.data);
                const a = document.createElement('a');
                a.href = url;
                a.download = "Rangliste.pdf";
                document.body.appendChild(a);
                a.click();
                a.remove();
                window.URL.revokeObjectURL(url);
                displayMsg(1, "Rangliste wurde erfolgreich heuntergeladen.");
            } else if (result.type === 'json') {
                if (result.data.success) {
                    const $container = $button.closest(".singleAbtDiv");
                    $container.find(".uploadRanglisteText").addClass("hidden");
                    $container.find(".updateRanglisteText").removeClass("hidden");
                    $container.find(".rangliseOnlineSpan").removeClass("hidden");
                    $container.find(".ranglisteDelete").removeClass("hidden");
                    displayMsg(1, "Die Rangliste wurde auf dem Server aktualisiert.");
                } else {
                    displayMsg(0, "Fehler beim Aktualiseren der Rangliste.");
                }
            }
            $button.removeClass('opacity50');
        })
        .catch(err => {
            displayMsg(0, "Error processing request:", err);
            console.error("Error processing request:", err);
            $button.removeClass('opacity50');
        });
        
    });

    $('.ranglisteDelete').on('click', function() {
        const $button = $(this);
        const progId = $button.data('id');

        // Visual feedback (optional but recommended)
        $button.addClass('opacity50');

        const url = '/intern/scripts/kampfrichter/ajax/ajax-delete_rangliste.php';

        fetch(url, {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                csrf_token,
                prog: progId
            })
        })
        .then(res => {
            if (!res.ok) throw new Error('Network response was not ok');
            
            
            return res.json().then(json => ({ type: 'json', data: json }));
            
        })
        .then(result => {
            if (result.data.success) {
                const $container = $button.closest(".singleAbtDiv");
                $container.find(".uploadRanglisteText").removeClass("hidden");
                $container.find(".updateRanglisteText").addClass("hidden");
                $container.find(".rangliseOnlineSpan").addClass("hidden");
                $container.find(".ranglisteDelete").addClass("hidden");
                displayMsg(1, "Die Rangliste wurde erfolgreich entfernt.");
            } else {
                displayMsg(0, "Fehler beim Löschen der Rangliste.");
            }
            $button.removeClass('opacity50');
        })
        .catch(err => {
            displayMsg(0, "Error processing request:", err);
            console.error("Error processing request:", err);
            $button.removeClass('opacity50');
        });
        
    });
	
    $('.protokollExport').on('click', function() {
        const $button = $(this);
        const abteilungId = $button.data('abteilung-id');
        

        const now = new Date();

        const formattedDate = new Intl.DateTimeFormat('en-CA', {
            year: 'numeric',
            month: '2-digit',
            day: '2-digit',
            hour: '2-digit',
            minute: '2-digit',
            second: '2-digit',
            hour12: false
        }).format(now).replace(/,/g, '');

        const url = '/intern/scripts/kampfrichter/ajax/ajax-neu_protokoll.php';

        fetch(url, {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                csrf_token,
                abteilungId: abteilungId,
                date: formattedDate
            })
        })
        .then(res => {
            if (!res.ok) throw new Error('Network response was not ok');

            return res.blob().then(blob => ({ type: 'blob', data: blob }));
        })
        .then(result => {
            if (result.type === 'blob') {
                const url = window.URL.createObjectURL(result.data);
                const a = document.createElement('a');
                a.href = url;
                a.download = "Protokoll.pdf";
                document.body.appendChild(a);
                a.click();
                a.remove();
                window.URL.revokeObjectURL(url);
                displayMsg(1, "Protokoll wurde erfolgreich heuntergeladen.");
            }
        })
        .catch(err => {
            displayMsg(0, "Error processing request:", err);
            console.error("Error processing request:", err);
        });
        
    });

    $('.protokollDeleteEntries').on('click', async function() {
        const $button = $(this);
        const abt = $button.data('abteilung-id');

        if (!await displayConfirmImportant("Möchten Sie wirklich alle Protokolleinträge für diese Abteilung löschen? Diese Aktion kann nicht rückgängig gemacht werden.")) { return; }

        const url = '/intern/scripts/kampfrichter/ajax/ajax-delete_protokoll_entries.php';

        fetch(url, {
            method: 'POST',
            headers: {'Content-Type': 'application/x-www-form-urlencoded'},
            body: new URLSearchParams({
                csrf_token,
                abteilungId: abt
            })
        })
        .then(res => {
            if (!res.ok) throw new Error('Network response was not ok');
            
            
            return res.json().then(json => ({ type: 'json', data: json }));
            
        })
        .then(result => {
            if (result.data.success) {
                displayMsg(1, "Die Einträge wurden erfolgreich entfernt.");
            } else {
                displayMsg(0, "Fehler beim Löschen der Einträge.");
            }
        })
        .catch(err => {
            displayMsg(0, "Error processing request:", err);
            console.error("Error processing request:", err);
        });
        
    });

    let activeEdit = null;

    $(document).on('click', '.editableValue', function () {
        const input = $(this);

        // Already editing
        if (!input.prop('readonly')) {
            return;
        }

        // Close another active edit
        if (activeEdit && activeEdit.get(0) !== input.get(0)) {
            cancelEdit(activeEdit);
        }

        input.data('original', input.val());
        input.prop('readonly', false).focus().select();

        activeEdit = input;

        input.on('keydown.edit', function (e) {
            if (e.key === 'Enter') {
                e.preventDefault();
                saveEdit(input);
            }

            if (e.key === 'Escape') {
                e.preventDefault();
                cancelEdit(input);
            }
        });

        input.on('blur.edit', function () {
            saveEdit(input);
        });
    });

    function saveEdit(input) {
        const originalValue = input.data('original');
        const newValue = input.val();
        const type = input.data('type');
        const discipline = input.data('discipline');
        const dataId = input.data('id');

        if (newValue === originalValue) {
            input.prop('readonly', true);
            cleanup(input);
            return;
        }

        input.addClass('is-saving');

        $.ajax({
            url: '/intern/scripts/kampfrichter/ajax/ajax-update_value_kampfrichter_admin.php',
            method: 'POST',
            data: {
                id: dataId,
                field_type: type,
                discipline: discipline,
                value: newValue
            },
            success: function () {
                input.prop('readonly', true);

                const row = input.closest('td');
                if (row.length) {
                    row.css(
                        'background',
                        'radial-gradient(circle at bottom right, #22c55e, transparent 55%)'
                    );

                    setTimeout(() => row.css('background', ''), 2000);
                }

                ws.send(JSON.stringify({
                    type: "KAMPFRICHTER_UPDATE",
                    payload: {
                        discipline: discipline,
                        id: dataId,
                        val: newValue
                    }
                }));
            },
            error: function () {
                input.val(originalValue).prop('readonly', true);
                alert('Speichern fehlgeschlagen');
            },
            complete: function () {
                input.removeClass('is-saving');
                cleanup(input);
            }
        });
    }

    function cancelEdit(input) {
        input.val(input.data('original')).prop('readonly', true);
        cleanup(input);
    }

    function cleanup(input) {
        input.off('.edit');
        activeEdit = null;
    }

    let rangNotenArray = JSON.parse(window.RANG_NOTEN_ARRAY) ?? [];

    const rangNotenId = window.RANG_NOTE_ID ?? 0;

    const rangSort = window.RANG_SORT ?? '';

    const selecteddiscipline = window.FREIGABE;

    ws.addEventListener("message", event => { // Use 'event' as it's more standard than 'blob'
        let msgOBJ;

        try {
            msgOBJ = JSON.parse(event.data);
        } catch (error) {
            return;
        }

        // Ensure it's an UPDATE type (matches your sendToGroup logic)
        if (msgOBJ?.type === "UPDATE") {

            const data = msgOBJ.payload;
            
            // Check access rights
            if (selecteddiscipline === 'A') {
                const noten = data.noten;


                if (noten[0][rangNotenId][1] !== undefined && rangNotenArray[data.programmId][data.personId] !== undefined) {
                    rangNotenArray[data.programmId][data.personId] = noten[0][rangNotenId][1];
                    applyRanks(rankProgramm(rangNotenArray, data.programmId, rangSort), true);
                }
            }
        }
    });

    function rankProgramm(dataObj, programmId, order = 'DESC') {
        if (!dataObj[programmId]) {
            console.error(`ID ${programmId} not found in data.`);
            return [];
        }

        const values = dataObj[programmId];

        // 1. Transform and Sort
        const sorted = Object.entries(values)
            .map(([id, val]) => ({ id, val }))
            .sort((a, b) => {
                // 1. Handle null values first (Always push them to the bottom)
                if (a.val === null && b.val === null) return 0;
                if (a.val === null) return 1;  // Move 'a' to a higher index (down)
                if (b.val === null) return -1; // Move 'b' to a higher index (down)

                // 2. Normal sorting logic for valid numbers
                return order.toUpperCase() === 'ASC' 
                    ? a.val - b.val 
                    : b.val - a.val;
            });

        let lastVal = null;
        let lastRank = 0;

        let sortedMap = [];

        sortedMap[programmId] = sorted.map((item, index) => {
            // If current value is different from the last, update rank to current position
            if (item.val !== lastVal) {
                lastRank = index + 1;
            }
            
            lastVal = item.val;
            
            return {
                rang: lastRank,
                ...item
            };
        });

        return sortedMap;
    }
    

    function rankAll(dataObj, order = 'DESC') {
        return Object.fromEntries(
            Object.entries(dataObj).map(([groupKey, values]) => {
                const sorted = Object.entries(values)
                    .map(([id, val]) => ({ id, val }))
                    .sort((a, b) => {
                        // 1. Handle null values first (Always push them to the bottom)
                        if (a.val === null && b.val === null) return 0;
                        if (a.val === null) return 1;  // Move 'a' to a higher index (down)
                        if (b.val === null) return -1; // Move 'b' to a higher index (down)

                        // 2. Normal sorting logic for valid numbers
                        return order.toUpperCase() === 'ASC' 
                            ? a.val - b.val 
                            : b.val - a.val;
                    });

                let lastVal = null;
                let lastRank = 0;

                const ranked = sorted.map((item, index) => {
                    if (item.val !== lastVal) {
                        lastRank = index + 1;
                    }
                    lastVal = item.val;
                    
                    return {
                        rang: lastRank,
                        ...item
                    };
                });

                return [groupKey, ranked];
            })
        );
    }

    function applyRanks(array, sort = false) {
        for (const [key, entries] of Object.entries(array)) {
            const $tbody = $(`.customDisplayEditorTable tbody[data-programm-id="${key}"]`);
            
            if ($tbody.length === 0) continue; 

            for (const [skey, entry] of Object.entries(entries)) {
                const $row = $tbody.find(`tr[data-person-id="${entry.id}"]:not(.notpaid)`);

                if ($row.length === 0) continue; 

                $row.attr('data-sort-rank', entry.rang);

                const $cell = $row.find('.rangField');

                const points = parseFloat(rangNotenArray[key][entry.id]);

                const text = !isNaN(points) ? entry.rang : '';
                
                $cell.text(text);
            }

            if (sort) {
                const rows = $tbody.find('tr').get();

                rows.sort((a, b) => {
                    const rankA = parseFloat($(a).attr('data-sort-rank')) || 999;
                    const rankB = parseFloat($(b).attr('data-sort-rank')) || 999;
                    return rankA - rankB;
                });

                $.each(rows, (index, row) => {
                    $tbody.append(row);
                });
            }
        }
    }

    applyRanks(rankAll(rangNotenArray, rangSort), true);

    window.addEventListener('valueChanged', (e) => {
        // Use e.detail to get your object
        const { noten, programmId, personId } = e.detail;

        if (noten[0][rangNotenId][1] !== undefined && rangNotenArray[programmId][personId] !== undefined) {
            rangNotenArray[programmId][personId] = noten[0][rangNotenId][1];
            applyRanks(rankProgramm(rangNotenArray, programmId, rangSort), true);
        }
    });

    const $parent = $('.allAbtContainer');
    const $children = $parent.children('.shiftedGeraetTable');

    $children.sort((a, b) => {
        const idA = parseFloat($(a).data('geraet-index'));
        const idB = parseFloat($(b).data('geraet-index'));
        
        return idA - idB;
    });

    $parent.append($children);

    const wsMessage = window.WS_MESSAGE || '';

    if (wsMessage !== '') {
        ws.addEventListener('open', () => {
            setTimeout(() => {
                ws.send(wsMessage);
            }, 300);
        });
    }

    $('.deleteNotenAbt').on('click', async function () {
        if (!(await displayConfirmImportant('Alle Noten dieses Programmes wirklich löschen? Diese Aktion ist unumkehrbar!'))) return;

        const $btn = $(this);

        const programmId = parseInt($btn.data('programm-id') || 0);

        $.ajax({
            url: '/intern/scripts/kampfrichter/ajax/ajax-delete-noten-turnerinnen.php',
            type: 'DELETE',
            data: {
                csrf_token,
                programmId
            },
            success: function (response) {
                if (response.success) {
                    const $tbody = $btn.closest('.singleAbtDiv').find('tbody');

                    if ($tbody.length !== 1 || $tbody.data('programm-id') !== programmId) {
                        location.reload();
                        return;
                    }

                    const $allValues = $tbody.find('.changebleValue:not(.emtyPlaceholder)');

                    $allValues.each((ind, el) => {
                        $(el).text('-').addClass('emtyPlaceholder');
                        updateDependentVisibility($(el));
                    });

                    const $allRanks = $tbody.find('.rangField');

                    $allRanks.each((ind, el) => {
                        $(el).text('');
                    });

                    const $allRows = $tbody.find('tr');

                    $allRows.each((ind, el) => {
                        $(el).attr('data-sort-rank', "0");
                        rangNotenArray[programmId][$(el).attr('data-person-id')] = null;
                    });

                    displayMsg(1, 'Noten gelöscht');

                } else {
                    displayMsg(0, response.message || 'Fehler beim Löschen');
                }
            },
            error: function () {
                displayMsg(0, 'Fehler beim Löschen');
            }
        })
    });
});