(function () {
    window.AgentFrontendModules = window.AgentFrontendModules || {};

    window.AgentFrontendModules.createFolderTreesModule = function createFolderTreesModule(deps) {
        const chevronSvg = '<svg width="16" height="16" viewBox="0 0 16 16" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round"><path d="M6 4l4 4-4 4"/></svg>';

        function createTreeController(options) {
            function getSelectedFolders() {
                const selected = options.getSelectedFolders();
                return selected && typeof selected === 'object' ? selected : {};
            }

            function renderTree(stores) {
                if (!options.treeEl) return;
                const nextStores = Array.isArray(stores) ? stores : [];
                options.setLastStores(nextStores);
                options.treeEl.innerHTML = '';
                options.treeEl.style.display = '';
                nextStores.forEach((store) => {
                    const header = document.createElement('div');
                    header.className = 'ft-store';
                    header.innerHTML = `<span class="ft-store-icon">${options.storeIcon}</span>`;
                    header.appendChild(document.createTextNode(store.store));
                    options.treeEl.appendChild(header);
                    const list = document.createElement('ul');
                    store.folders.forEach((folder) => list.appendChild(buildNode(folder)));
                    options.treeEl.appendChild(list);
                });
            }

            function buildNode(folder) {
                const hasChildren = folder.children && folder.children.length > 0;
                const li = document.createElement('li');
                li.dataset.ftPath = folder.path;

                const row = document.createElement('div');
                row.className = 'ft-node';

                const toggle = document.createElement('span');
                toggle.className = 'ft-toggle' + (hasChildren ? '' : ' leaf');
                toggle.innerHTML = chevronSvg;

                const checkbox = document.createElement('input');
                checkbox.type = 'checkbox';
                checkbox.className = 'ft-cb';
                checkbox.checked = !!getSelectedFolders()[folder.path];
                checkbox.addEventListener('change', () => {
                    setNode(li, checkbox.checked);
                    updateAncestors(li);
                });

                const icon = document.createElement('span');
                icon.className = 'ft-icon';
                icon.textContent = hasChildren ? '\uD83D\uDCC2' : options.leafIcon;

                const label = document.createElement('span');
                label.className = 'ft-label';
                label.textContent = folder.name;

                const count = document.createElement('span');
                count.className = 'ft-count';
                count.textContent = folder.count > 0 ? `(${folder.count})` : '';

                row.append(toggle, checkbox, icon, label, count);
                li.appendChild(row);

                if (hasChildren) {
                    const childList = document.createElement('ul');
                    childList.className = 'ft-children collapsed';
                    folder.children.forEach((child) => childList.appendChild(buildNode(child)));
                    li.appendChild(childList);
                    toggle.addEventListener('click', () => {
                        const isOpen = !childList.classList.contains('collapsed');
                        childList.classList.toggle('collapsed', isOpen);
                        toggle.classList.toggle('open', !isOpen);
                    });
                    label.style.cursor = 'pointer';
                    label.addEventListener('dblclick', () => toggle.click());
                }

                return li;
            }

            function setNode(li, checked) {
                const path = li.dataset.ftPath;
                const selected = getSelectedFolders();
                if (path) {
                    if (checked) selected[path] = selected[path] || '';
                    else delete selected[path];
                }
                const checkbox = li.querySelector(':scope > .ft-node > .ft-cb');
                if (checkbox) {
                    checkbox.checked = checked;
                    checkbox.indeterminate = false;
                }
                toggleDesc(li, checked);
                const childList = li.querySelector(':scope > .ft-children');
                if (childList) childList.querySelectorAll(':scope > li').forEach((child) => setNode(child, checked));
                deps.onSelectionsChanged();
            }

            function toggleDesc(li, show) {
                const existing = li.querySelector(':scope > .ft-desc-row');
                if (existing) existing.remove();
                if (!show) return;
            }

            function updateAncestors(li) {
                const parentList = li.parentElement;
                if (!parentList || !parentList.classList.contains('ft-children')) return;
                const parentItem = parentList.parentElement;
                if (!parentItem || parentItem.tagName !== 'LI') return;

                const siblings = parentList.querySelectorAll(':scope > li');
                let checkedCount = 0;
                let indeterminateCount = 0;
                siblings.forEach((sibling) => {
                    const checkbox = sibling.querySelector(':scope > .ft-node > .ft-cb');
                    if (!checkbox) return;
                    if (checkbox.indeterminate) indeterminateCount += 1;
                    else if (checkbox.checked) checkedCount += 1;
                });

                const selected = getSelectedFolders();
                const total = siblings.length;
                const parentCheckbox = parentItem.querySelector(':scope > .ft-node > .ft-cb');
                if (parentCheckbox) {
                    if (checkedCount === total && indeterminateCount === 0) {
                        parentCheckbox.checked = true;
                        parentCheckbox.indeterminate = false;
                        selected[parentItem.dataset.ftPath] = selected[parentItem.dataset.ftPath] || '';
                    } else if (checkedCount === 0 && indeterminateCount === 0) {
                        parentCheckbox.checked = false;
                        parentCheckbox.indeterminate = false;
                        delete selected[parentItem.dataset.ftPath];
                    } else {
                        parentCheckbox.checked = false;
                        parentCheckbox.indeterminate = true;
                        delete selected[parentItem.dataset.ftPath];
                    }
                }

                updateAncestors(parentItem);
            }

            function loadFromSettings(settings) {
                const nextSelected = {};
                const extra = settings[options.extraKey] || [];
                const profiles = settings[options.profileKey] || {};
                extra.forEach((path) => {
                    nextSelected[path] = profiles[path] || '';
                });
                options.setSelectedFolders(nextSelected);
                deps.onRenderSelected();
            }

            function collect() {
                const selected = getSelectedFolders();
                return {
                    [options.extraKey]: Object.keys(selected).sort(),
                    [options.profileKey]: { ...selected },
                };
            }

            async function scan() {
                if (!options.scanBtn) return;
                options.scanBtn.disabled = true;
                options.scanBtn.textContent = 'Scanning...';
                try {
                    const data = await deps.authFetchJson(options.scanEndpoint);
                    if (data && data.ok) {
                        renderTree(data.stores || []);
                    } else if (options.treeEl) {
                        options.treeEl.style.display = '';
                        options.treeEl.innerHTML = `<p class="settings-note" style="color:var(--danger)">${data?.error || options.scanErrorText}</p>`;
                    }
                } catch (error) {
                    if (options.treeEl) {
                        options.treeEl.style.display = '';
                        options.treeEl.innerHTML = `<p class="settings-note" style="color:var(--danger)">Error: ${error.message || error}</p>`;
                    }
                } finally {
                    options.scanBtn.disabled = false;
                    options.scanBtn.textContent = options.scanIdleLabel;
                }
            }

            function bindScanHandler() {
                if (options.scanBtn) options.scanBtn.addEventListener('click', scan);
            }

            return {
                renderTree,
                loadFromSettings,
                collect,
                bindScanHandler,
            };
        }

        const outlook = createTreeController({
            treeEl: deps.outlook.treeEl,
            scanBtn: deps.outlook.scanBtn,
            scanEndpoint: '/api/integrations/outlook/folders',
            scanIdleLabel: 'Scan Folders',
            scanErrorText: 'Could not scan folders.',
            storeIcon: '\uD83D\uDCEB',
            leafIcon: '\uD83D\uDCC1',
            extraKey: 'outlook_extra_folders',
            profileKey: 'outlook_folder_profiles',
            getSelectedFolders: deps.outlook.getSelectedFolders,
            setSelectedFolders: deps.outlook.setSelectedFolders,
            setLastStores: deps.outlook.setLastStores,
        });

        const google = createTreeController({
            treeEl: deps.google.treeEl,
            scanBtn: deps.google.scanBtn,
            scanEndpoint: '/api/integrations/google/labels',
            scanIdleLabel: 'Scan Labels',
            scanErrorText: 'Could not scan labels.',
            storeIcon: '\u2709\uFE0F',
            leafIcon: '\uD83C\uDFF7\uFE0F',
            extraKey: 'google_extra_folders',
            profileKey: 'google_folder_profiles',
            getSelectedFolders: deps.google.getSelectedFolders,
            setSelectedFolders: deps.google.setSelectedFolders,
            setLastStores: deps.google.setLastStores,
        });

        return {
            ftRenderTree: outlook.renderTree,
            ftLoadFromSettings: outlook.loadFromSettings,
            ftCollect: outlook.collect,
            gftRenderTree: google.renderTree,
            gftLoadFromSettings: google.loadFromSettings,
            gftCollect: google.collect,
            bindScanHandlers: function bindScanHandlers() {
                outlook.bindScanHandler();
                google.bindScanHandler();
            },
        };
    };
})();