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

    window.AgentFrontendModules.createContextSourcesModule = function createContextSourcesModule(deps) {
        function contextUiProvider(entry) {
            const provider = String(entry?.provider || '').trim().toLowerCase();
            const kind = String(entry?.kind || '').trim().toLowerCase();
            if (kind === 'email_folder' && (provider === 'outlook' || provider === 'google')) return provider;
            if ((provider === 'filesystem' || provider === 'local' || !provider) && kind === 'local_directory') return 'filesystem';
            if (provider === 'onedrive' || provider === 'onedrive_local') return 'onedrive';
            if (provider === 'google_drive') return 'google_drive';
            return '';
        }

        function contextProviderLabel(provider) {
            if (provider === 'outlook') return 'Outlook';
            if (provider === 'google') return 'Google Email';
            if (provider === 'filesystem') return 'Filesystem';
            if (provider === 'onedrive') return 'OneDrive';
            if (provider === 'google_drive') return 'Google Drive';
            return provider || 'Context';
        }

        function contextProviderMeta(entry) {
            if (entry.provider === 'outlook') return 'Persistent Outlook folder';
            if (entry.provider === 'google') return 'Persistent Gmail label';
            if (contextUiProvider(entry) === 'filesystem') return 'Persistent local directory';
            if (entry.provider === 'onedrive' || entry.provider === 'onedrive_local') return 'Persistent OneDrive folder';
            if (entry.provider === 'google_drive') return 'Persistent Google Drive folder';
            return entry.kind.replace(/_/g, ' ');
        }

        function contextProviderSortRank(provider) {
            return ({ outlook: 1, google: 2, filesystem: 3, onedrive: 4, google_drive: 5 })[provider] || 99;
        }

        function contextEntryManagedByUi(entry) {
            if (!entry || entry.enabled === false) return false;
            return !!contextUiProvider(entry);
        }

        function contextManagedEntriesFromState() {
            const entries = [];
            const outlookSelectedFolders = deps.state.getOutlookSelectedFolders?.() || {};
            const googleSelectedFolders = deps.state.getGoogleSelectedFolders?.() || {};
            const filesystemSources = deps.state.getFilesystemSources?.() || {};
            const oneDriveSources = deps.state.getOneDriveSources?.() || {};
            const googleDriveSources = deps.state.getGoogleDriveSources?.() || {};

            Object.keys(outlookSelectedFolders).sort().forEach((path) => {
                entries.push({ kind: 'email_folder', provider: 'outlook', path, description: outlookSelectedFolders[path] || '', enabled: true });
            });
            Object.keys(googleSelectedFolders).sort().forEach((path) => {
                entries.push({ kind: 'email_folder', provider: 'google', path, description: googleSelectedFolders[path] || '', enabled: true });
            });
            Object.keys(filesystemSources).sort().forEach((path) => {
                entries.push({ kind: 'local_directory', provider: 'filesystem', path, description: filesystemSources[path] || '', enabled: true });
            });
            Object.keys(oneDriveSources).sort().forEach((path) => {
                entries.push({ kind: 'cloud_folder', provider: 'onedrive', path, description: oneDriveSources[path] || '', enabled: true });
            });
            Object.keys(googleDriveSources).sort().forEach((path) => {
                entries.push({ kind: 'cloud_folder', provider: 'google_drive', path, description: googleDriveSources[path] || '', enabled: true });
            });
            return entries;
        }

        function renderManagedContextList(container, items, emptyText, onRemove) {
            if (!container) return;
            const ordered = [...items].sort((left, right) => left.path.localeCompare(right.path));
            if (!ordered.length) {
                container.innerHTML = `<div class="context-empty-state">${deps.helpers.escapeHtml(emptyText)}</div>`;
                return;
            }
            container.innerHTML = ordered.map((entry) => {
                return `
                    <div class="context-managed-item" data-context-path="${deps.helpers.escapeHtml(entry.path)}">
                        <div class="context-managed-copy">
                            <div class="context-managed-title">${deps.helpers.escapeHtml(entry.path)}</div>
                        </div>
                        <button type="button" class="context-managed-remove" data-remove-path="${deps.helpers.escapeHtml(entry.path)}">Remove</button>
                    </div>
                `;
            }).join('');
            container.querySelectorAll('[data-remove-path]').forEach((button) => {
                button.addEventListener('click', () => onRemove(button.getAttribute('data-remove-path') || ''));
            });
        }

        function removeOutlookContextPath(path) {
            if (!path) return;
            const nextSelected = { ...(deps.state.getOutlookSelectedFolders?.() || {}) };
            delete nextSelected[path];
            deps.state.setOutlookSelectedFolders?.(nextSelected);
            const renderTree = deps.helpers.getOutlookRenderTree?.();
            const lastStores = deps.state.getOutlookLastStores?.() || [];
            if (renderTree && lastStores.length) renderTree(lastStores);
            syncStructuralContextFromUi();
        }

        function removeGoogleContextPath(path) {
            if (!path) return;
            const nextSelected = { ...(deps.state.getGoogleSelectedFolders?.() || {}) };
            delete nextSelected[path];
            deps.state.setGoogleSelectedFolders?.(nextSelected);
            const renderTree = deps.helpers.getGoogleRenderTree?.();
            const lastStores = deps.state.getGoogleLastStores?.() || [];
            if (renderTree && lastStores.length) renderTree(lastStores);
            syncStructuralContextFromUi();
        }

        function removeFilesystemContextPath(path) {
            if (!path) return;
            const nextSources = { ...(deps.state.getFilesystemSources?.() || {}) };
            delete nextSources[path];
            deps.state.setFilesystemSources?.(nextSources);
            syncStructuralContextFromUi();
        }

        function removeOneDriveContextPath(path) {
            if (!path) return;
            const nextSources = { ...(deps.state.getOneDriveSources?.() || {}) };
            delete nextSources[path];
            deps.state.setOneDriveSources?.(nextSources);
            syncStructuralContextFromUi();
        }

        function removeGoogleDriveContextPath(path) {
            if (!path) return;
            const nextSources = { ...(deps.state.getGoogleDriveSources?.() || {}) };
            delete nextSources[path];
            deps.state.setGoogleDriveSources?.(nextSources);
            syncStructuralContextFromUi();
        }

        function renderContextManagedSelections() {
            const refs = deps.refs;
            const outlookSelectedFolders = deps.state.getOutlookSelectedFolders?.() || {};
            const googleSelectedFolders = deps.state.getGoogleSelectedFolders?.() || {};
            const filesystemSources = deps.state.getFilesystemSources?.() || {};
            const oneDriveSources = deps.state.getOneDriveSources?.() || {};
            const googleDriveSources = deps.state.getGoogleDriveSources?.() || {};

            renderManagedContextList(
                refs.outlookSelectedDiv,
                Object.keys(outlookSelectedFolders).map((path) => ({ provider: 'outlook', kind: 'email_folder', path, description: outlookSelectedFolders[path] || '' })),
                'No extra Outlook folders selected yet.',
                removeOutlookContextPath,
            );
            renderManagedContextList(
                refs.googleSelectedDiv,
                Object.keys(googleSelectedFolders).map((path) => ({ provider: 'google', kind: 'email_folder', path, description: googleSelectedFolders[path] || '' })),
                'No Gmail labels selected yet.',
                removeGoogleContextPath,
            );
            renderManagedContextList(
                refs.filesystemContextSelected,
                Object.keys(filesystemSources).map((path) => ({ provider: 'filesystem', kind: 'local_directory', path, description: filesystemSources[path] || '' })),
                'No persistent filesystem directories selected yet.',
                removeFilesystemContextPath,
            );
            renderManagedContextList(
                refs.onedriveContextSelected,
                Object.keys(oneDriveSources).map((path) => ({ provider: 'onedrive', kind: 'cloud_folder', path, description: oneDriveSources[path] || '' })),
                'No persistent OneDrive folders selected yet.',
                removeOneDriveContextPath,
            );
            renderManagedContextList(
                refs.googleDriveContextSelected,
                Object.keys(googleDriveSources).map((path) => ({ provider: 'google_drive', kind: 'cloud_folder', path, description: googleDriveSources[path] || '' })),
                'No persistent Google Drive folders selected yet.',
                removeGoogleDriveContextPath,
            );
        }

        function normalizeUiContextSourceEntry(entry) {
            if (!entry || typeof entry !== 'object') return null;
            const kind = String(entry.kind || entry.type || '').trim().toLowerCase();
            const provider = String(entry.provider || '').trim().toLowerCase();
            const path = String(entry.path || entry.folder || entry.label || entry.directory || '').trim();
            const description = String(entry.description || entry.notes || entry.label_description || '').trim();
            const enabled = entry.enabled !== false;
            if (!kind || !path) return null;
            return { kind, provider, path, description, enabled };
        }

        function loadManagedContextSources(settings) {
            const filesystemSources = {};
            const oneDriveSources = {};
            const googleDriveSources = {};
            const sources = Array.isArray(settings?.context_sources) ? settings.context_sources : [];
            sources
                .map(normalizeUiContextSourceEntry)
                .filter((entry) => entry && entry.enabled !== false)
                .forEach((entry) => {
                    const provider = contextUiProvider(entry);
                    if (provider === 'filesystem') filesystemSources[entry.path] = entry.description || '';
                    if (provider === 'onedrive') oneDriveSources[entry.path] = entry.description || '';
                    if (provider === 'google_drive') googleDriveSources[entry.path] = entry.description || '';
                });
            deps.state.setFilesystemSources?.(filesystemSources);
            deps.state.setOneDriveSources?.(oneDriveSources);
            deps.state.setGoogleDriveSources?.(googleDriveSources);
        }

        function upsertContextSource(state, path, description) {
            const normalizedPath = String(path || '').trim();
            if (!normalizedPath) return false;
            state[normalizedPath] = String(description || '').trim();
            return true;
        }

        function toggleContextCard(card, forceOpen = null) {
            if (!card) return;
            const shouldOpen = forceOpen === null ? !card.classList.contains('is-open') : !!forceOpen;
            card.classList.toggle('is-open', shouldOpen);
            const toggle = card.querySelector('[data-context-toggle]');
            if (toggle) toggle.setAttribute('aria-expanded', shouldOpen ? 'true' : 'false');
            const label = card.querySelector('.context-card-toggle-label');
            if (label) label.textContent = shouldOpen ? 'Collapse' : 'Expand';
        }

        function setEmailContextSectionState(section, button, statusNode, options) {
            if (section) section.style.display = '';
            if (button) button.disabled = !options.available;
            if (!statusNode) return;
            statusNode.textContent = options.message || '';
            statusNode.className = options.tone ? `settings-note ${options.tone}` : 'settings-note';
            statusNode.style.display = options.message ? '' : 'none';
        }

        function addFilesystemContextSource() {
            const nextSources = { ...(deps.state.getFilesystemSources?.() || {}) };
            if (!upsertContextSource(nextSources, deps.refs.filesystemContextPath?.value, deps.refs.filesystemContextDescription?.value)) return;
            deps.state.setFilesystemSources?.(nextSources);
            if (deps.refs.filesystemContextPath) deps.refs.filesystemContextPath.value = '';
            if (deps.refs.filesystemContextDescription) deps.refs.filesystemContextDescription.value = '';
            syncStructuralContextFromUi();
        }

        function addOneDriveContextSource(pathOverride = null) {
            const nextSources = { ...(deps.state.getOneDriveSources?.() || {}) };
            const path = pathOverride ?? deps.refs.onedriveContextPath?.value;
            if (!upsertContextSource(nextSources, path, deps.refs.onedriveContextDescription?.value)) return;
            deps.state.setOneDriveSources?.(nextSources);
            if (deps.refs.onedriveContextPath) deps.refs.onedriveContextPath.value = '';
            if (deps.refs.onedriveContextDescription) deps.refs.onedriveContextDescription.value = '';
            syncStructuralContextFromUi();
        }

        function addGoogleDriveContextSource(pathOverride = null) {
            const nextSources = { ...(deps.state.getGoogleDriveSources?.() || {}) };
            const path = pathOverride ?? deps.refs.googleDriveContextPath?.value;
            if (!upsertContextSource(nextSources, path, deps.refs.googleDriveContextDescription?.value)) return;
            deps.state.setGoogleDriveSources?.(nextSources);
            if (deps.refs.googleDriveContextPath) deps.refs.googleDriveContextPath.value = '';
            if (deps.refs.googleDriveContextDescription) deps.refs.googleDriveContextDescription.value = '';
            syncStructuralContextFromUi();
        }

        function contextSourceSortValue(entry) {
            return `${String(entry.provider || '').toLowerCase()}::${String(entry.path || '').toLowerCase()}`;
        }

        function buildStructuralContextSources(baseSettings = null) {
            const sourceSettings = baseSettings && typeof baseSettings === 'object' ? baseSettings : deps.state.getAppSettings?.();
            const merged = new Map();
            const preserved = Array.isArray(sourceSettings?.context_sources)
                ? sourceSettings.context_sources
                    .map(normalizeUiContextSourceEntry)
                    .filter((entry) => entry && !contextEntryManagedByUi(entry))
                : [];

            function put(entry) {
                const normalized = normalizeUiContextSourceEntry(entry);
                if (!normalized) return;
                const key = `${normalized.kind}::${normalized.provider}::${normalized.path.toLowerCase()}`;
                merged.set(key, normalized);
            }

            preserved.forEach(put);
            contextManagedEntriesFromState().forEach(put);

            return Array.from(merged.values()).sort((left, right) => contextSourceSortValue(left).localeCompare(contextSourceSortValue(right)));
        }

        async function persistStructuralContextSettings() {
            const appSettings = deps.state.getAppSettings?.();
            const payload = {
                context_sources: buildStructuralContextSources(appSettings),
                ...deps.helpers.ftCollect?.(),
                ...deps.helpers.gftCollect?.(),
            };
            await deps.helpers.authFetch('/api/settings', {
                method: 'POST',
                headers: { 'Content-Type': 'application/json' },
                body: JSON.stringify(payload),
            });
        }

        function scheduleStructuralContextSettingsSave() {
            if (deps.state.getIsLoadingSettings?.()) return;
            const currentTimer = deps.state.getContextAutoSaveTimer?.();
            if (currentTimer) clearTimeout(currentTimer);
            const timer = setTimeout(async () => {
                deps.state.setContextAutoSaveTimer?.(null);
                try {
                    await persistStructuralContextSettings();
                } catch (error) {
                    console.warn('context auto-save:', error);
                }
            }, 450);
            deps.state.setContextAutoSaveTimer?.(timer);
        }

        function renderStructuralContextSummary(baseSettings = null) {
            const refs = deps.refs;
            const sources = buildStructuralContextSources(baseSettings);
            const enabledSources = sources.filter((entry) => entry.enabled !== false);
            const outlookCount = enabledSources.filter((entry) => contextUiProvider(entry) === 'outlook').length;
            const googleCount = enabledSources.filter((entry) => contextUiProvider(entry) === 'google').length;
            const filesystemCount = enabledSources.filter((entry) => contextUiProvider(entry) === 'filesystem').length;
            const onedriveCount = enabledSources.filter((entry) => contextUiProvider(entry) === 'onedrive').length;
            const googleDriveCount = enabledSources.filter((entry) => contextUiProvider(entry) === 'google_drive').length;
            if (refs.outlookContextCount) refs.outlookContextCount.textContent = String(outlookCount);
            if (refs.googleContextCount) refs.googleContextCount.textContent = String(googleCount);
            if (refs.filesystemContextCount) refs.filesystemContextCount.textContent = String(filesystemCount);
            if (refs.onedriveContextCount) refs.onedriveContextCount.textContent = String(onedriveCount);
            if (refs.googleDriveContextCount) refs.googleDriveContextCount.textContent = String(googleDriveCount);
            if (refs.contextTotalCount) refs.contextTotalCount.textContent = String(enabledSources.length);
            if (!refs.contextSourcesSummary) return;

            const buckets = {
                outlook: enabledSources.filter((entry) => contextUiProvider(entry) === 'outlook'),
                googleMail: enabledSources.filter((entry) => contextUiProvider(entry) === 'google'),
                googleDrive: enabledSources.filter((entry) => contextUiProvider(entry) === 'google_drive'),
                filesystem: enabledSources.filter((entry) => contextUiProvider(entry) === 'filesystem'),
                onedrive: enabledSources.filter((entry) => contextUiProvider(entry) === 'onedrive'),
            };

            const renderLeaves = (items, emptyText) => {
                const orderedItems = [...items].sort((left, right) => left.path.localeCompare(right.path));
                if (!orderedItems.length) {
                    return `<div class="context-tree-leaf context-tree-leaf-muted">${deps.helpers.escapeHtml(emptyText)}</div>`;
                }
                return orderedItems.map((entry) => `
                    <div class="context-tree-leaf">
                        <span class="context-tree-bullet"></span>
                        <span class="context-tree-path">${deps.helpers.escapeHtml(entry.path)}</span>
                    </div>
                `).join('');
            };

            const renderRoot = (title, count, body) => `
                <div class="context-tree-root">
                    <div class="context-tree-root-header">
                        <div class="context-tree-title">${deps.helpers.escapeHtml(title)}</div>
                        <span class="context-source-chip">${count}</span>
                    </div>
                    <div class="context-tree-children">${body}</div>
                </div>
            `;

            const renderBranch = (title, items, emptyText) => `
                <div class="context-tree-branch">
                    <div class="context-tree-branch-header">
                        <span class="context-tree-branch-title">${deps.helpers.escapeHtml(title)}</span>
                        <span class="context-tree-branch-count">${items.length}</span>
                    </div>
                    <div class="context-tree-children">${renderLeaves(items, emptyText)}</div>
                </div>
            `;

            refs.contextSourcesSummary.innerHTML = [
                renderRoot('Outlook', buckets.outlook.length, renderLeaves(buckets.outlook, 'No folders selected')),
                renderRoot('Google', buckets.googleMail.length + buckets.googleDrive.length, [
                    renderBranch('Mail', buckets.googleMail, 'No labels selected'),
                    renderBranch('Drive', buckets.googleDrive, 'No folders selected'),
                ].join('')),
                renderRoot('Filesystem', buckets.filesystem.length, renderLeaves(buckets.filesystem, 'No folders selected')),
                renderRoot('OneDrive', buckets.onedrive.length, renderLeaves(buckets.onedrive, 'No folders selected')),
            ].join('');
        }

        function syncStructuralContextFromUi(baseSettings = null) {
            const targetSettings = baseSettings && typeof baseSettings === 'object' ? baseSettings : deps.state.getAppSettings?.();
            const sources = buildStructuralContextSources(targetSettings);
            targetSettings.context_sources = sources;
            renderContextManagedSelections();
            renderStructuralContextSummary(targetSettings);
            if (targetSettings === deps.state.getAppSettings?.()) scheduleStructuralContextSettingsSave();
            return sources;
        }

        function bindUi() {
            document.querySelectorAll('[data-context-toggle]').forEach((button) => {
                button.addEventListener('click', () => toggleContextCard(button.closest('[data-context-card]')));
                toggleContextCard(button.closest('[data-context-card]'), button.getAttribute('aria-expanded') !== 'false');
            });

            if (deps.refs.filesystemContextBrowseBtn && deps.refs.filesystemContextPath && deps.refs.filesystemContextRow) {
                deps.refs.filesystemContextBrowseBtn.addEventListener('click', () => {
                    deps.helpers.openDirBrowser?.(deps.refs.filesystemContextPath, deps.refs.filesystemContextRow);
                });
            }
            if (deps.refs.filesystemContextAddBtn) deps.refs.filesystemContextAddBtn.addEventListener('click', addFilesystemContextSource);
            if (deps.refs.filesystemContextPath) {
                deps.refs.filesystemContextPath.addEventListener('keydown', (event) => {
                    if (event.key === 'Enter') {
                        event.preventDefault();
                        addFilesystemContextSource();
                    }
                });
            }

            if (deps.refs.onedriveContextAddBtn) deps.refs.onedriveContextAddBtn.addEventListener('click', () => addOneDriveContextSource());
            if (deps.refs.onedriveContextBrowseBtn) {
                deps.refs.onedriveContextBrowseBtn.addEventListener('click', () => {
                    const provider = deps.state.getOneDriveMode?.() === 'local' ? 'onedrive_local' : 'onedrive';
                    deps.helpers.openCloudBrowser?.(provider, 'OneDrive', {
                        mode: 'folder',
                        onSelectFolder: (folder) => {
                            if (deps.refs.onedriveContextPath) deps.refs.onedriveContextPath.value = folder.pathLabel || folder.name || 'Root';
                        },
                    });
                });
            }
            if (deps.refs.onedriveContextAddRootBtn) {
                deps.refs.onedriveContextAddRootBtn.addEventListener('click', () => {
                    const localPathValue = deps.state.getOneDriveLocalPathValue?.() || '';
                    const rootPath = (deps.state.getOneDriveMode?.() === 'local' && localPathValue)
                        ? localPathValue
                        : 'Root';
                    addOneDriveContextSource(rootPath);
                });
            }
            if (deps.refs.onedriveContextPath) {
                deps.refs.onedriveContextPath.addEventListener('keydown', (event) => {
                    if (event.key === 'Enter') {
                        event.preventDefault();
                        addOneDriveContextSource();
                    }
                });
            }

            if (deps.refs.googleDriveContextAddBtn) deps.refs.googleDriveContextAddBtn.addEventListener('click', () => addGoogleDriveContextSource());
            if (deps.refs.googleDriveContextBrowseBtn) {
                deps.refs.googleDriveContextBrowseBtn.addEventListener('click', () => {
                    deps.helpers.openCloudBrowser?.('google_drive', 'Google Drive', {
                        mode: 'folder',
                        onSelectFolder: (folder) => {
                            if (deps.refs.googleDriveContextPath) deps.refs.googleDriveContextPath.value = folder.pathLabel || folder.name || 'Root';
                        },
                    });
                });
            }
            if (deps.refs.googleDriveContextAddRootBtn) {
                deps.refs.googleDriveContextAddRootBtn.addEventListener('click', () => addGoogleDriveContextSource('Root'));
            }
            if (deps.refs.googleDriveContextPath) {
                deps.refs.googleDriveContextPath.addEventListener('keydown', (event) => {
                    if (event.key === 'Enter') {
                        event.preventDefault();
                        addGoogleDriveContextSource();
                    }
                });
            }
        }

        return {
            bindUi,
            contextUiProvider,
            contextProviderLabel,
            contextProviderMeta,
            contextProviderSortRank,
            renderContextManagedSelections,
            loadManagedContextSources,
            setEmailContextSectionState,
            buildStructuralContextSources,
            renderStructuralContextSummary,
            syncStructuralContextFromUi,
        };
    };
})();