(() => {
    const menu = document.getElementById('hamburger-menu');
    const backdrop = document.getElementById('menu-backdrop');
    const button = document.getElementById('hamburger-btn');

    const closeMenu = () => {
        if (!menu || !backdrop || !button) {
            return;
        }
        menu.hidden = true;
        backdrop.hidden = true;
        button.setAttribute('aria-expanded', 'false');
    };

    const openMenu = () => {
        if (!menu || !backdrop || !button) {
            return;
        }
        menu.hidden = false;
        backdrop.hidden = false;
        button.setAttribute('aria-expanded', 'true');
    };

    button?.addEventListener('click', () => {
        if (menu?.hidden) {
            openMenu();
        } else {
            closeMenu();
        }
    });
    backdrop?.addEventListener('click', closeMenu);

    const otpBoxes = document.querySelectorAll('[data-otp-boxes] .otp-box');
    const otpHidden = document.getElementById('otp-value');
    const syncOtp = () => {
        if (otpHidden) {
            otpHidden.value = Array.from(otpBoxes).map((input) => input.value).join('');
        }
    };

    otpBoxes.forEach((input, index) => {
        input.addEventListener('input', () => {
            input.value = input.value.replace(/\D/g, '').slice(0, 1);
            if (input.value && otpBoxes[index + 1]) {
                otpBoxes[index + 1].focus();
            }
            syncOtp();
        });
        input.addEventListener('keydown', (event) => {
            if (event.key === 'Backspace' && !input.value && otpBoxes[index - 1]) {
                otpBoxes[index - 1].focus();
            }
        });
        input.addEventListener('paste', (event) => {
            const text = (event.clipboardData?.getData('text') || '').replace(/\D/g, '').slice(0, 6);
            if (!text) {
                return;
            }
            event.preventDefault();
            text.split('').forEach((char, i) => {
                if (otpBoxes[i]) {
                    otpBoxes[i].value = char;
                }
            });
            syncOtp();
            otpBoxes[Math.min(text.length, 5)]?.focus();
        });
    });

    document.getElementById('otp-form')?.addEventListener('submit', syncOtp);

    const resendBtn = document.getElementById('resend-btn');
    const resendCountdown = document.getElementById('resend-countdown');
    const resendTimer = document.getElementById('resend-timer');
    const resendRow = document.querySelector('[data-resend-row]');
    let remaining = parseInt(resendRow?.dataset.remaining || '0', 10);

    const formatTime = (value) => {
        const mins = Math.floor(value / 60);
        const secs = value % 60;
        return `${String(mins).padStart(2, '0')}:${String(secs).padStart(2, '0')}`;
    };

    const tickResend = () => {
        if (!resendBtn || !resendCountdown || !resendTimer) {
            return;
        }
        if (remaining <= 0) {
            resendBtn.disabled = false;
            resendCountdown.hidden = true;
            return;
        }
        resendBtn.disabled = true;
        resendCountdown.hidden = false;
        resendTimer.textContent = formatTime(remaining);
        remaining -= 1;
        window.setTimeout(tickResend, 1000);
    };

    if (remaining > 0) {
        tickResend();
    }

    const sheet = document.getElementById('category-sheet');
    const sheetBackdrop = document.getElementById('category-sheet-backdrop');
    const categoryForm = document.getElementById('category-form');
    const categoryName = document.getElementById('category_name');
    const sheetTitle = document.getElementById('category-sheet-title');
    const addBtn = document.getElementById('add-category-btn');

    const openSheet = (title, action, value) => {
        if (!sheet || !sheetBackdrop || !categoryForm || !categoryName || !sheetTitle) {
            return;
        }
        sheetTitle.textContent = title;
        categoryForm.action = action;
        categoryName.value = value || '';
        sheet.hidden = false;
        sheetBackdrop.hidden = false;
        categoryName.focus();
    };

    const closeSheet = () => {
        if (!sheet || !sheetBackdrop) {
            return;
        }
        sheet.hidden = true;
        sheetBackdrop.hidden = true;
    };

    addBtn?.addEventListener('click', () => {
        const action = addBtn.getAttribute('data-create-url') || categoryForm?.getAttribute('data-create-url') || '/categories';
        openSheet('Add New Category', action, '');
    });
    document.getElementById('category-sheet-cancel')?.addEventListener('click', closeSheet);
    sheetBackdrop?.addEventListener('click', closeSheet);

    document.querySelectorAll('[data-edit-category]').forEach((button) => {
        button.addEventListener('click', () => {
            const template = categoryForm?.getAttribute('data-update-template') || '/categories/__ID__';
            openSheet('Edit Category', template.replace('__ID__', button.dataset.id || ''), button.dataset.name || '');
        });
    });

    const deleteSheet = document.getElementById('delete-sheet');
    const deleteBackdrop = document.getElementById('delete-sheet-backdrop');
    const deleteEmptyCopy = document.getElementById('delete-empty-copy');
    const deleteTasksCopy = document.getElementById('delete-tasks-copy');
    const deleteCount = document.getElementById('delete-tasks-count');
    const deleteTarget = document.getElementById('delete-target');
    const deleteMoveHint = document.getElementById('delete-move-hint');
    const deleteModeMove = document.getElementById('delete-mode-move');
    const deleteModePurge = document.getElementById('delete-mode-purge');
    let pendingDelete = null;

    const closeDelete = () => {
        if (!deleteSheet || !deleteBackdrop) {
            return;
        }
        deleteSheet.hidden = true;
        deleteBackdrop.hidden = true;
        pendingDelete = null;
    };

    const fillTargets = (sourceId) => {
        if (!deleteTarget) {
            return 0;
        }
        deleteTarget.innerHTML = '<option value="">- Select -</option>';
        let count = 0;
        document.querySelectorAll('.category-row [data-edit-category]').forEach((button) => {
            if (button.dataset.id === sourceId) {
                return;
            }
            const option = document.createElement('option');
            option.value = button.dataset.id || '';
            option.textContent = button.dataset.name || '';
            deleteTarget.appendChild(option);
            count += 1;
        });
        return count;
    };

    const syncDeleteMode = () => {
        if (!deleteTarget || !deleteModeMove) {
            return;
        }
        const canMove = deleteTarget.options.length > 1 && deleteModeMove.checked;
        deleteTarget.disabled = !canMove;
    };

    document.querySelectorAll('[data-delete-category]').forEach((button) => {
        button.addEventListener('click', () => {
            if (!deleteSheet || !deleteBackdrop || !deleteEmptyCopy || !deleteTasksCopy || !deleteCount) {
                return;
            }
            pendingDelete = button;
            const taskCount = parseInt(button.dataset.taskCount || '0', 10);
            if (taskCount < 1) {
                deleteEmptyCopy.hidden = false;
                deleteTasksCopy.hidden = true;
            } else {
                deleteEmptyCopy.hidden = true;
                deleteTasksCopy.hidden = false;
                deleteCount.textContent = `There are ${taskCount} tasks associated with this category.`;
                const others = fillTargets(button.dataset.id || '');
                if (deleteModeMove) {
                    deleteModeMove.checked = others > 0;
                    deleteModeMove.disabled = others < 1;
                }
                if (deleteModePurge) {
                    deleteModePurge.checked = others < 1;
                }
                if (deleteMoveHint) {
                    deleteMoveHint.hidden = others > 0;
                }
                syncDeleteMode();
            }
            deleteSheet.hidden = false;
            deleteBackdrop.hidden = false;
        });
    });

    deleteModeMove?.addEventListener('change', syncDeleteMode);
    deleteModePurge?.addEventListener('change', syncDeleteMode);
    deleteBackdrop?.addEventListener('click', closeDelete);
    document.getElementById('delete-cancel')?.addEventListener('click', closeDelete);

    document.getElementById('delete-confirm')?.addEventListener('click', () => {
        if (!pendingDelete) {
            return;
        }
        const id = pendingDelete.dataset.id;
        const taskCount = parseInt(pendingDelete.dataset.taskCount || '0', 10);
        const row = pendingDelete.closest('.category-row');
        if (taskCount < 1) {
            row?.querySelector('form[action$="/delete"]')?.submit();
            return;
        }
        if (deleteModeMove?.checked) {
            const select = row?.querySelector('select[name="target_category_id"]');
            if (select && deleteTarget) {
                select.value = deleteTarget.value;
            }
            document.getElementById(`move-form-${id}`)?.submit();
            return;
        }
        document.getElementById(`purge-form-${id}`)?.submit();
    });

    const recurring = document.getElementById('is_recurring');
    const recurrencePanel = document.getElementById('recurrence-panel');
    const syncRecurrencePanel = () => {
        if (!recurrencePanel) {
            return;
        }
        recurrencePanel.hidden = !recurring?.checked;
    };
    recurring?.addEventListener('change', syncRecurrencePanel);
    syncRecurrencePanel();

    const unit = document.querySelector('[data-interval-unit]');
    const copy = document.querySelector('[data-recurrence-copy]');
    const intervalInput = document.getElementById('interval_value');
    const syncRecurrenceType = () => {
        const selected = document.querySelector('input[name="recurrence_type"]:checked');
        const type = selected?.value || 'daily';
        document.querySelectorAll('[data-recurrence-section]').forEach((section) => {
            section.hidden = section.getAttribute('data-recurrence-section') !== type;
        });
        document.querySelectorAll('.type-pill').forEach((pill) => {
            pill.classList.toggle('is-selected', pill.querySelector('input')?.checked === true);
        });
        const n = intervalInput?.value || '1';
        if (unit) {
            unit.textContent = type === 'weekly' ? 'week(s)' : (type === 'monthly' ? 'month(s)' : 'day(s)');
        }
        if (copy) {
            if (type === 'weekly') {
                copy.textContent = `Occurs every ${n} week(s).`;
            } else if (type === 'monthly') {
                copy.textContent = `Occurs every ${n} month(s).`;
            } else {
                copy.textContent = 'Occurs on a daily basis.';
            }
        }
    };
    document.querySelectorAll('input[name="recurrence_type"]').forEach((input) => {
        input.addEventListener('change', syncRecurrenceType);
    });
    intervalInput?.addEventListener('input', syncRecurrenceType);

    const closePopovers = () => {
        document.querySelectorAll('.filter-popover').forEach((popover) => {
            popover.hidden = true;
        });
        document.querySelectorAll('[data-filter-open]').forEach((button) => {
            button.setAttribute('aria-expanded', 'false');
        });
    };

    document.querySelectorAll('[data-filter-open]').forEach((button) => {
        button.addEventListener('click', (event) => {
            event.stopPropagation();
            const name = button.getAttribute('data-filter-open');
            const popover = document.getElementById(`${name}-popover`);
            if (!popover) {
                return;
            }
            const willOpen = popover.hidden;
            closePopovers();
            popover.hidden = !willOpen;
            button.setAttribute('aria-expanded', willOpen ? 'true' : 'false');
        });
    });
    document.addEventListener('click', (event) => {
        if (!(event.target instanceof Element)) {
            return;
        }
        if (event.target.closest('.filter-popover') || event.target.closest('[data-filter-open]')) {
            return;
        }
        closePopovers();
    });

    const csrfPayload = () => {
        const body = new URLSearchParams();
        const name = document.querySelector('meta[name="csrf-token-name"]')?.getAttribute('content');
        const hash = document.querySelector('meta[name="csrf-token"]')?.getAttribute('content');
        if (name && hash) {
            body.set(name, hash);
        }
        return body;
    };

    const postJson = async (url) => {
        const response = await fetch(url, {
            method: 'POST',
            headers: {
                'X-Requested-With': 'XMLHttpRequest',
                Accept: 'application/json',
            },
            body: csrfPayload(),
            credentials: 'same-origin',
        });
        let data = {};
        try {
            data = await response.json();
        } catch (error) {
            data = { ok: false };
        }
        return { ok: response.ok && data.ok !== false, status: response.status, data };
    };

    const emptyCopy = (root) => root?.getAttribute('data-empty-message') || 'No pending tasks match these filters.';

    const ensureEmpty = (container) => {
        if (!container || container.querySelector('.task-swipe')) {
            return;
        }
        if (!container.querySelector('.quadrant-empty')) {
            const p = document.createElement('p');
            p.className = 'quadrant-empty';
            p.textContent = emptyCopy(container.closest('[data-task-lists]') || container);
            container.prepend(p);
        }
    };

    const removeSwipe = (swipe) => {
        const parent = swipe.parentElement;
        swipe.remove();
        if (parent?.classList.contains('quadrant-body') || parent?.classList.contains('priority-list')) {
            ensureEmpty(parent);
        }
    };

    const closeSwipes = (except) => {
        document.querySelectorAll('.task-swipe.is-open').forEach((row) => {
            if (row !== except) {
                row.classList.remove('is-open');
            }
        });
    };

    document.querySelectorAll('.task-swipe').forEach((swipe) => {
        let startX = 0;
        let tracking = false;
        swipe.addEventListener('touchstart', (event) => {
            startX = event.changedTouches[0]?.clientX || 0;
            tracking = true;
        }, { passive: true });
        swipe.addEventListener('touchend', (event) => {
            if (!tracking) {
                return;
            }
            tracking = false;
            const endX = event.changedTouches[0]?.clientX || 0;
            const delta = startX - endX;
            if (delta > 48) {
                closeSwipes(swipe);
                swipe.classList.add('is-open');
            } else if (delta < -24) {
                swipe.classList.remove('is-open');
            }
        }, { passive: true });
    });

    document.addEventListener('click', (event) => {
        if (!(event.target instanceof Element)) {
            return;
        }
        if (!event.target.closest('.task-swipe')) {
            closeSwipes();
        }
    });

    const lists = document.querySelector('[data-task-lists]');
    const statusFilter = lists?.getAttribute('data-status-filter') || 'pending';
    const backdrop = document.getElementById('task-sheet-backdrop');
    const deleteSheet = document.getElementById('task-delete-sheet');
    const recurringSheet = document.getElementById('task-recurring-sheet');
    let pendingSwipe = null;

    const closeTaskSheets = () => {
        if (deleteSheet) {
            deleteSheet.hidden = true;
        }
        if (recurringSheet) {
            recurringSheet.hidden = true;
        }
        if (backdrop) {
            backdrop.hidden = true;
        }
        pendingSwipe = null;
    };

    const openSheet = (sheet) => {
        if (!sheet || !backdrop) {
            return;
        }
        sheet.hidden = false;
        backdrop.hidden = false;
    };

    const completeSwipe = async (swipe) => {
        const id = swipe.getAttribute('data-occurrence-id');
        if (!id) {
            return;
        }
        const result = await postJson(`/tasks/occurrences/${id}/complete`);
        if (!result.ok) {
            return;
        }
        if (statusFilter === 'pending') {
            removeSwipe(swipe);
            return;
        }
        swipe.setAttribute('data-status', 'completed');
        swipe.classList.remove('is-open');
    };

    document.querySelectorAll('[data-complete]').forEach((button) => {
        button.addEventListener('click', (event) => {
            event.preventDefault();
            event.stopPropagation();
            const swipe = button.closest('.task-swipe');
            if (swipe) {
                completeSwipe(swipe);
            }
        });
    });

    document.querySelectorAll('[data-delete]').forEach((button) => {
        button.addEventListener('click', (event) => {
            event.preventDefault();
            event.stopPropagation();
            const swipe = button.closest('.task-swipe');
            if (!swipe) {
                return;
            }
            pendingSwipe = swipe;
            if (swipe.getAttribute('data-recurring') === '1') {
                openSheet(recurringSheet);
            } else {
                openSheet(deleteSheet);
            }
        });
    });

    document.getElementById('task-delete-confirm')?.addEventListener('click', async () => {
        const swipe = pendingSwipe;
        if (!swipe) {
            return;
        }
        const taskId = swipe.getAttribute('data-task-id');
        const result = await postJson(`/tasks/${taskId}/delete`);
        closeTaskSheets();
        if (result.ok) {
            removeSwipe(swipe);
        }
    });
    document.getElementById('task-delete-this')?.addEventListener('click', async () => {
        const swipe = pendingSwipe;
        if (!swipe) {
            return;
        }
        const id = swipe.getAttribute('data-occurrence-id');
        const result = await postJson(`/tasks/occurrences/${id}/delete`);
        closeTaskSheets();
        if (result.ok) {
            removeSwipe(swipe);
        }
    });
    document.getElementById('task-delete-future')?.addEventListener('click', async () => {
        const swipe = pendingSwipe;
        if (!swipe) {
            return;
        }
        const id = swipe.getAttribute('data-occurrence-id');
        const result = await postJson(`/tasks/occurrences/${id}/delete-future`);
        closeTaskSheets();
        if (result.ok) {
            window.location.reload();
        }
    });
    document.getElementById('task-delete-cancel')?.addEventListener('click', closeTaskSheets);
    document.getElementById('task-recurring-cancel')?.addEventListener('click', closeTaskSheets);
    backdrop?.addEventListener('click', closeTaskSheets);
})();
