(function () {
    if (window.__MELON_LITE_SIDEBAR_INITED) return;
    window.__MELON_LITE_SIDEBAR_INITED = true;

    const settings = Object.assign({
        groupsDefaultOpen: true,
        mobileAutoClose: true
    }, window.APP_SIDEBAR_SETTINGS || {});

    const groupStorageKey = 'melon_lite_sidebar_groups';
    const scrollStorageKey = 'melon_lite_sidebar_scroll_top';
    const collapsedStorageKey = 'melon_lite_sidebar_collapsed';
    const desktopQuery = window.matchMedia('(min-width: 1200px), (min-width: 900px) and (orientation: landscape)');
    const mobileQuery = window.matchMedia('(max-width: 767px), (min-width: 768px) and (max-width: 1199px) and (orientation: portrait)');
    const tabletQuery = window.matchMedia('(min-width: 768px) and (max-width: 1199px), (pointer: coarse) and (min-width: 768px) and (max-width: 1366px)');

    function sidebar() {
        return document.getElementById('app-sidebar');
    }

    function overlay() {
        return document.getElementById('sidebar-overlay');
    }

    function sidebarScroll() {
        const el = sidebar();
        return el ? el.querySelector('.sidebar-scroll') : null;
    }

    function readJson(key, fallback) {
        try {
            const raw = localStorage.getItem(key);
            if (!raw) return fallback;
            const parsed = JSON.parse(raw);
            return parsed && typeof parsed === 'object' && !Array.isArray(parsed) ? parsed : fallback;
        } catch (err) {
            try { localStorage.removeItem(key); } catch (storageErr) {}
            return fallback;
        }
    }

    function writeJson(key, value) {
        try { localStorage.setItem(key, JSON.stringify(value)); } catch (err) {}
    }

    function readCollapsed() {
        try {
            const stored = localStorage.getItem(collapsedStorageKey);
            if (stored === null) return true;
            return stored === '1';
        } catch (err) { return true; }
    }

    function writeCollapsed(value) {
        try { localStorage.setItem(collapsedStorageKey, value ? '1' : '0'); } catch (err) {}
    }

    function readStoredScrollTop() {
        try {
            const value = sessionStorage.getItem(scrollStorageKey) || localStorage.getItem(scrollStorageKey);
            const parsed = parseInt(value, 10);
            return Number.isFinite(parsed) && parsed >= 0 ? parsed : 0;
        } catch (err) {
            return 0;
        }
    }

    function writeStoredScrollTop() {
        const scroll = sidebarScroll();
        if (!scroll) return;
        try {
            const value = String(scroll.scrollTop || 0);
            sessionStorage.setItem(scrollStorageKey, value);
            localStorage.setItem(scrollStorageKey, value);
        } catch (err) {}
    }

    function isDesktopLayout() {
        return desktopQuery.matches;
    }

    function applyViewportClasses() {
        const width = window.innerWidth || document.documentElement.clientWidth || 0;
        const isTablet = tabletQuery.matches;
        const isPortrait = window.matchMedia('(orientation: portrait)').matches;
        const isDesktop = width >= 1200 && !isTablet;
        document.body.classList.toggle('is-tablet-layout', isTablet);
        document.body.classList.toggle('is-tablet-portrait', isTablet && isPortrait);
        document.body.classList.toggle('is-tablet-landscape', isTablet && !isPortrait);
        document.body.classList.toggle('is-mobile-layout', width > 0 && width < 768);
        document.body.classList.toggle('is-desktop-layout', isDesktop);
    }

    function isElementVisibleInSidebar(element) {
        const scroll = sidebarScroll();
        if (!scroll || !element) return true;
        const containerRect = scroll.getBoundingClientRect();
        const elementRect = element.getBoundingClientRect();
        return elementRect.top >= containerRect.top && elementRect.bottom <= containerRect.bottom;
    }

    function revealActiveMenuIfNeeded() {
        const scroll = sidebarScroll();
        if (!scroll || document.body.classList.contains('sidebar-collapsed')) return;
        const active = scroll.querySelector('.nav-item.active');
        if (!active || isElementVisibleInSidebar(active)) return;
        try {
            active.scrollIntoView({ block: 'nearest', inline: 'nearest' });
            writeStoredScrollTop();
        } catch (err) {
            const offset = active.offsetTop - scroll.clientHeight / 2;
            scroll.scrollTop = Math.max(0, offset);
            writeStoredScrollTop();
        }
    }

    function menuKeyFromUrl(url) {
        let path = '';
        let relativePath = '';
        let urlObj;
        try {
            urlObj = new URL(url, window.location.href);
            const normalizedPath = urlObj.pathname.replace(/\\/g, '/');
            path = normalizedPath.split('/').pop() || 'index.php';
            relativePath = normalizedPath.includes('/admin/') ? 'admin/' + path : path;
        } catch (err) {
            path = 'index.php';
            relativePath = 'index.php';
            urlObj = new URL(window.location.href);
        }
        const map = {
            'index.php': 'home',
            'search.php': 'search',
            'user_settings.php': 'user_settings',
            'help.php': 'help',
            'stats.php': 'stats',
            'listening_notes.php': 'listening_notes',
            'tags.php': 'tags',
            'tag.php': 'tags',
            'new.php': 'new',
            'liked.php': 'liked',
            'recent.php': 'recent',
            'popular.php': 'popular',
            'folders.php': 'folders',
            'folder.php': 'folders',
            'artists.php': 'artists',
            'artist.php': 'artists',
            'albums.php': 'albums',
            'album.php': 'albums',
            'genres.php': 'genres',
            'genre.php': 'genres',
            'recommend.php': 'recommend',
            'auto_playlists.php': 'auto_playlists',
            'auto_playlist.php': 'auto_playlists',
            'playlists.php': 'playlists',
            'playlist_view.php': 'playlists',
            'playlist_create.php': 'playlist_create',
            'playlist_edit.php': 'playlists',
            'login.php': 'login',
            'settings.php': 'settings',
            'admin/index.php': 'admin_home',
            'admin/users.php': 'admin_users',
            'admin/api_tokens.php': 'api_tokens',
            'admin/scan.php': 'scan',
            'admin/diagnostics.php': 'diagnostics',
            'admin/logs.php': 'logs',
            'admin/log_view.php': 'logs',
            'admin/audit_logs.php': 'audit_logs',
            'admin/alerts.php': 'alerts',
            'admin/jobs.php': 'jobs',
            'admin/performance.php': 'performance',
            'admin/listening_stats.php': 'admin_listening_stats',
            'admin/metadata.php': 'metadata',
            'admin/metadata_quality.php': 'metadata_quality',
            'admin/metadata_requests.php': 'metadata_requests',
            'admin/bulk_edit.php': 'bulk_edit',
            'admin/duplicates.php': 'duplicates',
            'admin/missing_files.php': 'missing_files',
            'admin/smart_organize.php': 'smart_organize',
            'admin/tag_manage.php': 'tag_manage',
            'admin/name_merge.php': 'name_merge',
            'admin/backup_center.php': 'backup',
            'admin/backup.php': 'backup',
            'admin/restore.php': 'backup',
            'admin/import.php': 'backup',
            'admin/export.php': 'backup',
            'users.php': 'admin_users',
            'api_tokens.php': 'api_tokens',
            'scan.php': 'scan',
            'diagnostics.php': 'diagnostics',
            'audit_logs.php': 'audit_logs',
            'alerts.php': 'alerts',
            'jobs.php': 'jobs',
            'performance.php': 'performance',
            'listening_stats.php': 'admin_listening_stats',
            'metadata.php': 'metadata',
            'metadata_quality.php': 'metadata_quality',
            'metadata_requests.php': 'metadata_requests',
            'bulk_edit.php': 'bulk_edit',
            'duplicates.php': 'duplicates',
            'missing_files.php': 'missing_files',
            'smart_organize.php': 'smart_organize',
            'tag_manage.php': 'tag_manage',
            'name_merge.php': 'name_merge',
            'backup_center.php': 'backup',
            'backup.php': 'backup',
            'restore.php': 'backup',
            'import.php': 'backup',
            'export.php': 'backup',
            'logs.php': 'logs',
            'song.php': 'all'
        };
        if (relativePath === 'settings.php') {
            const hashMap = {
                '#theme-settings': 'theme_settings',
                '#player-settings': 'player_settings',
                '#pwa-settings': 'pwa_settings',
                '#maintenance-tools': 'maintenance'
            };
            if (hashMap[urlObj.hash]) return hashMap[urlObj.hash];
        }
        if (path === 'index.php' && urlObj.searchParams.get('view') === 'all') return 'all';
        return map[relativePath] || map[path] || null;
    }

    function updateActiveMenu(url) {
        const side = sidebar();
        const scroll = sidebarScroll();
        if (!side) return;
        const key = menuKeyFromUrl(url || window.location.href);
        if (!key) return;
        const previousScrollTop = scroll ? scroll.scrollTop : 0;
        side.querySelectorAll('.nav-item.active').forEach(function (item) {
            item.classList.remove('active');
            item.removeAttribute('aria-current');
        });
        side.querySelectorAll('.menu-group.has-active').forEach(group => group.classList.remove('has-active'));
        const safeKey = window.CSS && CSS.escape ? CSS.escape(key) : key.replace(/"/g, '\\"');
        const active = side.querySelector(`.nav-item[data-menu-key="${safeKey}"]`);
        if (active) {
            active.classList.add('active');
            active.setAttribute('aria-current', 'page');
            const group = active.closest('.menu-group');
            if (group && !document.body.classList.contains('sidebar-collapsed')) {
                group.classList.add('has-active', 'open');
                group.classList.remove('collapsed');
                const toggle = group.querySelector('.menu-group-toggle');
                if (toggle) toggle.setAttribute('aria-expanded', 'true');
            } else if (group) {
                group.classList.add('has-active');
            }
        }
        if (scroll) scroll.scrollTop = previousScrollTop;
        window.setTimeout(revealActiveMenuIfNeeded, 40);
    }

    function closeMobileSidebar() {
        const side = sidebar();
        const over = overlay();
        if (!side || !over) return;
        side.classList.remove('open');
        over.classList.remove('open');
        document.body.classList.remove('mobile-sidebar-open');
        const hamburger = document.getElementById('mobile-hamburger');
        if (hamburger) hamburger.setAttribute('aria-expanded', 'false');
    }

    function openMobileSidebar() {
        const side = sidebar();
        const over = overlay();
        if (!side || !over) return;
        side.classList.add('open');
        over.classList.add('open');
        document.body.classList.add('mobile-sidebar-open');
        const hamburger = document.getElementById('mobile-hamburger');
        if (hamburger) hamburger.setAttribute('aria-expanded', 'true');
    }

    function toggleMobileSidebar() {
        const side = sidebar();
        if (!side) return;
        if (side.classList.contains('open')) closeMobileSidebar();
        else openMobileSidebar();
    }

    function applyCollapsedState() {
        const collapsed = isDesktopLayout() && readCollapsed();
        document.body.classList.toggle('sidebar-collapsed', collapsed);
        const button = document.getElementById('sidebar-collapse-toggle');
        if (button) {
            button.setAttribute('aria-expanded', collapsed ? 'false' : 'true');
            button.setAttribute('aria-label', collapsed ? '사이드메뉴 펼치기' : '사이드메뉴 접기');
            button.setAttribute('title', collapsed ? '사이드메뉴 펼치기' : '사이드메뉴 접기');
            button.classList.toggle('is-collapsed', collapsed);
            const icon = button.querySelector('i');
            if (icon) icon.className = collapsed ? 'fa-solid fa-angles-right' : 'fa-solid fa-angles-left';
        }
        if (!isDesktopLayout()) document.body.classList.remove('sidebar-collapsed');
    }

    function toggleDesktopCollapse() {
        if (!isDesktopLayout()) return;
        const next = !document.body.classList.contains('sidebar-collapsed');
        writeStoredScrollTop();
        writeCollapsed(next);
        applyCollapsedState();
    }

    function initGroups() {
        const stored = readJson(groupStorageKey, {});
        document.querySelectorAll('.menu-group').forEach(function (group) {
            if (group.dataset.sidebarGroupBound === '1') return;
            group.dataset.sidebarGroupBound = '1';

            const key = group.getAttribute('data-group-key');
            const toggle = group.querySelector('.menu-group-toggle');
            const hasActive = group.classList.contains('has-active');

            if (Object.prototype.hasOwnProperty.call(stored, key) && !hasActive) {
                group.classList.toggle('open', stored[key] === true);
                group.classList.toggle('collapsed', stored[key] !== true);
            }
            if (hasActive) {
                group.classList.add('open');
                group.classList.remove('collapsed');
            }
            if (toggle) {
                toggle.setAttribute('aria-expanded', group.classList.contains('open') ? 'true' : 'false');
                toggle.addEventListener('click', function () {
                    if (document.body.classList.contains('sidebar-collapsed')) {
                        writeCollapsed(false);
                        applyCollapsedState();
                        return;
                    }
                    const nextOpen = !group.classList.contains('open');
                    group.classList.toggle('open', nextOpen);
                    group.classList.toggle('collapsed', !nextOpen);
                    toggle.setAttribute('aria-expanded', nextOpen ? 'true' : 'false');
                    const nextState = readJson(groupStorageKey, {});
                    nextState[key] = nextOpen;
                    writeJson(groupStorageKey, nextState);
                    window.setTimeout(writeStoredScrollTop, 0);
                });
            }
        });
    }

    function bindSearchForms() {
        document.querySelectorAll('.sidebar-search-form, .quick-search-form').forEach(function (form) {
            if (form.dataset.sidebarSearchBound === '1') return;
            form.dataset.sidebarSearchBound = '1';
            form.addEventListener('submit', function (event) {
                const input = form.querySelector('input[name="q"]');
                const value = input ? input.value.trim() : '';
                if (!value) {
                    event.preventDefault();
                    if (input) input.focus();
                    return;
                }
                if (input) input.value = value;
            });
        });
    }

    function normalizeMenuText(value) {
        return String(value || '').toLowerCase().replace(/\s+/g, '');
    }

    function restoreFilteredMenuState(side) {
        const stored = readJson(groupStorageKey, {});
        side.classList.remove('is-menu-filtering');
        side.querySelectorAll('.nav-item, .sidebar-quick-actions a').forEach(function (item) {
            item.hidden = false;
        });
        side.querySelectorAll('.sidebar-single-menu, .sidebar-utility-panel, .sidebar-quick-actions').forEach(function (group) {
            group.hidden = false;
        });
        side.querySelectorAll('.menu-group').forEach(function (group) {
            const key = group.getAttribute('data-group-key');
            const hasActive = group.classList.contains('has-active');
            const hasStoredState = Object.prototype.hasOwnProperty.call(stored, key);
            const shouldOpen = hasActive || (hasStoredState ? stored[key] === true : settings.groupsDefaultOpen);
            group.hidden = false;
            group.classList.toggle('open', shouldOpen);
            group.classList.toggle('collapsed', !shouldOpen);
            const toggle = group.querySelector('.menu-group-toggle');
            if (toggle) toggle.setAttribute('aria-expanded', shouldOpen ? 'true' : 'false');
        });
    }

    function ensureMenuFilter() {
        const side = sidebar();
        if (!side) return null;
        let filter = side.querySelector('.sidebar-menu-filter');
        if (filter) return filter;
        const searchForm = side.querySelector('.sidebar-search-form');
        if (!searchForm) return null;

        filter = document.createElement('div');
        filter.className = 'sidebar-menu-filter';
        filter.setAttribute('role', 'search');
        filter.innerHTML = [
            '<i class="fa-solid fa-filter" aria-hidden="true"></i>',
            '<input type="search" id="sidebar-menu-filter" autocomplete="off" aria-label="메뉴 찾기" placeholder="메뉴 찾기">',
            '<button type="button" id="sidebar-menu-filter-clear" aria-label="메뉴 검색 지우기" title="메뉴 검색 지우기"><i class="fa-solid fa-xmark" aria-hidden="true"></i></button>'
        ].join('');
        searchForm.insertAdjacentElement('afterend', filter);

        const empty = document.createElement('p');
        empty.className = 'sidebar-menu-empty';
        empty.id = 'sidebar-menu-empty';
        empty.hidden = true;
        empty.textContent = '찾은 메뉴가 없습니다.';
        filter.insertAdjacentElement('afterend', empty);
        return filter;
    }

    function bindMenuFilter() {
        const side = sidebar();
        const filter = ensureMenuFilter();
        if (!side || !filter || filter.dataset.menuFilterBound === '1') return;
        filter.dataset.menuFilterBound = '1';
        const input = filter.querySelector('input');
        const clear = filter.querySelector('button');
        const empty = side.querySelector('.sidebar-menu-empty');
        if (!input) return;

        const applyFilter = function () {
            const query = normalizeMenuText(input.value);
            const filtering = query.length > 0;
            let visibleCount = 0;
            if (clear) clear.hidden = !filtering;

            if (!filtering) {
                restoreFilteredMenuState(side);
                if (empty) empty.hidden = true;
                return;
            }

            side.classList.add('is-menu-filtering');

            side.querySelectorAll('.nav-item, .sidebar-quick-actions a').forEach(function (item) {
                const group = item.closest('.menu-group');
                const groupLabel = group ? group.querySelector('.menu-group-toggle span')?.textContent || '' : '';
                const text = normalizeMenuText(
                    item.textContent + ' ' +
                    groupLabel + ' ' +
                    (item.getAttribute('title') || '') + ' ' +
                    (item.getAttribute('aria-label') || '') + ' ' +
                    (item.getAttribute('data-menu-label') || '') + ' ' +
                    (item.getAttribute('data-menu-key') || '')
                );
                const visible = !filtering || text.indexOf(query) !== -1;
                item.hidden = !visible;
                if (visible) visibleCount += 1;
            });

            side.querySelectorAll('.menu-group').forEach(function (group) {
                const hasVisibleItem = Boolean(group.querySelector('.nav-item:not([hidden])'));
                group.hidden = filtering && !hasVisibleItem;
                if (filtering && hasVisibleItem) {
                    group.classList.add('open');
                    group.classList.remove('collapsed');
                    const toggle = group.querySelector('.menu-group-toggle');
                    if (toggle) toggle.setAttribute('aria-expanded', 'true');
                }
            });

            side.querySelectorAll('.sidebar-single-menu').forEach(function (group) {
                const hasVisibleItem = Boolean(group.querySelector('.nav-item:not([hidden])'));
                group.hidden = filtering && !hasVisibleItem;
            });

            const quickActions = side.querySelector('.sidebar-quick-actions');
            if (quickActions) {
                const hasVisibleQuickAction = Boolean(quickActions.querySelector('a:not([hidden])'));
                quickActions.hidden = filtering && !hasVisibleQuickAction;
                const utilityPanel = quickActions.closest('.sidebar-utility-panel');
                if (utilityPanel) utilityPanel.hidden = filtering && !hasVisibleQuickAction;
            }

            if (empty) empty.hidden = visibleCount > 0;
        };

        input.addEventListener('input', applyFilter);
        if (clear) {
            clear.hidden = true;
            clear.addEventListener('click', function () {
                input.value = '';
                applyFilter();
                input.focus();
            });
        }
    }

    function bindSidebarLinks() {
        const side = sidebar();
        if (!side) return;
        side.querySelectorAll('.nav-item, .sidebar-quick-actions a').forEach(function (link) {
            if (link.dataset.sidebarLinkBound === '1') return;
            link.dataset.sidebarLinkBound = '1';
            link.addEventListener('click', function () {
                writeStoredScrollTop();
                if (settings.mobileAutoClose && mobileQuery.matches) closeMobileSidebar();
            });
        });
    }

    function bindShellControls() {
        const hamburger = document.getElementById('mobile-hamburger');
        if (hamburger && hamburger.dataset.sidebarBound !== '1') {
            hamburger.dataset.sidebarBound = '1';
            hamburger.setAttribute('aria-expanded', sidebar()?.classList.contains('open') ? 'true' : 'false');
            hamburger.addEventListener('click', function (event) {
                event.preventDefault();
                toggleMobileSidebar();
            });
        }

        const over = overlay();
        if (over && over.dataset.sidebarBound !== '1') {
            over.dataset.sidebarBound = '1';
            over.addEventListener('click', closeMobileSidebar);
        }

        const collapse = document.getElementById('sidebar-collapse-toggle');
        if (collapse && collapse.dataset.sidebarBound !== '1') {
            collapse.dataset.sidebarBound = '1';
            collapse.addEventListener('click', function (event) {
                event.preventDefault();
                toggleDesktopCollapse();
            });
        }
    }

    function initScrollMemory() {
        const scroll = sidebarScroll();
        if (!scroll || scroll.dataset.sidebarScrollBound === '1') return;
        scroll.dataset.sidebarScrollBound = '1';
        window.requestAnimationFrame(function () {
            scroll.scrollTop = readStoredScrollTop();
            window.setTimeout(revealActiveMenuIfNeeded, 80);
        });
        scroll.addEventListener('scroll', function () {
            window.clearTimeout(scroll.__melonLiteScrollTimer);
            scroll.__melonLiteScrollTimer = window.setTimeout(writeStoredScrollTop, 120);
        }, { passive: true });
        window.addEventListener('beforeunload', writeStoredScrollTop);
        document.addEventListener('visibilitychange', function () {
            if (document.visibilityState === 'hidden') writeStoredScrollTop();
        });
    }

    function handleViewportChange() {
        applyViewportClasses();
        if (isDesktopLayout()) {
            closeMobileSidebar();
        } else {
            document.body.classList.remove('sidebar-collapsed');
        }
        applyCollapsedState();
    }

    function debounceViewportChange() {
        window.clearTimeout(window.__melonLiteSidebarViewportTimer);
        window.__melonLiteSidebarViewportTimer = window.setTimeout(handleViewportChange, 120);
    }

    function initSidebar() {
        applyViewportClasses();
        bindShellControls();
        initGroups();
        bindSearchForms();
        bindMenuFilter();
        bindSidebarLinks();
        initScrollMemory();
        applyCollapsedState();
        updateActiveMenu(window.location.href);
    }

    document.addEventListener('keydown', function (event) {
        if (event.key === 'Escape') closeMobileSidebar();
    });

    if (desktopQuery.addEventListener) desktopQuery.addEventListener('change', handleViewportChange);
    else if (desktopQuery.addListener) desktopQuery.addListener(handleViewportChange);
    if (mobileQuery.addEventListener) mobileQuery.addEventListener('change', handleViewportChange);
    else if (mobileQuery.addListener) mobileQuery.addListener(handleViewportChange);
    if (tabletQuery.addEventListener) tabletQuery.addEventListener('change', handleViewportChange);
    else if (tabletQuery.addListener) tabletQuery.addListener(handleViewportChange);
    window.addEventListener('resize', debounceViewportChange, { passive: true });
    window.addEventListener('orientationchange', debounceViewportChange, { passive: true });

    document.addEventListener('melonlite:page-ready', initSidebar);
    document.addEventListener('DOMContentLoaded', initSidebar);
    if (document.readyState !== 'loading') initSidebar();

    window.MelonLiteSidebar = {
        saveScroll: writeStoredScrollTop,
        updateActive: updateActiveMenu,
        closeMobile: closeMobileSidebar,
        toggleCollapsed: toggleDesktopCollapse,
        init: initSidebar,
        applyCollapsed: applyCollapsedState
    };
})();
