import { jsx as _jsx } from "react/jsx-runtime";
import { createLLMClient } from '../client-factory.js';
import { ErrorMessage, SuccessMessage, WarningMessage, } from '../components/message-box.js';
import { reloadAppConfig } from '../config/index.js';
import { formatConfigLintIssue, lintProviderConfig } from '../config/lint.js';
import { loadAllProviderConfigs } from '../config/mcp-config-loader.js';
import { saveTune, updateLastUsed } from '../config/preferences.js';
import { getToolManager } from '../message-handler.js';
import { getModelContextLimit, getSessionContextLimit } from '../models/index.js';
import { generateKey } from '../session/key-generator.js';
import { setAutoCompactMode, setAutoCompactThreshold, } from '../utils/auto-compact.js';
export function useModeHandlers({ client, currentModel, currentProvider, setClient, setCurrentModel, setCurrentProvider, setCurrentProviderConfig, setMessages, messages, getMessageTokens, setActiveMode, setIsSettingsMode, addToChatQueue, reinitializeMCPServers, setTune, }) {
    // Generic enter/exit helpers
    const enterMode = (mode) => setActiveMode(mode);
    const exitMode = () => setActiveMode(null);
    // Switching models keeps the conversation (messages are model-agnostic and
    // the client is stateless). The one real risk is downsizing to a model whose
    // context window can't hold the existing history — surface that as a warning
    // so the user can /compact rather than silently overflowing the next request.
    const warnIfHistoryWontFit = async (model, providerConfig) => {
        if (messages.length === 0)
            return;
        try {
            const used = messages.reduce((sum, m) => sum + getMessageTokens(m), 0);
            const limit = getSessionContextLimit() ??
                (await getModelContextLimit(model, {
                    providerConfig: providerConfig ?? undefined,
                }));
            if (limit && used > limit) {
                addToChatQueue(_jsx(WarningMessage, { message: `History (~${used.toLocaleString()} tokens) exceeds ${model}'s ~${limit.toLocaleString()} token window. Run /compact or /clear before continuing.`, hideBox: true }, generateKey('model-context-overflow')));
            }
        }
        catch {
            // Best-effort: skip the warning if the model's limit can't be resolved.
        }
    };
    // Handle model selection. The model picker lists every model across every
    // provider, so a selection may also switch the active provider. Staying on
    // the same provider just swaps the model on the live client; crossing to a
    // different provider spins up a fresh client (and re-runs config lint).
    const handleModelSelect = async (selectedProvider, selectedModel) => {
        const sameProvider = selectedProvider === currentProvider;
        if (sameProvider && selectedModel === currentModel) {
            exitMode();
            return;
        }
        if (sameProvider) {
            if (client) {
                client.setModel(selectedModel);
                setCurrentModel(selectedModel);
                setCurrentProviderConfig(client.getProviderConfig());
                // Conversation is kept across model switches (see warnIfHistoryWontFit).
                // Update preferences
                updateLastUsed(currentProvider, selectedModel);
                addToChatQueue(_jsx(SuccessMessage, { message: `Model changed to: ${selectedModel}.`, hideBox: true }, generateKey('model-changed')));
                await warnIfHistoryWontFit(selectedModel, client.getProviderConfig());
            }
            exitMode();
            return;
        }
        // Different provider: create a new client targeting the chosen
        // provider and model.
        try {
            const { client: newClient, actualProvider } = await createLLMClient(selectedProvider, selectedModel);
            if (actualProvider !== selectedProvider) {
                addToChatQueue(_jsx(ErrorMessage, { message: `${selectedProvider} is not available. Please ensure it's properly configured in agents.config.json.`, hideBox: true }, generateKey('provider-forced')));
                return;
            }
            setClient(newClient);
            setCurrentProvider(actualProvider);
            setCurrentProviderConfig(newClient.getProviderConfig());
            const newModel = newClient.getCurrentModel();
            setCurrentModel(newModel);
            // Conversation is kept across provider/model switches.
            updateLastUsed(actualProvider, newModel);
            addToChatQueue(_jsx(SuccessMessage, { message: `Model changed to: ${newModel} (${actualProvider}).`, hideBox: true }, generateKey('model-changed')));
            await warnIfHistoryWontFit(newModel, newClient.getProviderConfig());
            // Re-run lint scoped to the newly active provider so any
            // misconfiguration becomes visible right when it would start
            // taking effect, rather than getting buried in startup output.
            const newProviderConfig = loadAllProviderConfigs().find(p => p.name === actualProvider);
            if (newProviderConfig) {
                for (const issue of lintProviderConfig(newProviderConfig)) {
                    addToChatQueue(_jsx(WarningMessage, { message: formatConfigLintIssue(issue), hideBox: true }, generateKey(`config-lint-${issue.provider}`)));
                }
            }
        }
        catch (error) {
            addToChatQueue(_jsx(ErrorMessage, { message: `Failed to switch to ${selectedProvider}: ${String(error)}`, hideBox: true }, generateKey('provider-error')));
        }
        exitMode();
    };
    // Handle config wizard complete - reinitializes client and MCP servers
    const handleConfigWizardComplete = async (configPath) => {
        exitMode();
        if (configPath) {
            addToChatQueue(_jsx(SuccessMessage, { message: `Configuration saved to: ${configPath}.`, hideBox: true }, generateKey('config-wizard-complete')));
            reloadAppConfig();
            try {
                const { client: newClient, actualProvider } = await createLLMClient();
                setClient(newClient);
                setCurrentProvider(actualProvider);
                setCurrentProviderConfig(newClient.getProviderConfig());
                const newModel = newClient.getCurrentModel();
                setCurrentModel(newModel);
                setMessages([]);
                await newClient.clearContext();
                const toolManager = getToolManager();
                if (toolManager) {
                    try {
                        await reinitializeMCPServers(toolManager);
                        addToChatQueue(_jsx(SuccessMessage, { message: "MCP servers reinitialized with new configuration.", hideBox: true }, generateKey('mcp-reinit')));
                    }
                    catch (mcpError) {
                        addToChatQueue(_jsx(ErrorMessage, { message: `Failed to reinitialize MCP servers: ${String(mcpError)}`, hideBox: true }, generateKey('mcp-reinit-error')));
                    }
                }
                addToChatQueue(_jsx(SuccessMessage, { message: `Ready! Using provider: ${actualProvider}, model: ${newModel}`, hideBox: true }, generateKey('config-init')));
            }
            catch (error) {
                addToChatQueue(_jsx(ErrorMessage, { message: `Failed to initialize with new configuration: ${String(error)}`, hideBox: true }, generateKey('config-init-error')));
            }
        }
    };
    // Handle MCP wizard complete - reinitializes MCP servers
    const handleMcpWizardComplete = async (configPath) => {
        exitMode();
        if (configPath) {
            addToChatQueue(_jsx(SuccessMessage, { message: `MCP configuration saved to: ${configPath}.`, hideBox: true }, generateKey('mcp-wizard-complete')));
            reloadAppConfig();
            const toolManager = getToolManager();
            if (toolManager) {
                try {
                    await reinitializeMCPServers(toolManager);
                    addToChatQueue(_jsx(SuccessMessage, { message: "MCP servers reinitialized with new configuration.", hideBox: true }, generateKey('mcp-reinit')));
                }
                catch (mcpError) {
                    addToChatQueue(_jsx(ErrorMessage, { message: `Failed to reinitialize MCP servers: ${String(mcpError)}`, hideBox: true }, generateKey('mcp-reinit-error')));
                }
            }
        }
    };
    // Handle model mode selection
    const handleTuneSelect = async (config) => {
        setTune(config);
        saveTune(config);
        // Apply/remove auto-compact session overrides
        if (config.enabled && config.aggressiveCompact) {
            setAutoCompactThreshold(40);
            setAutoCompactMode('aggressive');
        }
        else {
            setAutoCompactThreshold(null);
            setAutoCompactMode(null);
        }
        // Clear conversation when toggling — tool profiles change what's available
        setMessages([]);
        if (client) {
            await client.clearContext();
        }
        const parts = [];
        if (config.enabled) {
            parts.push(`profile: ${config.toolProfile}`);
            if (config.aggressiveCompact)
                parts.push('aggressive compact');
            addToChatQueue(_jsx(SuccessMessage, { message: `Tune enabled (${parts.join(', ')}). Chat history cleared.`, hideBox: true }, generateKey('tune')));
        }
        else {
            addToChatQueue(_jsx(SuccessMessage, { message: "Tune disabled. Chat history cleared.", hideBox: true }, generateKey('tune')));
        }
        exitMode();
    };
    return {
        enterMode,
        exitMode,
        // Convenience enter helpers
        enterModelSelectionMode: () => enterMode('model'),
        enterModelDatabaseMode: () => enterMode('modelDatabase'),
        enterConfigWizardMode: () => enterMode('configWizard'),
        enterMcpWizardMode: () => enterMode('mcpWizard'),
        enterExplorerMode: () => enterMode('explorer'),
        enterIdeSelectionMode: () => enterMode('ideSelection'),
        enterSettingsMode: () => setIsSettingsMode(true),
        // Cancel/complete handlers
        handleModelSelect,
        handleModelSelectionCancel: exitMode,
        handleModelDatabaseCancel: exitMode,
        handleConfigWizardComplete,
        handleConfigWizardCancel: exitMode,
        handleMcpWizardComplete,
        handleMcpWizardCancel: exitMode,
        handleSettingsCancel: () => setIsSettingsMode(false),
        handleExplorerCancel: exitMode,
        handleIdeSelectionCancel: exitMode,
        // Model mode
        enterTune: () => enterMode('tune'),
        handleTuneSelect,
        handleTuneCancel: exitMode,
    };
}
//# sourceMappingURL=useModeHandlers.js.map