// src/Conversation.d.ts

import { Tool } from './Tool';
import { Toolpack } from './Toolpack';
import { ContentPart } from './lib/utils'; // Import ContentPart type

/**
 * Defines the structure of a message within the conversation history.
 */
export interface Message {
    /** The role of the entity sending the message. */
    role: 'user' | 'assistant' | 'tool' | 'system' | 'error';
    /**
     * The content of the message.
     * - For 'user' and 'assistant': Typically a string or an array of ContentPart objects.
     * - For 'tool': Represents the normalized result content after execution (Array<ContentPart>).
     * - For 'system': An array of ContentPart objects constructed internally.
     * - For 'error': A string describing an internal error.
     */
    content: string | ContentPart[];
    /** Identifier for a tool call (present on 'tool' role messages). */
    callId?: string;
    /** Tool name (present on 'tool' role messages). */
    name?: string;
    /** Parsed parameters for the tool call (present on 'tool' role messages). */
    params?: Record<string, any>;
    /** Raw input provided for the tool call (present on 'tool' role messages). */
    raw?: string | null;
    /** The original, unnormalized result from the tool execution (present on 'tool' role messages after execution). */
    result?: any;
    /** Error message if tool execution failed or normalization produced an error (present on 'tool' and 'error' role messages). */
    error?: any;
}

/**
 * Options for configuring the Conversation instance.
 */
export interface ConversationOptions {
    /** An array of toolpack names to be enabled by default when the conversation starts. */
    initialEnabledToolpacks?: string[];
}

/**
 * Options passed to the `llmCallback` function.
 */
export interface LlmCallbackOptions {
    /** Indicates if the LLM response should be streamed. Defaults to true. */
    stream?: boolean;
    /** Add other LLM-specific options here if needed (e.g., temperature, max_tokens). */
    [key: string]: any;
}

/**
 * Type definition for the asynchronous generator function required by the Conversation constructor.
 * This function is responsible for interacting with the underlying Large Language Model.
 *
 * @param messages The current conversation history, formatted for the LLM.
 * @param options Options for the LLM call (e.g., streaming control).
 * @returns An asynchronous generator that yields string chunks of the LLM's response when streaming.
 */
export type LlmCallback = (
    messages: Message[],
    options: LlmCallbackOptions
) => AsyncGenerator<string>;

/**
 * Represents an element that can be included in the system prompt definition.
 * Can be a simple string, a Tool instance, a Toolpack instance,
 * a structured content part, or an async function that resolves to one of these or an array of these.
 */
export type ContentDefinitionItem =
    | string
    | Tool
    | Toolpack
    | ContentPart
    | ((conversation: Conversation, ...args: any[]) => Promise<ContentDefinitionItem | ContentDefinitionItem[] | null | undefined>);


/**
 * Represents the different types of events yielded by the `send` method's async generator.
 */
export type ConversationEvent =
    | { type: 'assistant'; role: 'assistant'; content: string } // LLM text chunk
    | { type: 'tool.generating'; role: 'tool.generating'; callId: string; name: string; params: Record<string, any>; rawChunk: string; raw: string } // Partial raw content for a tool
    | { type: 'tool.calling'; role: 'tool.calling'; callId: string; name: string; params: Record<string, any>; raw: string | null } // Tool call initiated
    | { type: 'tool'; role: 'tool'; callId: string; name: string; params: Record<string, any>; raw: string | null; result: any; content: ContentPart[]; error?: any } // Tool result processed
    | { type: 'error'; role: 'error'; content: string }; // Internal error occurred


/**
 * Manages a conversation with an LLM, handling message history, tool integration,
 * streaming responses, and function call execution flow.
 */
export declare class Conversation {
    #llmCallback: LlmCallback;
    #contentDefinition: ContentDefinitionItem[];
    #options: ConversationOptions;
    #invokeArgs: any[];
    #activeToolsMap: Map<string, Tool>;
    #allDefinedToolpacksMap: Map<string, Toolpack>;
    #functionTag: string;
    #resultTag: string;
    #functionCompleteRegex: RegExp;
    #functionStartRegex: RegExp;
    #functionEndRegexStr: string;

    /**
     * The history of messages in the conversation. Publicly accessible for inspection.
     * Modifying this array directly is not recommended; use the `send` method.
     */
    messages: Message[];

    /**
     * A set containing the names of toolpacks currently enabled for use.
     * Can be modified directly to enable/disable toolpacks between turns,
     * but changes only take effect on the *next* call to `send`.
     */
    enabledToolpacks: Set<string>;

    /**
     * Creates a new Conversation instance.
     * @param llmCallback An async generator function that takes the message history and options,
     *                    and yields string chunks from the LLM response.
     * @param options Configuration options for the conversation.
     * @throws {Error} If llmCallback is not an async generator function.
     */
    constructor(llmCallback: LlmCallback, options?: ConversationOptions);

    /**
     * Defines the content and tools available in the system prompt.
     * This replaces any previous definition. Call this before the first `send`.
     * @param definition An array containing strings, Tool instances, Toolpack instances,
     *                   content objects (like { type: 'image', ... }), or async functions
     *                   that resolve to these types or arrays of them.
     * @returns The Conversation instance for chaining.
     * @throws {Error} If the definition is not an array.
     */
    content(definition: ContentDefinitionItem[]): this;

    /**
     * Sends a user message to the LLM and processes the response, handling tool calls.
     * Returns an async generator that yields events representing the conversation flow
     * (assistant text chunks, tool call initiation, tool results, errors).
     *
     * @param messageContent The user's message content (string, array of content parts, or a user message object).
     * @param args Additional arguments to be passed to any tool action functions invoked during this turn.
     * @returns An async generator yielding `ConversationEvent` objects.
     * @throws {Error} If the messageContent format is invalid.
     */
    send(messageContent: string | ContentPart | ContentPart[] | Message, ...args: any[]): AsyncGenerator<ConversationEvent>;

    #addEnableToolpackTool(): void;
    #buildConversationState(): Promise<ContentPart[]>;
    #prepareMessagesForLLM(systemContent: ContentPart[]): Message[];
    #invokeAndProcess(): AsyncGenerator<ConversationEvent>;
}