/**
 * Admin floor overview for table reservations.
 */
(function () {
    'use strict';

    var config = window.macaMenulistAdminBookingFloor || {};
    var strings = config.strings || {};
    var root = document.getElementById('maca-booking-floor');

    function appendAuth(body) {
        body.append('nonce', config.nonce || '');
    }

    if (!root) {
        return;
    }

    var dateInput = root.querySelector('.maca-booking-floor-date');
    var timeRange = root.querySelector('.maca-booking-floor-time');
    var timeLabel = document.getElementById('maca-booking-floor-time-label');
    var summaryEl = document.getElementById('maca-booking-floor-summary');
    var dayOccupancyEl = document.getElementById('maca-booking-floor-day-occupancy');
    var messageEl = document.getElementById('maca-booking-floor-message');
    var gridEl = document.getElementById('maca-booking-floor-grid');
    var queueEl = document.getElementById('maca-booking-floor-queue');
    var queueListEl = document.getElementById('maca-booking-floor-queue-list');

    var slots = [];
    var loadToken = 0;
    var activeDrag = null;
    var bookingsDayLink = document.getElementById('maca-booking-floor-link-bookings');

    function updateBookingsDayLink() {
        if (!bookingsDayLink || !dateInput || !config.bookingsListUrl) {
            return;
        }

        var separator = config.bookingsListUrl.indexOf('?') === -1 ? '?' : '&';
        bookingsDayLink.href =
            config.bookingsListUrl +
            separator +
            'booking_date=' +
            encodeURIComponent(dateInput.value || config.today || '');
    }

    function clampDate(value) {
        if (!value) {
            return config.today || '';
        }
        if (config.minDate && value < config.minDate) {
            return config.minDate;
        }
        if (config.maxDate && value > config.maxDate) {
            return config.maxDate;
        }
        return value;
    }

    function postFloor(data) {
        var body = new FormData();
        body.append('action', 'maca_admin_booking_floor');
        appendAuth(body);
        Object.keys(data).forEach(function (key) {
            body.append(key, data[key]);
        });

        return fetch(config.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: body
        }).then(function (response) {
            return response.json();
        });
    }

    function setMessage(text, isError) {
        if (!messageEl) {
            return;
        }
        messageEl.textContent = text || '';
        messageEl.className = 'maca-booking-floor-message' + (isError ? ' is-error' : '');
    }

    function setSummary(text) {
        if (summaryEl) {
            summaryEl.textContent = text || '';
        }
    }

    function occupancyLevelClass(percent) {
        if (percent >= 90) {
            return 'maca-booking-occupancy-high';
        }
        if (percent >= 70) {
            return 'maca-booking-occupancy-medium';
        }
        return 'maca-booking-occupancy-low';
    }

    function updateDayOccupancy(dayOccupancy) {
        if (!dayOccupancyEl) {
            return;
        }

        var data = dayOccupancy || {};
        var capacity = parseInt(data.peak_capacity, 10) || 0;
        var unavailable = strings.dayOccupancyUnavailable || '—';

        if (capacity <= 0) {
            dayOccupancyEl.textContent = unavailable;
            dayOccupancyEl.className =
                'maca-booking-floor-day-occupancy maca-booking-occupancy maca-booking-occupancy-low';
            dayOccupancyEl.removeAttribute('title');
            return;
        }

        var percent = parseInt(data.percent, 10) || 0;
        var booked = parseInt(data.booked_seats, 10) || 0;
        var text = strings.dayOccupancy || '%1$d%% (%2$d / %3$d)';

        dayOccupancyEl.textContent = text
            .replace('%1$d', String(percent))
            .replace('%2$d', String(booked))
            .replace('%3$d', String(capacity))
            .replace(/%%/g, '%');
        dayOccupancyEl.className =
            'maca-booking-floor-day-occupancy maca-booking-occupancy ' + occupancyLevelClass(percent);

        if (strings.dayOccupancyLabel) {
            dayOccupancyEl.setAttribute(
                'title',
                strings.dayOccupancyLabel + ': ' + booked + ' / ' + capacity
            );
        }
    }

    function applyFloorPayload(data) {
        if (!data) {
            return;
        }

        if (data.day_occupancy) {
            updateDayOccupancy(data.day_occupancy);
        } else if (data.status && data.status.day_occupancy) {
            updateDayOccupancy(data.status.day_occupancy);
        }
    }

    function setGridLoading() {
        if (!gridEl) {
            return;
        }
        clearDragState();
        gridEl.setAttribute('aria-busy', 'true');
        gridEl.innerHTML = '<p class="maca-booking-floor-loading">' + (strings.loading || 'Laddar…') + '</p>';
    }

    function escapeHtml(text) {
        var div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    function getFloorTime() {
        if (!timeRange || !slots.length) {
            return '';
        }

        var index = parseInt(timeRange.value, 10);
        if (isNaN(index) || index < 0) {
            index = 0;
        }
        if (index >= slots.length) {
            index = slots.length - 1;
        }

        return slots[index] || '';
    }

    function moveBooking(bookingId, tableId, splitSlot) {
        var body = new FormData();
        var floorTime = getFloorTime();

        body.append('action', 'maca_admin_move_booking');
        appendAuth(body);
        body.append('booking_id', String(bookingId));
        body.append('table_id', String(tableId));
        if (splitSlot) {
            body.append('split_slot', splitSlot);
        }
        if (floorTime) {
            body.append('floor_time', floorTime);
        }

        return fetch(config.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: body
        }).then(function (response) {
            return response.json();
        });
    }

    function clearDragState() {
        activeDrag = null;
        if (!gridEl) {
            return;
        }
        gridEl.classList.remove('is-floor-drag-active');
        gridEl.querySelectorAll('.maca-booking-floor-card').forEach(function (card) {
            card.classList.remove('is-dragging', 'is-drop-target', 'is-drag-over');
        });
    }

    function parseMoveTargets(raw) {
        if (!raw) {
            return [];
        }

        var targets = [];
        var parts = String(raw).split(',');
        var i;
        var bits;
        var id;
        var slot;
        var key;

        for (i = 0; i < parts.length; i += 1) {
            bits = parts[i].trim().split(':');
            id = parseInt(bits[0], 10);
            slot = bits[1] ? bits[1].trim() : '';
            if (id > 0) {
                key = id + ':' + slot;
                if (!targets.some(function (t) { return t.key === key; })) {
                    targets.push({ id: id, slot: slot, key: key });
                }
            }
        }

        return targets;
    }

    function targetMatches(targets, tableId, splitSlot) {
        splitSlot = splitSlot || '';
        return targets.some(function (t) {
            return t.id === tableId && (t.slot || '') === splitSlot;
        });
    }

    function tableDayAction(action, tableId, dayLayout) {
        if (!dateInput || !tableId) {
            return Promise.resolve({ success: false });
        }

        var body = new FormData();
        body.append('action', action);
        appendAuth(body);
        body.append('table_id', String(tableId));
        body.append('booking_date', dateInput.value || config.today || '');
        if (dayLayout) {
            body.append('day_layout', dayLayout);
        }

        return fetch(config.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: body
        }).then(function (response) {
            return response.json();
        });
    }

    function getDropCard(target) {
        if (!gridEl || !target || !target.closest || !activeDrag) {
            return null;
        }

        var card = target.closest('.maca-booking-floor-card');
        if (!card || !gridEl.contains(card) || !card.classList.contains('is-drop-target')) {
            return null;
        }

        return card;
    }

    function highlightDropCard(card) {
        if (!gridEl) {
            return;
        }

        gridEl.querySelectorAll('.maca-booking-floor-card.is-drag-over').forEach(function (el) {
            el.classList.remove('is-drag-over');
        });

        if (card) {
            card.classList.add('is-drag-over');
        }
    }

    function renderQueue(queue, floorOpen) {
        if (!queueEl || !queueListEl) {
            return;
        }

        queue = queue || [];

        if (!floorOpen) {
            queueEl.hidden = true;
            queueListEl.innerHTML = '';
            return;
        }

        queueEl.hidden = false;

        if (!queue.length) {
            queueListEl.innerHTML =
                '<p class="maca-booking-floor-queue-empty">' +
                escapeHtml(strings.queueEmpty || 'Inga väntande eller väntlista.') +
                '</p>';
            return;
        }

        var html = '';
        var i;
        var block;

        for (i = 0; i < queue.length; i += 1) {
            block = renderBookingBlock(queue[i]);
            html +=
                '<div class="maca-booking-floor-queue-item maca-booking-floor-queue-item-' +
                escapeHtml(queue[i].status || 'pending') +
                '">' +
                block.html +
                (config.bookingUrl && queue[i].id
                    ? '<a class="button button-link maca-booking-floor-queue-view" href="' +
                      escapeHtml(config.bookingUrl + '&booking_id=' + queue[i].id) +
                      '">' +
                      escapeHtml(strings.viewBooking || 'Visa bokning') +
                      '</a>'
                    : '') +
                '</div>';
        }

        queueListEl.innerHTML = html;
    }

    function initDragDrop() {
        if (!root || !gridEl || root.dataset.macaDragBound === '1') {
            return;
        }

        root.dataset.macaDragBound = '1';

        root.addEventListener('dragstart', function (event) {
            var handle = event.target.closest('.maca-booking-floor-drag');
            if (!handle) {
                return;
            }

            var bookingId = parseInt(handle.getAttribute('data-booking-id'), 10);
            var targets = parseMoveTargets(handle.getAttribute('data-move-targets'));

            if (!bookingId || !targets.length) {
                event.preventDefault();
                return;
            }

            activeDrag = {
                bookingId: bookingId,
                targets: targets,
                sourceCard: handle.closest('.maca-booking-floor-card')
            };

            if (event.dataTransfer) {
                event.dataTransfer.effectAllowed = 'move';
                event.dataTransfer.setData('text/plain', String(bookingId));
                try {
                    event.dataTransfer.setData('application/x-maca-booking-id', String(bookingId));
                } catch (e) {
                    /* ignore */
                }
            }

            if (activeDrag.sourceCard) {
                activeDrag.sourceCard.classList.add('is-dragging');
            }

            gridEl.classList.add('is-floor-drag-active');

            gridEl.querySelectorAll('.maca-booking-floor-card').forEach(function (card) {
                var tableId = parseInt(card.getAttribute('data-table-id'), 10);
                var slot = card.getAttribute('data-split-slot') || '';
                if (targetMatches(targets, tableId, slot)) {
                    card.classList.add('is-drop-target');
                }
            });
        });

        root.addEventListener('dragend', function () {
            clearDragState();
        });

        gridEl.addEventListener('dragenter', function (event) {
            if (!activeDrag) {
                return;
            }

            var card = getDropCard(event.target);
            if (!card) {
                return;
            }

            event.preventDefault();
            highlightDropCard(card);
        });

        gridEl.addEventListener('dragover', function (event) {
            if (!activeDrag) {
                return;
            }

            var card = getDropCard(event.target);
            if (!card) {
                return;
            }

            event.preventDefault();
            if (event.dataTransfer) {
                event.dataTransfer.dropEffect = 'move';
            }
            highlightDropCard(card);
        });

        gridEl.addEventListener('dragleave', function (event) {
            if (!activeDrag) {
                return;
            }

            var card = getDropCard(event.target);
            var related = event.relatedTarget;

            if (card && related && card.contains(related)) {
                return;
            }

            highlightDropCard(null);
        });

        gridEl.addEventListener('drop', function (event) {
            if (!activeDrag) {
                return;
            }

            var card = getDropCard(event.target);
            if (!card) {
                return;
            }

            event.preventDefault();
            event.stopPropagation();

            var tableId = parseInt(card.getAttribute('data-table-id'), 10);
            var splitSlot = card.getAttribute('data-split-slot') || '';
            var bookingId = activeDrag.bookingId;

            if (!tableId || !targetMatches(activeDrag.targets, tableId, splitSlot)) {
                clearDragState();
                setMessage(
                    strings.dropFailed ||
                        'Kunde inte placera här. Kontrollera att bordet är ledigt vid vald tid.',
                    true
                );
                return;
            }

            clearDragState();
            setMessage(strings.moving || 'Flyttar…', false);
            gridEl.setAttribute('aria-busy', 'true');

            moveBooking(bookingId, tableId, splitSlot)
                .then(function (result) {
                    if (!result.success) {
                        setMessage(
                            result.data && result.data.message ? result.data.message : strings.error,
                            true
                        );
                        gridEl.setAttribute('aria-busy', 'false');
                        return;
                    }

                    setMessage(result.data.message || strings.moveSuccess, false);
                    loadStatus();
                })
                .catch(function () {
                    setMessage(strings.error, true);
                    gridEl.setAttribute('aria-busy', 'false');
                });
        });
    }

    function renderSeatSlots(seatSlots, hasBookings) {
        var html = '';
        var s;
        var i;
        var slot;
        var capacity;
        var occupied;
        var seatClass;

        if (!seatSlots || !seatSlots.length) {
            return html;
        }

        for (s = 0; s < seatSlots.length; s += 1) {
            slot = seatSlots[s];
            if (s > 0) {
                html += '<span class="maca-booking-floor-seat-gap" aria-hidden="true"></span>';
            }

            capacity = Math.max(0, parseInt(slot.capacity, 10) || 0);
            occupied = Math.max(0, Math.min(capacity, parseInt(slot.occupied, 10) || 0));

            for (i = 0; i < capacity; i += 1) {
                if (i < occupied) {
                    seatClass = 'maca-booking-floor-seat maca-booking-floor-seat-occupied';
                } else if (hasBookings) {
                    seatClass = 'maca-booking-floor-seat maca-booking-floor-seat-shareable';
                } else {
                    seatClass = 'maca-booking-floor-seat maca-booking-floor-seat-available';
                }
                html += '<span class="' + seatClass + '" aria-hidden="true"></span>';
            }
        }

        return html;
    }

    function getTableBookings(table) {
        if (table.bookings && table.bookings.length) {
            return table.bookings;
        }
        if (table.booking) {
            return [table.booking];
        }
        return [];
    }

    function renderBookingBlock(booking) {
        var hasTargets = (booking.move_targets || []).length > 0;
        var canAssign = booking.can_assign !== false && hasTargets;
        var canMove =
            (booking.status === 'pending' ||
                booking.status === 'confirmed' ||
                booking.status === 'waitlist') &&
            canAssign;
        var moveTargetIds = (booking.move_targets || []).map(function (t) {
            var key = String(t.id);
            if (t.split_slot) {
                key += ':' + t.split_slot;
            }
            return key;
        });
        var html = '';

        if (canMove) {
            html +=
                '<div class="maca-booking-floor-card-booking maca-booking-floor-drag" draggable="true"' +
                ' data-booking-id="' +
                String(booking.id) +
                '"' +
                ' data-move-targets="' +
                moveTargetIds.join(',') +
                '"' +
                ' title="' +
                escapeHtml(strings.dragHint || '') +
                '">';
        } else {
            html += '<div class="maca-booking-floor-card-booking">';
        }

        html +=
            '<p class="maca-booking-floor-card-guest">' +
            escapeHtml(booking.guest_name) +
            '</p>' +
            '<p class="maca-booking-floor-card-meta">' +
            escapeHtml(String(booking.party_size)) +
            ' ' +
            escapeHtml(strings.guests || 'gäster') +
            '</p>';

        if (booking.status === 'waitlist' && booking.requested_time) {
            html +=
                '<p class="maca-booking-floor-card-meta maca-booking-floor-card-requested-time">' +
                escapeHtml((strings.requestedTime || 'Önskad tid') + ': ' + booking.requested_time) +
                '</p>';
        } else {
            html +=
                '<p class="maca-booking-floor-card-meta">' +
                escapeHtml(booking.booking_time || booking.requested_time || '') +
                '</p>';
        }

        if (booking.status === 'pending' || booking.status === 'waitlist') {
            html +=
                '<p class="maca-booking-floor-card-status maca-booking-floor-card-status-pending">' +
                escapeHtml(
                    booking.status_label ||
                        (booking.status === 'waitlist' ? strings.waitlist : strings.pending) ||
                        'väntande'
                ) +
                '</p>';
        }

        if (
            canAssign &&
            booking.status === 'waitlist' &&
            booking.requested_time &&
            !booking.at_requested_time &&
            booking.placement_time
        ) {
            html +=
                '<p class="maca-booking-floor-card-status maca-booking-floor-card-status-place-hint">' +
                escapeHtml(
                    (strings.placeAtTime || 'Placeras kl. %s').replace('%s', booking.placement_time)
                ) +
                '</p>';
        }

        if (!canAssign && (booking.status === 'pending' || booking.status === 'waitlist')) {
            html +=
                '<p class="maca-booking-floor-card-status maca-booking-floor-card-status-muted">' +
                escapeHtml(strings.queueNoTables || 'Inga lediga bord vid vald tid på skjutreglaget.') +
                '</p>';
        }

        html += '</div>';

        return {
            html: html,
            canMove: canMove
        };
    }

    function renderGrid(status) {
        if (!gridEl) {
            return;
        }

        clearDragState();
        gridEl.setAttribute('aria-busy', 'false');

        if (!status || status.closed) {
            gridEl.innerHTML = '';
            renderQueue([], false);
            setSummary('');
            setMessage(status && status.message ? status.message : strings.closed, false);
            return;
        }

        setMessage('', false);

        var tables = status.tables || [];
        var summary = status.summary || {};

        if (strings.summary && summary.total !== undefined) {
            setSummary(
                strings.summary
                    .replace('%1$d', String(summary.available || 0))
                    .replace('%2$d', String(summary.partial !== undefined ? summary.partial : 0))
                    .replace('%3$d', String(summary.full !== undefined ? summary.full : summary.occupied || 0))
                    .replace('%4$d', String(summary.total || 0))
            );
        }

        if (!tables.length) {
            gridEl.innerHTML = '<p class="maca-booking-floor-empty">' + escapeHtml(strings.closed || '') + '</p>';
            renderQueue(status.queue || [], true);
            return;
        }

        var html = '';

        tables.forEach(function (table) {
            var isEmpty = !!table.is_empty || !!table.available;
            var isPartial = !!table.is_partial;
            var isFull = !!table.is_full;
            var isSplittable = !!table.is_splittable;
            var isSplitPart = !!table.is_split_part;
            var splitSlot = table.split_slot || '';
            var canSplitDay = !!table.can_split_day;
            var canManageDaySplit = !!table.can_manage_day_split;
            var canUnsplitDay = !!table.can_unsplit_day;
            var dayLayoutPresets = table.day_layout_presets || [];
            var daySplitLayout = table.day_split_layout || '';
            var daySplitLayoutValue = table.day_split_layout_value || '';
            var splitLayout = table.split_layout || '';
            var totalSeats = Math.max(0, parseInt(table.seats, 10) || 0);
            var occupiedSeats = Math.max(0, parseInt(table.occupied_seats, 10) || 0);
            var bookings = getTableBookings(table);
            var hasBookings = bookings.length > 0;
            var cardClass = 'maca-booking-floor-card';
            var statusText = strings.available || 'Ledigt';
            var bookingHtml = '';
            var actionsHtml = '';
            var dragHintHtml = '';
            var dropHintHtml = '';
            var anyCanMove = false;
            var i;
            var block;

            if (isSplittable) {
                cardClass += ' is-splittable';
            }

            if (isSplitPart) {
                cardClass += ' is-split-part';
            }

            if (isEmpty) {
                cardClass += ' is-available is-empty is-floor-bookable';
            } else if (isPartial) {
                cardClass += ' is-partial is-floor-bookable';
                statusText = strings.shareable || 'Kan delas';
                if (strings.partialOccupied) {
                    statusText =
                        strings.partialOccupied
                            .replace('%1$d', String(occupiedSeats))
                            .replace('%2$d', String(totalSeats)) +
                        ' · ' +
                        statusText;
                }
            } else {
                cardClass += ' is-full is-occupied';
                statusText = strings.occupied || 'Upptaget';
            }

            if (isEmpty) {
                dropHintHtml =
                    '<p class="maca-booking-floor-book-hint">' +
                    escapeHtml(strings.bookClickHint || 'Klicka för att lägga bokning här') +
                    '</p>' +
                    '<p class="maca-booking-floor-drop-hint">' +
                    escapeHtml(strings.dropHint || 'Släpp här för att flytta bokningen') +
                    '</p>';
            } else if (isPartial) {
                dropHintHtml =
                    '<p class="maca-booking-floor-book-hint">' +
                    escapeHtml(strings.bookClickHintShare || 'Klicka för att lägga till bokning på bordet') +
                    '</p>' +
                    '<p class="maca-booking-floor-drop-hint maca-booking-floor-drop-hint-share">' +
                    escapeHtml(strings.dropHintShare || 'Släpp här för att lägga till på bordet') +
                    '</p>';
            }

            for (i = 0; i < bookings.length; i += 1) {
                block = renderBookingBlock(bookings[i]);
                bookingHtml += block.html;
                if (block.canMove) {
                    anyCanMove = true;
                }

                if (config.bookingUrl && bookings[i].id) {
                    actionsHtml +=
                        '<div class="maca-booking-floor-card-actions">' +
                        '<a class="button button-secondary maca-booking-floor-btn-view" href="' +
                        escapeHtml(config.bookingUrl + '&booking_id=' + bookings[i].id) +
                        '">' +
                        escapeHtml(strings.viewBooking || 'Visa bokning') +
                        '</a>' +
                        '</div>';
                }
            }

            if (anyCanMove) {
                dragHintHtml =
                    '<p class="maca-booking-floor-drag-hint">' +
                    escapeHtml(strings.dragHint || 'Dra till grönt (ledigt) eller orange (dela bord) bord.') +
                    '</p>';
            } else if (hasBookings) {
                dragHintHtml =
                    '<p class="maca-booking-floor-drag-hint maca-booking-floor-drag-hint-muted">' +
                    escapeHtml(strings.noMoveTargets || 'Inga andra bord med plats vid denna tid.') +
                    '</p>';
            }

            if (canManageDaySplit && dayLayoutPresets.length) {
                actionsHtml +=
                    '<div class="maca-booking-floor-card-actions maca-booking-floor-card-actions-split">' +
                    (daySplitLayout
                        ? '<p class="description maca-booking-floor-day-split-active">' +
                          escapeHtml(
                              (strings.daySplitActive || 'Idag: %s').replace('%s', daySplitLayout)
                          ) +
                          '</p>'
                        : '') +
                    '<label class="maca-booking-floor-day-split-label">' +
                    '<span class="screen-reader-text">' +
                    escapeHtml(strings.daySplitLayout || 'Delning för dagen') +
                    '</span>' +
                    '<select class="maca-booking-floor-day-split-select" data-floor-day-split-select="' +
                    escapeHtml(String(table.id)) +
                    '">';

                dayLayoutPresets.forEach(function (preset) {
                    var selected =
                        daySplitLayoutValue && preset.value === daySplitLayoutValue ? ' selected' : '';
                    if (!daySplitLayoutValue && preset.value === 'default' && !canUnsplitDay) {
                        selected = ' selected';
                    }
                    actionsHtml +=
                        '<option value="' +
                        escapeHtml(preset.value) +
                        '"' +
                        selected +
                        '>' +
                        escapeHtml(preset.label) +
                        '</option>';
                });

                actionsHtml += '</select></label> ';

                if (canSplitDay) {
                    actionsHtml +=
                        '<button type="button" class="button button-secondary" data-floor-split-day="' +
                        escapeHtml(String(table.id)) +
                        '">' +
                        escapeHtml(strings.splitDay || 'Dela för vald dag') +
                        '</button> ';
                } else {
                    actionsHtml +=
                        '<button type="button" class="button button-secondary" data-floor-split-day="' +
                        escapeHtml(String(table.id)) +
                        '">' +
                        escapeHtml(strings.updateDaySplit || 'Uppdatera delning') +
                        '</button> ';
                }

                if (canUnsplitDay) {
                    actionsHtml +=
                        '<button type="button" class="button button-link" data-floor-unsplit-day="' +
                        escapeHtml(String(table.id)) +
                        '">' +
                        escapeHtml(strings.unsplitDay || 'Helt bord denna dag') +
                        '</button>';
                }

                actionsHtml += '</div>';
            }

            html +=
                '<article class="' +
                cardClass +
                '" data-table-id="' +
                escapeHtml(String(table.id)) +
                '" data-split-slot="' +
                escapeHtml(splitSlot) +
                '" aria-label="' +
                escapeHtml((strings.table || 'Bord') + ' ' + table.table_number + ', ' + statusText) +
                '">' +
                '<header class="maca-booking-floor-card-header">' +
                '<strong class="maca-booking-floor-card-title">' +
                escapeHtml((strings.table || 'Bord') + ' ' + table.table_number) +
                (isSplittable && splitLayout && !isSplitPart
                    ? '<span class="maca-booking-floor-card-badge">' +
                      escapeHtml(
                          (strings.splittableBadge || 'Delningsbart %s').replace('%s', splitLayout)
                      ) +
                      '</span>'
                    : '') +
                '</strong>' +
                '<span class="maca-booking-floor-card-seats">' +
                escapeHtml(String(table.seats) + ' ' + (strings.seats || 'platser')) +
                (hasBookings && strings.bookingCount
                    ? ' · ' +
                      escapeHtml(
                          strings.bookingCount
                              .replace('%1$d', String(table.booking_count || bookings.length))
                              .replace(
                                  '%2$d',
                                  String(table.max_bookings || config.maxBookingsPerTable || 4)
                              )
                      )
                    : '') +
                '</span>' +
                '</header>' +
                '<div class="maca-booking-floor-card-chairs">' +
                renderSeatSlots(table.seat_slots, hasBookings) +
                '</div>' +
                dropHintHtml +
                bookingHtml +
                dragHintHtml +
                actionsHtml +
                '</article>';
        });

        gridEl.innerHTML = html;
        renderQueue(status.queue || [], true);
        clearBookSelection();
        if (pendingTableKey) {
            var cards = gridEl.querySelectorAll('.maca-booking-floor-card');
            var c;
            var key;
            for (c = 0; c < cards.length; c += 1) {
                key =
                    cards[c].getAttribute('data-table-id') +
                    (cards[c].getAttribute('data-split-slot')
                        ? ':' + cards[c].getAttribute('data-split-slot')
                        : '');
                if (key === pendingTableKey) {
                    cards[c].classList.add('is-floor-book-selected');
                    break;
                }
            }
        }
    }

    function updateTimeUi() {
        if (!timeRange || !timeLabel) {
            return;
        }

        if (!slots.length) {
            timeRange.disabled = true;
            timeRange.max = 0;
            timeRange.value = 0;
            timeLabel.textContent = '—';
            return;
        }

        var index = parseInt(timeRange.value, 10);
        if (isNaN(index) || index < 0) {
            index = 0;
        }
        if (index >= slots.length) {
            index = slots.length - 1;
        }

        timeRange.disabled = false;
        timeRange.min = 0;
        timeRange.max = Math.max(0, slots.length - 1);
        timeRange.value = String(index);
        timeLabel.textContent = slots[index];
    }

    function pickDefaultSlotIndex() {
        if (!slots.length) {
            return 0;
        }

        var today = config.today || '';
        var date = dateInput ? dateInput.value : '';

        if (date !== today) {
            return 0;
        }

        var now = new Date();
        var nowMinutes = now.getHours() * 60 + now.getMinutes();
        var bestIndex = 0;
        var bestDiff = Infinity;
        var i;

        for (i = 0; i < slots.length; i += 1) {
            var parts = slots[i].split(':');
            var slotMinutes = parseInt(parts[0], 10) * 60 + parseInt(parts[1], 10);
            var diff = Math.abs(slotMinutes - nowMinutes);

            if (diff < bestDiff) {
                bestDiff = diff;
                bestIndex = i;
            }
        }

        return bestIndex;
    }

    function loadStatus() {
        if (!dateInput || !slots.length) {
            setGridLoading();
            renderGrid({ closed: true, message: strings.closed });
            return;
        }

        var token = ++loadToken;
        var date = dateInput.value;
        var index = timeRange ? parseInt(timeRange.value, 10) : 0;
        var time = slots[index] || slots[0];

        setGridLoading();
        setMessage('', false);

        postFloor({
            booking_date: date,
            booking_time: time
        }).then(function (result) {
            if (token !== loadToken) {
                return;
            }

            if (!result.success) {
                setMessage(result.data && result.data.message ? result.data.message : strings.error, true);
                gridEl.innerHTML = '';
                gridEl.setAttribute('aria-busy', 'false');
                return;
            }

            if (result.data.slots && result.data.slots.length) {
                slots = result.data.slots;
                updateTimeUi();
            }

            applyFloorPayload(result.data);
            renderGrid(result.data.status);
        }).catch(function () {
            if (token !== loadToken) {
                return;
            }
            setMessage(strings.error, true);
            gridEl.innerHTML = '';
            gridEl.setAttribute('aria-busy', 'false');
        });
    }

    function loadSlots() {
        if (!dateInput) {
            return;
        }

        var token = ++loadToken;
        var date = clampDate(dateInput.value);

        if (dateInput.value !== date) {
            dateInput.value = date;
        }

        setGridLoading();
        setMessage('', false);
        setSummary('');

        postFloor({ booking_date: date }).then(function (result) {
            if (token !== loadToken) {
                return;
            }

            if (!result.success) {
                slots = [];
                updateTimeUi();
                setMessage(result.data && result.data.message ? result.data.message : strings.error, true);
                renderGrid({ closed: true, message: '' });
                return;
            }

            slots = result.data.slots || [];
            updateTimeUi();
            applyFloorPayload(result.data);

            if (!slots.length) {
                renderGrid({ closed: true, message: strings.closed });
                return;
            }

            if (timeRange) {
                timeRange.value = String(pickDefaultSlotIndex());
                updateTimeUi();
            }

            loadStatus();
        }).catch(function () {
            if (token !== loadToken) {
                return;
            }
            slots = [];
            updateTimeUi();
            setMessage(strings.error, true);
            renderGrid({ closed: true, message: '' });
        });
    }

    if (dateInput) {
        if (config.minDate) {
            dateInput.min = config.minDate;
        }
        if (config.maxDate) {
            dateInput.max = config.maxDate;
        }

        dateInput.addEventListener('change', function () {
            updateBookingsDayLink();
            loadSlots();
        });
        updateBookingsDayLink();
    }

    if (timeRange) {
        timeRange.addEventListener('input', function () {
            updateTimeUi();
            loadStatus();
        });
    }

    function initFloorActions() {
        if (!gridEl || gridEl.dataset.macaActionsBound === '1') {
            return;
        }

        gridEl.dataset.macaActionsBound = '1';

        gridEl.addEventListener('click', function (event) {
            var splitBtn = event.target.closest('[data-floor-split-day]');
            var unsplitBtn = event.target.closest('[data-floor-unsplit-day]');
            var tableId;
            var action;
            var successMsg;

            if (splitBtn) {
                tableId = parseInt(splitBtn.getAttribute('data-floor-split-day'), 10);
                action = 'maca_admin_split_table_day';
                successMsg = strings.splitDaySuccess || strings.splitDay;
                var selectEl = gridEl.querySelector(
                    '[data-floor-day-split-select="' + String(tableId) + '"]'
                );
                var dayLayout = selectEl ? selectEl.value : 'default';
                event.preventDefault();
                setMessage(strings.loading || 'Laddar…', false);
                gridEl.setAttribute('aria-busy', 'true');

                tableDayAction(action, tableId, dayLayout)
                    .then(function (result) {
                        if (!result.success) {
                            setMessage(
                                result.data && result.data.message ? result.data.message : strings.error,
                                true
                            );
                            gridEl.setAttribute('aria-busy', 'false');
                            return;
                        }

                        setMessage(result.data.message || successMsg, false);
                        loadSlots();
                    })
                    .catch(function () {
                        setMessage(strings.error, true);
                        gridEl.setAttribute('aria-busy', 'false');
                    });
                return;
            } else if (unsplitBtn) {
                tableId = parseInt(unsplitBtn.getAttribute('data-floor-unsplit-day'), 10);
                action = 'maca_admin_unsplit_table_day';
                successMsg = strings.unsplitDaySuccess || strings.unsplitDay;
            } else {
                return;
            }

            if (!tableId) {
                return;
            }

            event.preventDefault();
            setMessage(strings.loading || 'Laddar…', false);
            gridEl.setAttribute('aria-busy', 'true');

            tableDayAction(action, tableId, '')
                .then(function (result) {
                    if (!result.success) {
                        setMessage(
                            result.data && result.data.message ? result.data.message : strings.error,
                            true
                        );
                        gridEl.setAttribute('aria-busy', 'false');
                        return;
                    }

                    setMessage(result.data.message || successMsg, false);
                    loadSlots();
                })
                .catch(function () {
                    setMessage(strings.error, true);
                    gridEl.setAttribute('aria-busy', 'false');
                });
        });
    }

    initDragDrop();
    initFloorActions();

    var addToggle = document.getElementById('maca-booking-floor-add-toggle');
    var addPanel = document.getElementById('maca-booking-floor-add-panel');
    var addForm = document.getElementById('maca-booking-floor-add-form');
    var addCancel = document.getElementById('maca-booking-floor-add-cancel');
    var addTableSelect = document.getElementById('maca-floor-add-table');
    var addPartyInput = document.getElementById('maca-floor-add-party');
    var addNameInput = document.getElementById('maca-floor-add-name');
    var addWaitlistInput = document.getElementById('maca-floor-add-waitlist');
    var addTableRow = document.querySelector('.maca-booking-floor-add-table-row');
    var addDescConfirmed = document.querySelector('.maca-booking-floor-add-desc-confirmed');
    var addDescWaitlist = document.querySelector('.maca-booking-floor-add-desc-waitlist');
    var addEmailLabelConfirmed = document.querySelector('.maca-floor-add-email-label-confirmed');
    var addEmailLabelWaitlist = document.querySelector('.maca-floor-add-email-label-waitlist');
    var pendingTableKey = '';

    function isWaitlistMode() {
        return addWaitlistInput && addWaitlistInput.checked;
    }

    function syncWaitlistAddForm() {
        var waitlist = isWaitlistMode();

        if (addTableRow) {
            addTableRow.hidden = waitlist;
        }
        if (addDescConfirmed) {
            addDescConfirmed.hidden = waitlist;
        }
        if (addDescWaitlist) {
            addDescWaitlist.hidden = !waitlist;
        }
        if (addEmailLabelConfirmed) {
            addEmailLabelConfirmed.hidden = waitlist;
        }
        if (addEmailLabelWaitlist) {
            addEmailLabelWaitlist.hidden = !waitlist;
        }

        if (!waitlist) {
            refreshStaffTableOptions(addTableSelect ? addTableSelect.value : '');
        }
    }

    function clearBookSelection() {
        if (!gridEl) {
            return;
        }

        gridEl.querySelectorAll('.maca-booking-floor-card.is-floor-book-selected').forEach(function (card) {
            card.classList.remove('is-floor-book-selected');
        });
    }

    function setTableSelectValue(key) {
        if (!addTableSelect || !key) {
            return false;
        }

        var i;
        for (i = 0; i < addTableSelect.options.length; i += 1) {
            if (addTableSelect.options[i].value === key) {
                addTableSelect.selectedIndex = i;
                return true;
            }
        }

        return false;
    }

    function getSelectedSlotTime() {
        if (!slots.length) {
            return '';
        }
        var idx = timeRange ? parseInt(timeRange.value, 10) || 0 : 0;
        if (idx < 0 || idx >= slots.length) {
            idx = 0;
        }
        return slots[idx] || '';
    }

    function postStaffBooking(data) {
        var body = new FormData();
        body.append('action', data.action);
        appendAuth(body);
        Object.keys(data).forEach(function (key) {
            if (key !== 'action') {
                body.append(key, data[key]);
            }
        });
        return fetch(config.ajaxUrl, {
            method: 'POST',
            credentials: 'same-origin',
            body: body
        }).then(function (response) {
            return response.json();
        });
    }

    function refreshStaffTableOptions(preferredKey) {
        if (!addTableSelect || !dateInput || isWaitlistMode()) {
            return Promise.resolve();
        }

        var time = getSelectedSlotTime();
        var partySize = addPartyInput ? parseInt(addPartyInput.value, 10) || 2 : 2;
        var keyToSelect = preferredKey || pendingTableKey || '';

        if (!time) {
            addTableSelect.innerHTML =
                '<option value="auto">' + escapeHtml(strings.tableAuto || 'Automatiskt ledigt bord') + '</option>';
            return Promise.resolve();
        }

        return postStaffBooking({
            action: 'maca_admin_staff_booking_tables',
            booking_date: dateInput.value,
            booking_time: time,
            party_size: String(partySize)
        })
            .then(function (result) {
                var html =
                    '<option value="auto">' + escapeHtml(strings.tableAuto || 'Automatiskt ledigt bord') + '</option>';
                var tables = result.success && result.data && result.data.tables ? result.data.tables : [];

                tables.forEach(function (row) {
                    var key = String(row.table_id) + (row.split_slot ? ':' + row.split_slot : '');
                    html +=
                        '<option value="' +
                        escapeHtml(key) +
                        '">' +
                        escapeHtml(row.label) +
                        '</option>';
                });

                addTableSelect.innerHTML = html;

                if (keyToSelect && setTableSelectValue(keyToSelect)) {
                    pendingTableKey = '';
                } else if (keyToSelect) {
                    pendingTableKey = keyToSelect;
                }

                if (!tables.length) {
                    setMessage(strings.noTables || '', true);
                }
            })
            .catch(function () {
                /* ignore */
            });
    }

    function selectTableForStaffBooking(card) {
        if (!card) {
            return;
        }

        var tableId = card.getAttribute('data-table-id') || '';
        var splitSlot = card.getAttribute('data-split-slot') || '';
        var tableKey = tableId + (splitSlot ? ':' + splitSlot : '');

        clearBookSelection();
        card.classList.add('is-floor-book-selected');
        pendingTableKey = tableKey;
        setAddPanelOpen(true);
        setMessage(strings.bookTableSelected || '', false);

        refreshStaffTableOptions(tableKey).then(function () {
            if (addNameInput) {
                addNameInput.focus();
            }
        });

        if (addPanel) {
            addPanel.scrollIntoView({ behavior: 'smooth', block: 'nearest' });
        }
    }

    function setAddPanelOpen(open) {
        if (!addPanel || !addToggle) {
            return;
        }
        addPanel.hidden = !open;
        addToggle.setAttribute('aria-expanded', open ? 'true' : 'false');
        if (open) {
            refreshStaffTableOptions(pendingTableKey);
        } else {
            clearBookSelection();
            pendingTableKey = '';
        }
    }

    if (addToggle && addPanel) {
        addToggle.addEventListener('click', function () {
            setAddPanelOpen(addPanel.hidden);
        });
    }

    if (addCancel) {
        addCancel.addEventListener('click', function () {
            setAddPanelOpen(false);
        });
    }

    if (addWaitlistInput) {
        addWaitlistInput.addEventListener('change', syncWaitlistAddForm);
        syncWaitlistAddForm();
    }

    if (addPartyInput) {
        addPartyInput.addEventListener('change', function () {
            refreshStaffTableOptions(addTableSelect ? addTableSelect.value : '');
        });
        addPartyInput.addEventListener('input', function () {
            refreshStaffTableOptions(addTableSelect ? addTableSelect.value : '');
        });
    }

    if (timeRange) {
        timeRange.addEventListener('input', function () {
            if (addPanel && !addPanel.hidden) {
                refreshStaffTableOptions(addTableSelect ? addTableSelect.value : '');
            }
        });
    }

    function initFloorBookClick() {
        if (!gridEl || gridEl.dataset.macaBookClickBound === '1') {
            return;
        }

        gridEl.dataset.macaBookClickBound = '1';

        gridEl.addEventListener('click', function (event) {
            if (activeDrag) {
                return;
            }

            var card = event.target.closest('.maca-booking-floor-card.is-floor-bookable');
            if (!card || !gridEl.contains(card)) {
                return;
            }

            if (
                event.target.closest(
                    'button, a, select, input, textarea, .maca-booking-floor-drag, .maca-booking-floor-day-split-select'
                )
            ) {
                return;
            }

            event.preventDefault();
            selectTableForStaffBooking(card);
        });
    }

    initFloorBookClick();

    if (addForm) {
        addForm.addEventListener('submit', function (event) {
            event.preventDefault();

            var time = getSelectedSlotTime();
            if (!time || !dateInput) {
                setMessage(strings.closed || strings.error, true);
                return;
            }

            var body = new FormData(addForm);
            body.append('action', 'maca_admin_create_staff_booking');
            appendAuth(body);
            body.append('booking_date', dateInput.value);
            body.append('booking_time', time);
            body.append('table_key', addTableSelect ? addTableSelect.value : 'auto');
            if (document.getElementById('maca-floor-add-send-email') && document.getElementById('maca-floor-add-send-email').checked) {
                body.append('send_email', '1');
            }
            if (addWaitlistInput && addWaitlistInput.checked) {
                body.append('waitlist', '1');
            }

            setMessage(strings.loading || 'Laddar…', false);
            gridEl.setAttribute('aria-busy', 'true');

            fetch(config.ajaxUrl, {
                method: 'POST',
                credentials: 'same-origin',
                body: body
            })
                .then(function (response) {
                    return response.json();
                })
                .then(function (result) {
                    gridEl.setAttribute('aria-busy', 'false');
                    if (!result.success) {
                        setMessage(result.data && result.data.message ? result.data.message : strings.error, true);
                        return;
                    }

                    setMessage(result.data.message || strings.bookingSaved || '', false);
                    addForm.reset();
                    if (addPartyInput) {
                        addPartyInput.value = '2';
                    }
                    setAddPanelOpen(false);
                    loadStatus();
                })
                .catch(function () {
                    gridEl.setAttribute('aria-busy', 'false');
                    setMessage(strings.error, true);
                });
        });
    }

    loadSlots();
})();
