import { InlineKeyboard } from "grammy";
import { getArtifactTurnReport, cleanupArtifactStorage, inspectArtifactStorage, listRecentArtifactReports, planArtifactCleanup, removeArtifactTurn, } from "../../artifacts/artifacts.js";
import { ARTIFACT_DELIVERY_MODES, isArtifactDeliveryMode } from "../../artifacts/artifact-delivery.js";
import { buildArtifactActionsKeyboard, filterArtifactReports, } from "../shared/bot-rendering.js";
import { renderArtifactCleanupAction, renderArtifactDeliveryAction, renderArtifactReportsAction, renderArtifactUsageAction } from "../shared/channel-actions.js";
import { escapeHTML } from "../../core/format.js";
import { NOOP_PAGE_CALLBACK_DATA } from "./telegram-channel-runtime.js";
import { safeEditMessage, safeReply, } from "./telegram-output.js";
export function registerTelegramArtifactCommands(options) {
    const { bot, config } = options;
    bot.command("artifacts", async (ctx) => {
        const contextSession = await options.getContextSession(ctx, { deferThreadStart: true });
        if (!contextSession || !ctx.chat) {
            return;
        }
        const workspace = contextSession.session.getInfo().workspace;
        const rawText = ctx.message?.text ?? "";
        const argument = rawText.replace(/^\/artifacts(?:@\w+)?\s*/i, "").trim();
        const parts = argument.split(/\s+/).filter(Boolean);
        const subcommand = parts[0]?.toLowerCase();
        if (subcommand === "quota" || subcommand === "usage") {
            const rendered = renderArtifactUsageAction(await inspectArtifactStorage(workspace, {
                maxTotalBytes: config.artifactMaxTotalBytes,
                warnPercent: config.artifactWarnPercent,
            }));
            await safeReply(ctx, rendered.html, { fallbackText: rendered.plain });
            return;
        }
        if (subcommand === "cleanup") {
            const action = parts[1]?.toLowerCase();
            const cleanupOptions = {
                maxAgeMs: config.artifactRetentionDays * 24 * 60 * 60 * 1000,
                maxTurnDirs: config.artifactMaxTurnDirs,
                maxInboxDirs: config.artifactMaxInboxDirs,
                maxTotalBytes: config.artifactMaxTotalBytes,
            };
            const plan = action === "run"
                ? await cleanupArtifactStorage(workspace, cleanupOptions, false)
                : await planArtifactCleanup(workspace, cleanupOptions);
            const rendered = renderArtifactCleanupAction(plan);
            await safeReply(ctx, rendered.html, { fallbackText: rendered.plain });
            if (action === "run") {
                options.appendActivity?.(ctx, {
                    status: "info",
                    type: "artifact_cleanup",
                    threadId: contextSession.session.getInfo().threadId,
                    workspace,
                    agentId: contextSession.session.getInfo().agentId,
                    detail: `${plan.candidates.length} candidates, ${plan.removedBytes} bytes`,
                });
            }
            return;
        }
        if (subcommand === "delivery") {
            const requested = parts[1]?.toLowerCase();
            if (!requested) {
                const rendered = renderArtifactDeliveryAction(options.getArtifactDeliveryMode?.(ctx) ?? config.telegramArtifactDeliveryMode, "user");
                await safeReply(ctx, rendered.html, { fallbackText: rendered.plain });
                return;
            }
            if (requested === "default" || requested === "inherit") {
                const mode = await options.setArtifactDeliveryMode?.(ctx, null);
                const rendered = renderArtifactDeliveryAction(mode ?? config.telegramArtifactDeliveryMode, "user");
                await safeReply(ctx, rendered.html, { fallbackText: rendered.plain });
                return;
            }
            if (!isArtifactDeliveryMode(requested)) {
                const text = `Unknown artifact delivery mode. Use one of: ${ARTIFACT_DELIVERY_MODES.join(", ")}, default.`;
                await safeReply(ctx, escapeHTML(text), { fallbackText: text });
                return;
            }
            const mode = await options.setArtifactDeliveryMode?.(ctx, requested);
            const rendered = renderArtifactDeliveryAction(mode ?? requested, "user");
            await safeReply(ctx, rendered.html, { fallbackText: rendered.plain });
            return;
        }
        const reports = await listRecentArtifactReports(workspace, 10, config.maxFileSize);
        if (reports.length === 0) {
            await safeReply(ctx, escapeHTML("No generated artifacts found for this workspace."), {
                fallbackText: "No generated artifacts found for this workspace.",
            });
            return;
        }
        if (argument) {
            if (parts[0]?.toLowerCase() === "delete" && parts[1]) {
                const selected = reports.find((report) => report.turnId === parts[1] || report.turnId.startsWith(parts[1]));
                if (!selected) {
                    await safeReply(ctx, escapeHTML(`No artifact turn found for "${parts[1]}".`), {
                        fallbackText: `No artifact turn found for "${parts[1]}".`,
                    });
                    return;
                }
                const removed = await removeArtifactTurn(workspace, selected.turnId);
                const text = removed ? `Deleted artifact turn: ${selected.turnId}` : `Artifact turn not found: ${selected.turnId}`;
                await safeReply(ctx, escapeHTML(text), { fallbackText: text });
                if (removed) {
                    options.appendActivity?.(ctx, {
                        status: "info",
                        type: "artifact_deleted",
                        threadId: contextSession.session.getInfo().threadId,
                        workspace,
                        agentId: contextSession.session.getInfo().agentId,
                        detail: selected.turnId,
                    });
                }
                return;
            }
            const filtered = filterArtifactReports(reports, argument);
            if (filtered) {
                if (filtered.length === 0) {
                    await safeReply(ctx, escapeHTML(`No artifacts matched "${argument}".`), {
                        fallbackText: `No artifacts matched "${argument}".`,
                    });
                    return;
                }
                const rendered = renderArtifactReportsAction(filtered);
                await safeReply(ctx, rendered.html, {
                    fallbackText: rendered.plain,
                    replyMarkup: buildArtifactActionsKeyboard(filtered),
                });
                return;
            }
            const shouldZip = parts[0]?.toLowerCase() === "zip";
            const requestedTurn = shouldZip ? parts[1] : parts[0];
            const selected = !requestedTurn || requestedTurn.toLowerCase() === "latest"
                ? reports[0]
                : reports.find((report) => report.turnId === requestedTurn || report.turnId.startsWith(requestedTurn));
            if (!selected) {
                await safeReply(ctx, escapeHTML(`No artifact turn found for "${argument}".`), {
                    fallbackText: `No artifact turn found for "${argument}".`,
                });
                return;
            }
            if (shouldZip) {
                options.appendActivity?.(ctx, {
                    status: "info",
                    type: "artifact_zip_sent",
                    threadId: contextSession.session.getInfo().threadId,
                    workspace,
                    agentId: contextSession.session.getInfo().agentId,
                    detail: selected.turnId,
                });
                await options.deliverArtifactReportZip(ctx, ctx.chat.id, selected, ctx.message?.message_thread_id);
            }
            else {
                options.appendActivity?.(ctx, {
                    status: "info",
                    type: "artifacts_sent",
                    threadId: contextSession.session.getInfo().threadId,
                    workspace,
                    agentId: contextSession.session.getInfo().agentId,
                    detail: selected.turnId,
                });
                await options.deliverArtifactReport(ctx, ctx.chat.id, selected, ctx.message?.message_thread_id);
            }
            return;
        }
        const { html, plain } = renderArtifactReportsAction(reports);
        await safeReply(ctx, html, {
            fallbackText: plain,
            replyMarkup: buildArtifactActionsKeyboard(reports),
        });
    });
    bot.callbackQuery(/^artifact_(send|zip|delete|delete_confirm):([a-zA-Z0-9._-]+)$/, async (ctx) => {
        const action = ctx.match?.[1];
        const turnId = ctx.match?.[2];
        const chatId = ctx.chat?.id;
        const messageId = ctx.callbackQuery.message?.message_id;
        if (!action || !turnId || !chatId) {
            await ctx.answerCallbackQuery();
            return;
        }
        const contextSession = await options.getContextSession(ctx, { deferThreadStart: true });
        if (!contextSession) {
            await ctx.answerCallbackQuery({ text: "No context" });
            return;
        }
        const workspace = contextSession.session.getInfo().workspace;
        if (action === "delete") {
            await ctx.answerCallbackQuery({ text: "Confirm deletion" });
            const keyboard = new InlineKeyboard()
                .text("Delete artifacts", `artifact_delete_confirm:${turnId}`)
                .row()
                .text("Cancel", NOOP_PAGE_CALLBACK_DATA);
            const html = `<b>Delete artifact turn?</b>\n<code>${escapeHTML(turnId)}</code>`;
            const plain = `Delete artifact turn?\n${turnId}`;
            if (messageId) {
                await safeEditMessage(bot, chatId, messageId, html, { fallbackText: plain, replyMarkup: keyboard });
            }
            else {
                await safeReply(ctx, html, { fallbackText: plain, replyMarkup: keyboard });
            }
            return;
        }
        if (action === "delete_confirm") {
            const removed = await removeArtifactTurn(workspace, turnId);
            await ctx.answerCallbackQuery({ text: removed ? "Deleted" : "Already gone" });
            if (removed) {
                const info = contextSession.session.getInfo();
                options.appendActivity?.(ctx, {
                    status: "info",
                    type: "artifact_deleted",
                    threadId: info.threadId,
                    workspace,
                    agentId: info.agentId,
                    detail: turnId,
                });
            }
            const html = removed
                ? `<b>Deleted artifact turn:</b> <code>${escapeHTML(turnId)}</code>`
                : `<b>Artifact turn not found:</b> <code>${escapeHTML(turnId)}</code>`;
            const plain = removed ? `Deleted artifact turn: ${turnId}` : `Artifact turn not found: ${turnId}`;
            if (messageId) {
                await safeEditMessage(bot, chatId, messageId, html, { fallbackText: plain });
            }
            else {
                await safeReply(ctx, html, { fallbackText: plain });
            }
            return;
        }
        const report = await getArtifactTurnReport(workspace, turnId, config.maxFileSize);
        if (!report) {
            await ctx.answerCallbackQuery({ text: "Artifact turn not found" });
            return;
        }
        await ctx.answerCallbackQuery({ text: action === "zip" ? "Sending ZIP..." : "Sending artifacts..." });
        const info = contextSession.session.getInfo();
        options.appendActivity?.(ctx, {
            status: "info",
            type: action === "zip" ? "artifact_zip_sent" : "artifacts_sent",
            threadId: info.threadId,
            workspace,
            agentId: info.agentId,
            detail: turnId,
        });
        if (action === "zip") {
            await options.deliverArtifactReportZip(ctx, chatId, report, ctx.callbackQuery.message?.message_thread_id);
        }
        else {
            await options.deliverArtifactReport(ctx, chatId, report, ctx.callbackQuery.message?.message_thread_id);
        }
    });
}
