"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runConversationSimulation = runConversationSimulation;
const conversationSimulator_1 = require("./conversationSimulator");
/**
 * Attempts to repair malformed JSON by closing unterminated strings and objects
 */
function repairJsonString(jsonString) {
    let repaired = jsonString.trim();
    // Track if we're inside a string
    let inString = false;
    let escapeNext = false;
    let braceDepth = 0;
    let bracketDepth = 0;
    for (let i = 0; i < repaired.length; i++) {
        const char = repaired[i];
        if (escapeNext) {
            escapeNext = false;
            continue;
        }
        if (char === '\\') {
            escapeNext = true;
            continue;
        }
        if (char === '"' && !escapeNext) {
            inString = !inString;
        }
        else if (!inString) {
            if (char === '{') {
                braceDepth++;
            }
            if (char === '}') {
                braceDepth--;
            }
            if (char === '[') {
                bracketDepth++;
            }
            if (char === ']') {
                bracketDepth--;
            }
        }
    }
    // If we're still in a string at the end, close it
    if (inString) {
        // Find the last unclosed string and close it
        repaired += '"';
    }
    // Close any unclosed braces/brackets
    while (braceDepth > 0) {
        repaired += '}';
        braceDepth--;
    }
    while (bracketDepth > 0) {
        repaired += ']';
        bracketDepth--;
    }
    return repaired;
}
async function runConversationSimulation(callbackModel, azureProvider, conversationParams, total, cliApiClient, cliCall = false) {
    try {
        // convert string[] to Record<string, number>
        const intentionMap = conversationParams.userIntentions.reduce((acc, intent) => {
            acc[intent] = 1;
            return acc;
        }, {});
        const azureSimulatorModel = {
            async generate(prompt) {
                try {
                    const response = await azureProvider.callApi(prompt);
                    if (response.error) {
                        throw new Error(`Azure API error: ${response.error}`);
                    }
                    total.cost = total.cost.plus(response.cost ?? 0);
                    total.tokenUsage.prompt = total.tokenUsage.prompt.plus(response.tokenUsage?.prompt ?? 0);
                    total.tokenUsage.completion = total.tokenUsage.completion.plus(response.tokenUsage?.completion ?? 0);
                    total.tokenUsage.total = total.tokenUsage.total.plus(response.tokenUsage?.total ?? 0);
                    total.tokenUsage.cached = total.tokenUsage.cached.plus(response?.tokenUsage?.cached ?? 0);
                    const content = response.output;
                    const cost = response.tokenUsage?.total ?? 0;
                    // Handle different response formats
                    let json;
                    if (typeof content === 'string') {
                        // Check if the response is wrapped in markdown code blocks
                        const markdownJsonMatch = content.match(/```(?:json)?\s*(\{[\s\S]*?\})\s*```/);
                        let jsonString = content;
                        if (markdownJsonMatch) {
                            jsonString = markdownJsonMatch[1];
                        }
                        // Convert Python-style booleans to JavaScript booleans
                        jsonString = jsonString.replace(/\bFalse\b/g, 'false').replace(/\bTrue\b/g, 'true');
                        try {
                            json = JSON.parse(jsonString);
                        }
                        catch (err) {
                            // Attempt to repair malformed JSON
                            try {
                                const repairedJson = repairJsonString(jsonString);
                                json = JSON.parse(repairedJson);
                                console.warn('Successfully repaired malformed JSON response');
                            }
                            catch (repairErr) {
                                // If repair fails, try to extract a partial result
                                /*  console.log('Failed to parse JSON response (original and repaired):', {
                                   original: jsonString.substring(0, 500),
                                   error: err instanceof Error ? err.message : String(err),
                                   repairError: repairErr instanceof Error ? repairErr.message : String(repairErr),
                                 });
                                  */
                                // Try to extract just the simulated_input field if it exists
                                // Match "simulated_input": "..." where the string might be unterminated
                                const simulatedInputMatch = jsonString.match(/"simulated_input"\s*:\s*"([^"]*(?:"|$))/);
                                if (simulatedInputMatch && simulatedInputMatch[1]) {
                                    // Remove trailing quote if present, and clean up the string
                                    let partialInput = simulatedInputMatch[1].replace(/^"|"$/g, '').trim();
                                    // If the string was cut off, add ellipsis to indicate truncation
                                    if (!jsonString.includes(`"simulated_input": "${partialInput}"`)) {
                                        partialInput = partialInput.trim();
                                    }
                                    json = { simulated_input: partialInput || 'I need more information.' };
                                    //console.warn('Using partial extracted simulated_input:', partialInput);
                                }
                                else {
                                    // Last resort: use a default structure
                                    json = { simulated_input: 'I need more information.' };
                                    //console.warn('Using fallback default response due to JSON parse failure');
                                }
                            }
                        }
                    }
                    else if (typeof content === 'object' && content !== null) {
                        // If content is already an object, use it directly
                        json = content;
                    }
                    else {
                        throw new Error(`Unexpected response format: ${typeof content}`);
                    }
                    return { result: json, cost };
                }
                catch (error) {
                    console.error('Error in azureSimulatorModel.generate:', error);
                    throw error;
                }
            },
            getModelName() {
                return 'azure-chat';
            },
        };
        const simulator = new conversationSimulator_1.ConversationSimulator({
            userIntentions: intentionMap,
            userProfileItems: conversationParams.userProfiles || [],
            openingMessage: conversationParams.openingMessage,
            simulatorModel: azureSimulatorModel,
            cliApiClient,
            total,
        });
        const modelCallback = async (input, params) => {
            try {
                const historyStr = params.conversationHistory.map((t) => `${t.role}: ${t.content}`).join(' ');
                const prompt = `Conversation so far: ${historyStr} User: ${input}`;
                const response = await callbackModel.generate(prompt);
                // Handle null or undefined response
                if (!response) {
                    console.error('Model callback returned null or undefined response');
                    return 'Error: No response from model';
                }
                // Handle error in response
                if ('error' in response && response.error) {
                    console.error('Model callback returned error:', response.error);
                    return `Error: ${typeof response.error === 'string' ? response.error : JSON.stringify(response.error)}`;
                }
                // Handle null or undefined result
                if (!response.result) {
                    console.error('Model callback returned null or undefined result');
                    return 'Error: No result from model';
                }
                if (typeof response.result === 'string') {
                    return response.result;
                }
                if (response.result && typeof response.result === 'object' && 'content' in response.result) {
                    return response.result.content;
                }
                return JSON.stringify(response.result);
            }
            catch (error) {
                console.error('Error in modelCallback:', error);
                const errorMessage = error instanceof Error ? error.message : String(error);
                return `Error: ${errorMessage}`;
            }
        };
        const conversations = await simulator.simulate(modelCallback, conversationParams.minimumTurns, conversationParams.maximumTurns, conversationParams.chatStopCriteria, cliCall);
        return conversations;
    }
    catch (error) {
        console.error('Error in runConversationSimulation:', error);
        throw error;
    }
}
//# sourceMappingURL=updatedConversation.js.map