// /thinking command - Set the thinking level (variant) for the current session's model.
// Only works in threads with active sessions. Reads model variants from the provider API.
import { ActionRowBuilder, ChannelType, StringSelectMenuBuilder } from 'discord.js';
import crypto from 'node:crypto';
import { getSessionThinking, getThreadSession, setSessionThinking } from '../database.js';
import { resolveWorkingDirectory } from '../discord-utils.js';
import { createLogger, LogPrefix } from '../logger.js';
import { initializeOpencodeForDirectory } from '../opencode.js';
import { getThinkingValuesForModel, matchThinkingValue } from '../thinking-utils.js';
import { getCurrentModelInfo } from './model.js';
const thinkingLogger = createLogger(LogPrefix.THINKING);
// Store pending select menu contexts keyed by short hash (Discord custom_id max 100 chars)
const pendingContexts = new Map();
export async function handleThinkingCommand({ interaction, appId, }) {
    await interaction.deferReply({ ephemeral: true });
    const channel = interaction.channel;
    if (!channel) {
        await interaction.editReply({ content: 'This command can only be used in a channel.' });
        return;
    }
    const isThread = channel.type === ChannelType.PublicThread || channel.type === ChannelType.PrivateThread || channel.type === ChannelType.AnnouncementThread;
    if (!isThread) {
        await interaction.editReply({ content: 'This command can only be used in a thread with an active session.' });
        return;
    }
    const thread = channel;
    const sessionId = await getThreadSession(thread.id);
    if (!sessionId) {
        await interaction.editReply({ content: 'No current session in this thread. Start or resume a session first.' });
        return;
    }
    const resolved = await resolveWorkingDirectory({ channel: thread });
    if (!resolved) {
        await interaction.editReply({ content: 'This channel is not configured with a project directory.' });
        return;
    }
    if (resolved.channelAppId && resolved.channelAppId !== appId) {
        await interaction.editReply({ content: 'This channel is not configured for this bot.' });
        return;
    }
    const getClient = await initializeOpencodeForDirectory(resolved.projectDirectory);
    if (getClient instanceof Error) {
        await interaction.editReply({ content: getClient.message });
        return;
    }
    const modelInfo = await getCurrentModelInfo({
        sessionId,
        channelId: thread.parentId || thread.id,
        appId: resolved.channelAppId || appId,
        getClient,
    });
    if (modelInfo.type === 'none') {
        await interaction.editReply({ content: 'No model selected. Set a model first with `/model`.' });
        return;
    }
    const providersResponse = await getClient().provider.list({ query: { directory: resolved.workingDirectory } });
    if (!providersResponse.data) {
        await interaction.editReply({ content: 'Failed to load provider metadata.' });
        return;
    }
    const thinkingValues = getThinkingValuesForModel({
        providers: providersResponse.data.all,
        providerId: modelInfo.providerID,
        modelId: modelInfo.modelID,
    });
    if (thinkingValues.length === 0) {
        await interaction.editReply({ content: `Model \`${modelInfo.model}\` does not expose thinking levels.` });
        return;
    }
    // If value provided directly, set it immediately
    const requestedValue = interaction.options.getString('value');
    if (requestedValue) {
        const matched = matchThinkingValue({ requestedValue, availableValues: thinkingValues });
        if (!matched) {
            await interaction.editReply({ content: `Invalid thinking value "${requestedValue}". Available: ${thinkingValues.join(', ')}` });
            return;
        }
        await setSessionThinking(sessionId, matched);
        thinkingLogger.log(`Set ${matched} for session ${sessionId}`);
        await interaction.editReply({ content: `Thinking set to \`${matched}\` for this session.\nModel: \`${modelInfo.model}\`` });
        return;
    }
    // Show select menu
    const currentThinking = await getSessionThinking(sessionId);
    const contextHash = crypto.randomBytes(8).toString('hex');
    pendingContexts.set(contextHash, { sessionId, threadId: thread.id, modelDisplay: modelInfo.model, thinkingValues });
    const options = thinkingValues.slice(0, 25).map((value, i) => ({
        label: value.slice(0, 100),
        value: `v_${i}`,
        description: `Use ${value} thinking`.slice(0, 100),
    }));
    const row = new ActionRowBuilder().addComponents(new StringSelectMenuBuilder()
        .setCustomId(`thinking_value:${contextHash}`)
        .setPlaceholder('Select a thinking level')
        .addOptions(options));
    const currentText = currentThinking ? `**Current:** \`${currentThinking}\`` : '**Current:** none';
    await interaction.editReply({
        content: `**Set Thinking Level**\n${currentText}\n**Model:** \`${modelInfo.model}\`\nSelect a thinking level:`,
        components: [row],
    });
}
export async function handleThinkingValueSelectMenu(interaction) {
    await interaction.deferUpdate();
    const contextHash = interaction.customId.replace('thinking_value:', '');
    const context = pendingContexts.get(contextHash);
    if (!context) {
        await interaction.editReply({ content: 'Selection expired. Run /thinking again.', components: [] });
        return;
    }
    pendingContexts.delete(contextHash);
    const currentSessionId = await getThreadSession(context.threadId);
    if (!currentSessionId || currentSessionId !== context.sessionId) {
        await interaction.editReply({ content: 'Session changed. Run /thinking again.', components: [] });
        return;
    }
    const selectedIndex = Number(interaction.values[0]?.replace(/^v_/, ''));
    const selectedValue = Number.isInteger(selectedIndex) ? context.thinkingValues[selectedIndex] : undefined;
    if (!selectedValue) {
        await interaction.editReply({ content: 'Invalid selection. Run /thinking again.', components: [] });
        return;
    }
    await setSessionThinking(context.sessionId, selectedValue);
    thinkingLogger.log(`Set ${selectedValue} for session ${context.sessionId}`);
    await interaction.editReply({
        content: `Thinking set to \`${selectedValue}\` for this session.\nModel: \`${context.modelDisplay}\``,
        components: [],
    });
}
