/**
 * @license
 * Copyright 2025 Vybestack LLC
 * SPDX-License-Identifier: Apache-2.0
 */
import * as fsPromises from 'fs/promises';
import React from 'react';
import { Text } from 'ink';
import { Colors } from '../colors.js';
import { CommandKind, } from './types.js';
import { decodeTagName, EmojiFilter, } from '@vybestack/llxprt-code-core';
import path from 'path';
import { MessageType } from '../types.js';
const getSavedChatTags = async (context, mtSortDesc) => {
    const cfg = context.services.config;
    const geminiDir = cfg?.storage?.getProjectTempDir();
    if (!geminiDir) {
        return [];
    }
    try {
        const file_head = 'checkpoint-';
        const file_tail = '.json';
        const files = await fsPromises.readdir(geminiDir);
        const chatDetails = [];
        for (const file of files) {
            if (file.startsWith(file_head) && file.endsWith(file_tail)) {
                const filePath = path.join(geminiDir, file);
                const stats = await fsPromises.stat(filePath);
                const tagName = file.slice(file_head.length, -file_tail.length);
                chatDetails.push({
                    name: decodeTagName(tagName),
                    mtime: stats.mtime,
                });
            }
        }
        chatDetails.sort((a, b) => mtSortDesc
            ? b.mtime.getTime() - a.mtime.getTime()
            : a.mtime.getTime() - b.mtime.getTime());
        return chatDetails;
    }
    catch (_err) {
        return [];
    }
};
const listCommand = {
    name: 'list',
    description: 'List saved conversation checkpoints',
    kind: CommandKind.BUILT_IN,
    action: async (context) => {
        const chatDetails = await getSavedChatTags(context, false);
        if (chatDetails.length === 0) {
            return {
                type: 'message',
                messageType: 'info',
                content: 'No saved conversation checkpoints found.',
            };
        }
        const maxNameLength = Math.max(...chatDetails.map((chat) => chat.name.length));
        let message = 'List of saved conversations:\n\n';
        for (const chat of chatDetails) {
            const paddedName = chat.name.padEnd(maxNameLength, ' ');
            const isoString = chat.mtime.toISOString();
            const match = isoString.match(/(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})/);
            const formattedDate = match ? `${match[1]} ${match[2]}` : 'Invalid Date';
            message += `  - \u001b[36m${paddedName}\u001b[0m  \u001b[90m(saved on ${formattedDate})\u001b[0m\n`;
        }
        message += `\n\u001b[90mNote: Newest last, oldest first\u001b[0m`;
        return {
            type: 'message',
            messageType: 'info',
            content: message,
        };
    },
};
const saveCommand = {
    name: 'save',
    description: 'Save the current conversation as a checkpoint. Usage: /chat save <tag>',
    kind: CommandKind.BUILT_IN,
    action: async (context, args) => {
        const tag = args.trim();
        if (!tag) {
            return {
                type: 'message',
                messageType: 'error',
                content: 'Missing tag. Usage: /chat save <tag>',
            };
        }
        const { logger, config } = context.services;
        await logger.initialize();
        // Check for overwrite confirmation first
        if (!context.overwriteConfirmed) {
            const exists = await logger.checkpointExists(tag);
            if (exists) {
                return {
                    type: 'confirm_action',
                    prompt: React.createElement(Text, null, 'A checkpoint with the tag ', React.createElement(Text, { color: Colors.AccentPurple }, tag), ' already exists. Do you want to overwrite it?'),
                    originalInvocation: {
                        raw: context.invocation?.raw || `/chat save ${tag}`,
                    },
                };
            }
        }
        const client = config?.getGeminiClient();
        // Check if chat is initialized before accessing it
        if (!client?.hasChatInitialized()) {
            return {
                type: 'message',
                messageType: 'error',
                content: 'No chat history available to save.',
            };
        }
        const chat = client.getChat();
        const history = chat.getHistory();
        if (history.length > 2) {
            await logger.saveCheckpoint(history, tag);
            return {
                type: 'message',
                messageType: 'info',
                content: `Conversation checkpoint saved with tag: ${decodeTagName(tag)}.`,
            };
        }
        else {
            return {
                type: 'message',
                messageType: 'info',
                content: 'No conversation found to save.',
            };
        }
    },
};
const resumeCommand = {
    name: 'resume',
    altNames: ['load'],
    description: 'Resume a conversation from a checkpoint. Usage: /chat resume <tag>',
    kind: CommandKind.BUILT_IN,
    action: async (context, args) => {
        const tag = args.trim();
        if (!tag) {
            return {
                type: 'message',
                messageType: 'error',
                content: 'Missing tag. Usage: /chat resume <tag>',
            };
        }
        const { logger, config } = context.services;
        await logger.initialize();
        // Get emoji filter mode from settings
        const emojiFilterMode = config?.getEphemeralSetting('emojifilter') || 'auto';
        // Create emoji filter if not in 'allowed' mode
        const emojiFilter = emojiFilterMode !== 'allowed'
            ? new EmojiFilter({ mode: emojiFilterMode })
            : undefined;
        const checkpoint = await logger.loadCheckpoint(tag);
        let conversation = checkpoint.history;
        // Apply emoji filtering if needed
        if (emojiFilter) {
            conversation = conversation.map((item) => {
                const filteredItem = { ...item };
                if (Array.isArray(filteredItem.parts)) {
                    filteredItem.parts = filteredItem.parts.map((part) => {
                        if (part.text) {
                            const filterResult = emojiFilter.filterText(part.text);
                            return { ...part, text: filterResult.filtered };
                        }
                        return part;
                    });
                }
                return filteredItem;
            });
        }
        if (conversation.length === 0) {
            return {
                type: 'message',
                messageType: 'info',
                content: `No saved checkpoint found with tag: ${decodeTagName(tag)}.`,
            };
        }
        const rolemap = {
            user: MessageType.USER,
            model: MessageType.GEMINI,
        };
        const uiHistory = [];
        let hasSystemPrompt = false;
        let i = 0;
        for (const item of conversation) {
            i += 1;
            const text = item.parts
                ?.filter((m) => !!m.text)
                .map((m) => m.text)
                .join('') || '';
            if (!text) {
                continue;
            }
            if (i === 1 && text.match(/context for our chat/)) {
                hasSystemPrompt = true;
            }
            if (i > 2 || !hasSystemPrompt) {
                uiHistory.push({
                    type: (item.role && rolemap[item.role]) || MessageType.GEMINI,
                    text,
                });
            }
        }
        return {
            type: 'load_history',
            history: uiHistory,
            clientHistory: conversation,
        };
    },
    completion: async (context, partialArg) => {
        const chatDetails = await getSavedChatTags(context, true);
        return chatDetails
            .map((chat) => chat.name)
            .filter((name) => name.startsWith(partialArg));
    },
};
const deleteCommand = {
    name: 'delete',
    description: 'Delete a conversation checkpoint. Usage: /chat delete <tag>',
    kind: CommandKind.BUILT_IN,
    action: async (context, args) => {
        const tag = args.trim();
        if (!tag) {
            return {
                type: 'message',
                messageType: 'error',
                content: 'Missing tag. Usage: /chat delete <tag>',
            };
        }
        const { logger } = context.services;
        await logger.initialize();
        const deleted = await logger.deleteCheckpoint(tag);
        if (deleted) {
            return {
                type: 'message',
                messageType: 'info',
                content: `Conversation checkpoint '${decodeTagName(tag)}' has been deleted.`,
            };
        }
        else {
            return {
                type: 'message',
                messageType: 'error',
                content: `Error: No checkpoint found with tag '${decodeTagName(tag)}'.`,
            };
        }
    },
    completion: async (context, partialArg) => {
        const chatDetails = await getSavedChatTags(context, true);
        return chatDetails
            .map((chat) => chat.name)
            .filter((name) => name.startsWith(partialArg));
    },
};
export const chatCommand = {
    name: 'chat',
    description: 'Manage conversation history.',
    kind: CommandKind.BUILT_IN,
    subCommands: [listCommand, saveCommand, resumeCommand, deleteCommand],
};
//# sourceMappingURL=chatCommand.js.map