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

    window.AgentFrontendModules.createCopilotModule = function createCopilotModule(deps) {
        function getSettings() {
            return deps.getSettings();
        }

        function setSettings(nextSettings) {
            deps.setSettings(nextSettings);
        }

        function normalizeTime(value, fallbackTime) {
            const raw = String(value || '').trim();
            if (/^\d{2}:\d{2}$/.test(raw)) return raw;
            return fallbackTime;
        }

        function normalizeCopilotTime(value) {
            return normalizeTime(value, '08:30');
        }

        function normalizeFollowupTime(value) {
            return normalizeTime(value, '11:30');
        }

        function hasOwn(object, key) {
            return !!object && Object.prototype.hasOwnProperty.call(object, key);
        }

        function normalizeCopilotSettings(settings) {
            const normalized = Object.assign({}, settings || {});
            normalized.copilot_enabled = !!normalized.copilot_enabled;
            normalized.copilot_morning_brief_enabled = !!normalized.copilot_morning_brief_enabled;
            normalized.copilot_followup_enabled = !!normalized.copilot_followup_enabled;
            normalized.copilot_morning_brief_time = normalizeCopilotTime(
                hasOwn(normalized, 'copilot_morning_brief_time') ? normalized.copilot_morning_brief_time : normalized.copilot_briefing_time
            );
            normalized.copilot_followup_time = normalizeFollowupTime(
                hasOwn(normalized, 'copilot_followup_time') ? normalized.copilot_followup_time : '11:30'
            );
            normalized.copilot_morning_brief_instructions = String(
                hasOwn(normalized, 'copilot_morning_brief_instructions') ? normalized.copilot_morning_brief_instructions : (normalized.copilot_instructions || '')
            );
            normalized.copilot_followup_instructions = String(
                hasOwn(normalized, 'copilot_followup_instructions') ? normalized.copilot_followup_instructions : (normalized.copilot_instructions || '')
            );
            normalized.copilot_briefing_time = normalized.copilot_morning_brief_time;
            normalized.copilot_instructions = normalized.copilot_morning_brief_instructions;
            return normalized;
        }

        function collectCopilotStateFromUi(settings) {
            const sourceSettings = settings && typeof settings === 'object' ? settings : getSettings();
            const settingsOpen = !!(deps.settingsOverlay && deps.settingsOverlay.style.display !== 'none');
            return {
                copilot_enabled: settingsOpen
                    ? !!(deps.copilotEnabledSettingsToggle && deps.copilotEnabledSettingsToggle.checked)
                    : !!sourceSettings.copilot_enabled,
                copilot_morning_brief_enabled: settingsOpen
                    ? !!(deps.copilotMorningBriefToggle && deps.copilotMorningBriefToggle.checked)
                    : !!sourceSettings.copilot_morning_brief_enabled,
                copilot_morning_brief_time: settingsOpen
                    ? normalizeCopilotTime(deps.copilotBriefingTimeInput ? deps.copilotBriefingTimeInput.value : '08:30')
                    : normalizeCopilotTime(sourceSettings.copilot_morning_brief_time),
                copilot_followup_enabled: settingsOpen
                    ? !!(deps.copilotFollowupToggle && deps.copilotFollowupToggle.checked)
                    : !!sourceSettings.copilot_followup_enabled,
                copilot_followup_time: settingsOpen
                    ? normalizeFollowupTime(deps.copilotFollowupTimeInput ? deps.copilotFollowupTimeInput.value : '11:30')
                    : normalizeFollowupTime(sourceSettings.copilot_followup_time),
                copilot_autonomy_level: settingsOpen
                    ? String(deps.copilotAutonomyLevelInput ? deps.copilotAutonomyLevelInput.value : 'suggest').trim() || 'suggest'
                    : String(sourceSettings.copilot_autonomy_level || 'suggest').trim() || 'suggest',
                copilot_morning_brief_instructions: settingsOpen
                    ? String(deps.copilotMorningInstructionsInput ? deps.copilotMorningInstructionsInput.value : '').trim()
                    : String(sourceSettings.copilot_morning_brief_instructions || '').trim(),
                copilot_followup_instructions: settingsOpen
                    ? String(deps.copilotFollowupInstructionsInput ? deps.copilotFollowupInstructionsInput.value : '').trim()
                    : String(sourceSettings.copilot_followup_instructions || '').trim(),
                copilot_briefing_time: settingsOpen
                    ? normalizeCopilotTime(deps.copilotBriefingTimeInput ? deps.copilotBriefingTimeInput.value : '08:30')
                    : normalizeCopilotTime(sourceSettings.copilot_morning_brief_time),
                copilot_instructions: settingsOpen
                    ? String(deps.copilotMorningInstructionsInput ? deps.copilotMorningInstructionsInput.value : '').trim()
                    : String(sourceSettings.copilot_morning_brief_instructions || '').trim(),
            };
        }

        function copilotAutonomySummary(level) {
            if (level === 'signal') return 'only surfaces what matters';
            if (level === 'draft') return 'may prepare draft replies or outlines';
            return 'suggests concrete next actions';
        }

        function setCopilotStatus(target, message, tone) {
            const statusTarget = String(target || '').trim().toLowerCase();
            const noteEl = statusTarget === 'followup' ? deps.copilotFollowupStatusNote : deps.copilotMorningStatusNote;
            if (!noteEl) return;
            noteEl.textContent = String(message || '').trim();
            noteEl.className = 'copilot-status-note' + (tone ? ` ${tone}` : '');
        }

        function setAllCopilotStatuses(message, tone) {
            setCopilotStatus('morning', message, tone);
            setCopilotStatus('followup', message, tone);
        }

        function syncCopilotEnabledToggles(enabled) {
            if (deps.copilotEnabledSettingsToggle) deps.copilotEnabledSettingsToggle.checked = !!enabled;
        }

        function computeCopilotFirstRunIso(timeText) {
            const normalized = normalizeCopilotTime(timeText);
            const parts = normalized.split(':');
            const next = new Date();
            next.setSeconds(0, 0);
            next.setHours(Number(parts[0]) || 8, Number(parts[1]) || 30, 0, 0);
            if (next.getTime() <= Date.now() + 60000) {
                next.setDate(next.getDate() + 1);
            }
            return next.toISOString();
        }

        function buildCopilotMorningBriefGoal() {
            const state = collectCopilotStateFromUi();
            const settings = getSettings();
            const sources = [];
            if (settings.outlook_enabled) sources.push('Outlook email and calendar');
            if (settings.google_enabled) sources.push('Gmail and Google Calendar');
            const sourceLine = sources.length ? sources.join(', ') : 'available email and calendar integrations';
            const autonomyLine = state.copilot_autonomy_level === 'draft'
                ? 'You may prepare draft replies or preparation outlines, but do not send or modify anything automatically.'
                : state.copilot_autonomy_level === 'signal'
                    ? 'Only signal what matters. Do not prepare drafts unless explicitly asked.'
                    : 'Suggest concrete next actions, but do not send or modify anything automatically.';
            const instructionLine = state.copilot_morning_brief_instructions
                ? `Extra user instructions: ${state.copilot_morning_brief_instructions}`
                : 'Extra user instructions: none.';
            return [
                'Co-Pilot Morning Brief for today.',
                `Use ${sourceLine} as the primary sources.`,
                'Deliver an advice-first morning brief, not an exhaustive inventory.',
                'Start with the 2-3 things that most deserve attention today and explain why they matter.',
                'Then give the recommended action order for this morning.',
                'Only after that add short supporting bullets for reply-likely emails, meetings needing preparation, and watch items.',
                'Avoid long lists and avoid repeating every raw mail or calendar item.',
                autonomyLine,
                instructionLine,
            ].join('\n');
        }

        function buildCopilotFollowupGoal() {
            const state = collectCopilotStateFromUi();
            const settings = getSettings();
            const sources = [];
            if (settings.outlook_enabled) sources.push('Outlook email and calendar');
            if (settings.google_enabled) sources.push('Gmail and Google Calendar');
            const sourceLine = sources.length ? sources.join(', ') : 'available email and calendar integrations';
            const autonomyLine = state.copilot_autonomy_level === 'draft'
                ? 'You may prepare draft replies or preparation outlines, but do not send or modify anything automatically.'
                : state.copilot_autonomy_level === 'signal'
                    ? 'Only signal what matters. Do not prepare drafts unless explicitly asked.'
                    : 'Suggest concrete next actions, but do not send or modify anything automatically.';
            const instructionLine = state.copilot_followup_instructions
                ? `Extra user instructions: ${state.copilot_followup_instructions}`
                : 'Extra user instructions: none.';
            return [
                'Co-Pilot Follow-up Brief for today.',
                `Use ${sourceLine} as the primary sources.`,
                'Deliver a follow-up-first brief focused on open loops, pending replies, decisions, and meeting preparation.',
                'Start with the 2-3 items most likely to stall progress if ignored.',
                'Then group the remaining items into reply-needed, prep-needed, and watchlist signals.',
                'Avoid exhaustive lists and avoid repeating every raw mail or calendar item.',
                autonomyLine,
                instructionLine,
            ].join('\n');
        }

        function copilotScheduleDefinitions(state) {
            const currentState = state || collectCopilotStateFromUi();
            return [
                {
                    ...deps.copilotScheduleConfigs['morning-brief'],
                    enabled: !!currentState.copilot_morning_brief_enabled,
                    time: currentState.copilot_morning_brief_time,
                    goal: buildCopilotMorningBriefGoal(),
                },
                {
                    ...deps.copilotScheduleConfigs['follow-up'],
                    enabled: !!currentState.copilot_followup_enabled,
                    time: currentState.copilot_followup_time,
                    goal: buildCopilotFollowupGoal(),
                },
            ];
        }

        function upsertLocalCopilotSchedules() {
            const state = collectCopilotStateFromUi();
            const localIds = Object.values(deps.copilotScheduleConfigs).map(function (item) { return item.localId; });
            const schedules = deps.loadSchedules().filter(function (item) { return !localIds.includes(item.id); });
            copilotScheduleDefinitions(state).forEach(function (definition) {
                if (!(state.copilot_enabled && definition.enabled)) return;
                schedules.push({
                    id: definition.localId,
                    goal: definition.goal,
                    model: getSettings().main_model || '',
                    context: '',
                    interval: 1,
                    unit: 'days',
                    enabled: true,
                    source: definition.source,
                    label: definition.label,
                    metadata: {
                        briefing_time: definition.time,
                        autonomy_level: state.copilot_autonomy_level,
                    },
                    createdAt: Date.now(),
                    nextRun: new Date(computeCopilotFirstRunIso(definition.time)).getTime(),
                    lastRun: null,
                    runCount: 0,
                });
            });
            deps.saveSchedules(schedules);
            deps.startSchedulePolling();
            return schedules;
        }

        async function syncCopilotSchedules() {
            const state = collectCopilotStateFromUi();
            try {
                const data = await deps.authFetchJson(`${deps.backendUrl}/api/schedules`);
                const schedules = Array.isArray(data.schedules) ? data.schedules : [];
                for (const definition of copilotScheduleDefinitions(state)) {
                    const existing = schedules.find(function (item) {
                        return String((item && item.source) || '').trim() === definition.source;
                    });
                    if (!(state.copilot_enabled && definition.enabled)) {
                        if (existing) {
                            await deps.authFetchJson(`${deps.backendUrl}/api/schedules/${existing.id}`, { method: 'DELETE' });
                        }
                        continue;
                    }
                    const payload = {
                        goal: definition.goal,
                        interval: '1d',
                        first_run: computeCopilotFirstRunIso(definition.time),
                        source: definition.source,
                        label: definition.label,
                        enabled: true,
                        metadata: {
                            briefing_time: definition.time,
                            autonomy_level: state.copilot_autonomy_level,
                        },
                    };
                    const endpoint = existing ? `${deps.backendUrl}/api/schedules/${existing.id}` : `${deps.backendUrl}/api/schedules`;
                    const method = existing ? 'PATCH' : 'POST';
                    const body = existing
                        ? {
                            goal: payload.goal,
                            interval: payload.interval,
                            next_run: payload.first_run,
                            source: payload.source,
                            label: payload.label,
                            enabled: true,
                            metadata: payload.metadata,
                        }
                        : payload;
                    await deps.authFetchJson(endpoint, {
                        method: method,
                        headers: { 'Content-Type': 'application/json' },
                        body: JSON.stringify(body),
                    });
                }
                const localIds = Object.values(deps.copilotScheduleConfigs).map(function (item) { return item.localId; });
                const localSchedules = deps.loadSchedules().filter(function (item) { return !localIds.includes(item.id); });
                deps.saveSchedules(localSchedules);
                return deps.authFetchJson(`${deps.backendUrl}/api/schedules`);
            } catch (_) {
                return { serverSchedules: [], localSchedules: upsertLocalCopilotSchedules() };
            }
        }

        async function saveCopilotSettings() {
            const state = collectCopilotStateFromUi();
            const nextSettings = Object.assign({}, getSettings(), {
                copilot_enabled: state.copilot_enabled,
                copilot_morning_brief_enabled: state.copilot_morning_brief_enabled,
                copilot_morning_brief_time: state.copilot_morning_brief_time,
                copilot_followup_enabled: state.copilot_followup_enabled,
                copilot_followup_time: state.copilot_followup_time,
                copilot_briefing_time: state.copilot_briefing_time,
                copilot_autonomy_level: state.copilot_autonomy_level,
                copilot_morning_brief_instructions: state.copilot_morning_brief_instructions,
                copilot_followup_instructions: state.copilot_followup_instructions,
                copilot_instructions: state.copilot_instructions,
            });
            setSettings(nextSettings);
            refreshCopilotPanelUi();
            try {
                await deps.authFetchJson(`${deps.backendUrl}/api/settings`, {
                    method: 'POST',
                    headers: { 'Content-Type': 'application/json' },
                    body: JSON.stringify(nextSettings),
                });
                const data = await syncCopilotSchedules();
                const serverSchedules = Array.isArray(data?.schedules)
                    ? data.schedules
                    : Array.isArray(data?.serverSchedules)
                        ? data.serverSchedules
                        : [];
                const localSchedules = Array.isArray(data?.localSchedules)
                    ? data.localSchedules
                    : deps.loadSchedules();
                updateCopilotStatusFromSchedules(serverSchedules, localSchedules);
                if (typeof deps.renderSchedules === 'function') {
                    deps.renderSchedules();
                }
                return data;
            } catch (error) {
                setAllCopilotStatuses(`Could not save Co-Pilot: ${error.message || error}`, 'err');
                throw error;
            }
        }

        function populateCopilotQuickstartOptions() {
            if (!deps.copilotQuickstartSelect) return;
            const currentValue = String(deps.copilotQuickstartSelect.value || '').trim();
            deps.copilotQuickstartSelect.innerHTML = '';
            deps.copilotQuickstarts.forEach(function (item) {
                const option = document.createElement('option');
                option.value = item.id;
                option.textContent = item.label;
                deps.copilotQuickstartSelect.appendChild(option);
            });
            const nextValue = deps.copilotQuickstarts.some(function (item) { return item.id === currentValue; })
                ? currentValue
                : (deps.copilotQuickstarts[0] ? deps.copilotQuickstarts[0].id : '');
            deps.copilotQuickstartSelect.value = nextValue;
            if (deps.copilotQuickstartBtn) deps.copilotQuickstartBtn.disabled = !nextValue;
        }

        function refreshCopilotPanelUi() {
            const state = collectCopilotStateFromUi();
            const copilotActive = state.copilot_enabled;
            const morningBriefEnabled = !!state.copilot_morning_brief_enabled;
            const followupEnabled = !!state.copilot_followup_enabled;
            if (deps.copilotQuickstartBtn) deps.copilotQuickstartBtn.disabled = !(deps.copilotQuickstartSelect && deps.copilotQuickstartSelect.value);
            if (deps.copilotMorningBriefToggle) deps.copilotMorningBriefToggle.disabled = false;
            if (deps.copilotBriefingTimeInput) deps.copilotBriefingTimeInput.disabled = !morningBriefEnabled;
            if (deps.copilotFollowupToggle) deps.copilotFollowupToggle.disabled = false;
            if (deps.copilotFollowupTimeInput) deps.copilotFollowupTimeInput.disabled = !followupEnabled;
            if (deps.copilotAutonomyLevelInput) deps.copilotAutonomyLevelInput.disabled = false;
            if (deps.copilotMorningInstructionsInput) deps.copilotMorningInstructionsInput.disabled = false;
            if (deps.copilotFollowupInstructionsInput) deps.copilotFollowupInstructionsInput.disabled = false;
            if (deps.copilotRunNowBtn) deps.copilotRunNowBtn.disabled = !copilotActive;
            if (deps.copilotFollowupRunBtn) deps.copilotFollowupRunBtn.disabled = !copilotActive;

            if (!copilotActive) {
                setCopilotStatus(
                    'morning',
                    morningBriefEnabled
                        ? 'Co-Pilot is off. Your Morning Brief settings are ready and will go live when you enable Co-Pilot.'
                        : 'Co-Pilot is off. You can configure the Morning Brief first, then enable Co-Pilot when ready.',
                    morningBriefEnabled ? 'ok' : ''
                );
                setCopilotStatus(
                    'followup',
                    followupEnabled
                        ? 'Co-Pilot is off. Your Follow-up sweep is configured and will go live when you enable Co-Pilot.'
                        : 'Co-Pilot is off. You can configure Follow-up first, then enable Co-Pilot when ready.',
                    followupEnabled ? 'ok' : ''
                );
                return;
            }
            if (!state.copilot_morning_brief_enabled) {
                setCopilotStatus('morning', 'Co-Pilot is on. Morning Brief is not scheduled yet.', 'ok');
            } else {
                setCopilotStatus('morning', `Morning Brief is set for ${state.copilot_morning_brief_time}. Co-Pilot ${copilotAutonomySummary(state.copilot_autonomy_level)}.`, 'ok');
            }
            if (!state.copilot_followup_enabled) {
                setCopilotStatus('followup', 'Co-Pilot is on. Follow-up is not scheduled yet.', 'ok');
            } else {
                setCopilotStatus('followup', `Follow-up is set for ${state.copilot_followup_time}. Co-Pilot ${copilotAutonomySummary(state.copilot_autonomy_level)}.`, 'ok');
            }
        }

        function applyCopilotUiFromSettings() {
            setSettings(normalizeCopilotSettings(getSettings()));
            const settings = getSettings();
            if (deps.copilotEnabledSettingsToggle) deps.copilotEnabledSettingsToggle.checked = !!settings.copilot_enabled;
            if (deps.copilotMorningBriefToggle) deps.copilotMorningBriefToggle.checked = !!settings.copilot_morning_brief_enabled;
            if (deps.copilotBriefingTimeInput) deps.copilotBriefingTimeInput.value = normalizeCopilotTime(settings.copilot_morning_brief_time);
            if (deps.copilotFollowupToggle) deps.copilotFollowupToggle.checked = !!settings.copilot_followup_enabled;
            if (deps.copilotFollowupTimeInput) deps.copilotFollowupTimeInput.value = normalizeFollowupTime(settings.copilot_followup_time);
            if (deps.copilotAutonomyLevelInput) deps.copilotAutonomyLevelInput.value = String(settings.copilot_autonomy_level || 'suggest').trim() || 'suggest';
            if (deps.copilotMorningInstructionsInput) deps.copilotMorningInstructionsInput.value = String(settings.copilot_morning_brief_instructions || '');
            if (deps.copilotFollowupInstructionsInput) deps.copilotFollowupInstructionsInput.value = String(settings.copilot_followup_instructions || '');
            populateCopilotQuickstartOptions();
            refreshCopilotPanelUi();
        }

        function findCopilotSchedule(source, serverSchedules, localSchedules) {
            const combined = []
                .concat(Array.isArray(serverSchedules) ? serverSchedules : [])
                .concat(Array.isArray(localSchedules) ? localSchedules : []);
            return combined.find(function (item) {
                return String((item && item.source) || '').trim() === source;
            }) || null;
        }

        function updateCopilotStatusFromSchedules(serverSchedules, localSchedules) {
            const state = collectCopilotStateFromUi();
            if (!state.copilot_enabled) {
                setAllCopilotStatuses('Co-Pilot is off. Turn it on to activate scheduled Co-Pilots.');
                return;
            }
            copilotScheduleDefinitions(state).forEach(function (definition) {
                if (!definition.enabled) {
                    setCopilotStatus(definition.statusTarget, `Co-Pilot is on. ${definition.label.replace('Co-Pilot ', '')} is not scheduled yet.`, 'ok');
                    return;
                }
                const schedule = findCopilotSchedule(definition.source, serverSchedules, localSchedules);
                if (!schedule) {
                    setCopilotStatus(definition.statusTarget, `${definition.label.replace('Co-Pilot ', '')} is enabled, but not saved yet. Save your Settings to apply it.`, 'err');
                    return;
                }
                const nextRunText = schedule.next_run
                    ? new Date(schedule.next_run).toLocaleString()
                    : schedule.nextRun
                        ? new Date(schedule.nextRun).toLocaleString()
                        : definition.time;
                const sourceText = schedule.id === definition.localId ? 'local browser fallback' : 'server scheduler';
                setCopilotStatus(definition.statusTarget, `${definition.label.replace('Co-Pilot ', '')} active. Next run: ${nextRunText} via ${sourceText}.`, 'ok');
            });
        }

        return {
            normalizeCopilotTime: normalizeCopilotTime,
            normalizeFollowupTime: normalizeFollowupTime,
            normalizeCopilotSettings: normalizeCopilotSettings,
            collectCopilotStateFromUi: collectCopilotStateFromUi,
            copilotAutonomySummary: copilotAutonomySummary,
            setCopilotStatus: setCopilotStatus,
            setAllCopilotStatuses: setAllCopilotStatuses,
            syncCopilotEnabledToggles: syncCopilotEnabledToggles,
            computeCopilotFirstRunIso: computeCopilotFirstRunIso,
            buildCopilotMorningBriefGoal: buildCopilotMorningBriefGoal,
            buildCopilotFollowupGoal: buildCopilotFollowupGoal,
            copilotScheduleDefinitions: copilotScheduleDefinitions,
            upsertLocalCopilotSchedules: upsertLocalCopilotSchedules,
            syncCopilotSchedules: syncCopilotSchedules,
            saveCopilotSettings: saveCopilotSettings,
            populateCopilotQuickstartOptions: populateCopilotQuickstartOptions,
            refreshCopilotPanelUi: refreshCopilotPanelUi,
            applyCopilotUiFromSettings: applyCopilotUiFromSettings,
            findCopilotSchedule: findCopilotSchedule,
            updateCopilotStatusFromSchedules: updateCopilotStatusFromSchedules,
        };
    };
})();