// /stop-opencode-server command - Stop the single shared OpenCode server after inactivity checks.
// Checks ALL runtimes globally (not just per-directory) since there is only one server.
// Stopping it affects all projects.
import { ChannelType, MessageFlags, } from 'discord.js';
import { stopOpencodeServer, } from '../opencode.js';
import { getGlobalRuntimeInactivitySnapshot, disposeRuntimesForDirectory, getActiveRuntimeProjectDirectories, } from '../session-handler/thread-session-runtime.js';
import { resolveWorkingDirectory, SILENT_MESSAGE_FLAGS, } from '../discord-utils.js';
import { DEFAULT_RUNTIME_IDLE_MS, } from '../runtime-idle-sweeper.js';
function formatInactivityMinutes(inactiveForMs) {
    if (inactiveForMs === null) {
        return 'unknown';
    }
    return `${Math.floor(inactiveForMs / 60_000)}m`;
}
export async function handleStopOpencodeServerCommand({ command, }) {
    const channel = command.channel;
    if (!channel) {
        await command.reply({
            content: 'This command can only be used in a channel',
            flags: MessageFlags.Ephemeral | SILENT_MESSAGE_FLAGS,
        });
        return;
    }
    const isThread = [
        ChannelType.PublicThread,
        ChannelType.PrivateThread,
        ChannelType.AnnouncementThread,
    ].includes(channel.type);
    const isTextChannel = channel.type === ChannelType.GuildText;
    if (!isThread && !isTextChannel) {
        await command.reply({
            content: 'This command can only be used in text channels or threads',
            flags: MessageFlags.Ephemeral | SILENT_MESSAGE_FLAGS,
        });
        return;
    }
    const resolved = await resolveWorkingDirectory({
        channel: channel,
    });
    if (!resolved) {
        await command.reply({
            content: 'Could not determine project directory for this channel',
            flags: MessageFlags.Ephemeral | SILENT_MESSAGE_FLAGS,
        });
        return;
    }
    await command.deferReply({ flags: SILENT_MESSAGE_FLAGS });
    // Check ALL runtimes globally since stopping the server affects all projects
    const nowMs = Date.now();
    const globalSnapshot = getGlobalRuntimeInactivitySnapshot({ nowMs });
    const inactivityMs = globalSnapshot.inactiveForMs;
    if (globalSnapshot.hasNonIdleRuntime) {
        await command.editReply({
            content: `OpenCode server not stopped: activity is still in progress across ${globalSnapshot.runtimeCount} runtime(s). Last inactivity: ${formatInactivityMinutes(inactivityMs)}.`,
        });
        return;
    }
    if (globalSnapshot.runtimeCount > 0 && inactivityMs !== null && inactivityMs < DEFAULT_RUNTIME_IDLE_MS) {
        await command.editReply({
            content: `OpenCode server not stopped: global inactivity is ${formatInactivityMinutes(inactivityMs)} (needs at least 60m).`,
        });
        return;
    }
    // Dispose all runtimes across all directories before stopping the shared server
    const activeDirectories = getActiveRuntimeProjectDirectories();
    let totalDisposed = 0;
    for (const dir of activeDirectories) {
        totalDisposed += disposeRuntimesForDirectory({ directory: dir });
    }
    const stopped = await stopOpencodeServer();
    if (!stopped) {
        await command.editReply({
            content: `No running OpenCode server found. Last inactivity: ${formatInactivityMinutes(inactivityMs)}.`,
        });
        return;
    }
    await command.editReply({
        content: `OpenCode server stopped. Last inactivity: ${formatInactivityMinutes(inactivityMs)}. Disposed ${totalDisposed} runtime${totalDisposed === 1 ? '' : 's'}.`,
    });
}
