import { CommonRequestOptions } from '@xsai/shared';

type FinishReason = 'content_filter' | 'error' | 'length' | 'other' | 'stop' | 'tool-calls' | (string & {});

interface AudioBase64 {
    /**
     * Base64 encoded audio data.
     */
    data: string;
    format: 'mp3' | 'wav';
}
interface AudioPart extends CommonPart<'input_audio'> {
    input_audio: AudioBase64;
}
interface CommonPart<T extends string> {
    type: T;
}
interface ImagePart extends CommonPart<'image_url'> {
    image_url: ImageURLorBase64;
}
interface ImageURLorBase64 {
    /**
     * Specifies the detail level of the image.
     */
    detail?: 'auto' | 'high' | 'low';
    /**
     * Either a URL of the image or the base64 encoded image data.
     */
    url: string;
}
type Part = AudioPart | ImagePart | RefusalPart | TextPart;
interface RefusalPart extends CommonPart<'refusal'> {
    refusal: string;
}
interface TextPart extends CommonPart<'text'> {
    text: string;
}

interface AssistantMessage extends Optional<CommonMessage<'assistant', AssistantMessagePart>, 'content'> {
    refusal?: null | string;
    tool_calls?: ToolCall[];
}
type AssistantMessagePart = RefusalPart | TextPart;
interface AssistantMessageResponse extends Omit<AssistantMessage, 'content'> {
    content?: string;
}
interface CommonMessage<T extends string, P extends Part> {
    content: Array<P> | string;
    name?: string;
    role: T;
}
type Message = AssistantMessage | SystemMessage | ToolMessage | UserMessage;
interface SystemMessage extends CommonMessage<'system', SystemMessagePart> {
}
type SystemMessagePart = TextPart;
interface ToolCall {
    function: {
        arguments: string;
        name: string;
    };
    id: string;
    index: number;
    type: 'function';
}
interface ToolMessage extends Omit<CommonMessage<'tool', ToolMessagePart>, 'name'> {
    tool_call_id: string;
}
type ToolMessagePart = AudioPart | ImagePart | TextPart;
interface UserMessage extends CommonMessage<'user', UserMessagePart> {
}
type UserMessagePart = AudioPart | ImagePart | TextPart;
type Optional<T, K extends keyof T> = Omit<T, K> & Pick<Partial<T>, K>;

interface CompletionToolCall {
    args: string;
    toolCallId: string;
    toolCallType: 'function';
    toolName: string;
}
interface CompletionToolResult {
    args: Record<string, unknown>;
    result: string | ToolMessagePart[];
    toolCallId: string;
    toolName: string;
}
interface Tool {
    execute: (input: unknown, options: ToolExecuteOptions) => Promise<ToolExecuteResult> | ToolExecuteResult;
    function: {
        description?: string;
        name: string;
        parameters: Record<string, unknown>;
        strict?: boolean;
    };
    type: 'function';
}
interface ToolExecuteOptions {
    abortSignal?: AbortSignal;
    messages: Message[];
    toolCallId: string;
}
type ToolExecuteResult = object | string | unknown[];

interface Usage {
    completion_tokens: number;
    prompt_tokens: number;
    total_tokens: number;
}

type CompletionStep<T extends boolean = false> = (T extends true ? {
    usage: Usage;
} : {
    usage?: Usage;
}) & {
    finishReason: FinishReason;
    stepType: CompletionStepType;
    text?: string;
    toolCalls: CompletionToolCall[];
    toolResults: CompletionToolResult[];
};
type CompletionStepType = 'continue' | 'done' | 'initial' | 'tool-result';

type ToolChoice = 'auto' | 'none' | 'required' | {
    function: {
        name: string;
    };
    type: 'function';
};

/** @see {@link https://platform.openai.com/docs/api-reference/chat/create} */
interface ChatOptions extends CommonRequestOptions {
    [key: string]: unknown;
    /**
     * number between -2.0 and 2.0.
     * @default 0
     */
    frequencyPenalty?: number;
    messages: Message[];
    /**
     * number between -2.0 and 2.0.
     * @default 0
     */
    presencePenalty?: number;
    seed?: number;
    /** up to 4 sequences where the API will stop generating further tokens. */
    stop?: [string, string, string, string] | [string, string, string] | [string, string] | [string] | string;
    /**
     * what sampling temperature to use, between 0 and 2.
     * @default 1
     */
    temperature?: number;
    toolChoice?: ToolChoice;
    tools?: Tool[];
    /** @default 1 */
    topP?: number;
}
declare const chat: <T extends ChatOptions>(options: T) => Promise<Response>;

interface DetermineStepTypeOptions {
    finishReason: FinishReason;
    maxSteps: number;
    stepsLength: number;
    toolCallsLength: number;
}
/** @internal */
declare const determineStepType: ({ finishReason, maxSteps, stepsLength, toolCallsLength }: DetermineStepTypeOptions) => CompletionStepType;

interface ExecuteToolOptions {
    abortSignal?: AbortSignal;
    messages: Message[];
    toolCall: ToolCall;
    tools?: Tool[];
}
interface ExecuteToolResult {
    completionToolCall: CompletionToolCall;
    completionToolResult: CompletionToolResult;
    message: ToolMessage;
}
declare const executeTool: ({ abortSignal, messages, toolCall, tools }: ExecuteToolOptions) => Promise<ExecuteToolResult>;

export { type AssistantMessage, type AssistantMessagePart, type AssistantMessageResponse, type AudioBase64, type AudioPart, type ChatOptions, type CommonMessage, type CommonPart, type CompletionStep, type CompletionStepType, type CompletionToolCall, type CompletionToolResult, type DetermineStepTypeOptions, type ExecuteToolOptions, type ExecuteToolResult, type FinishReason, type ImagePart, type ImageURLorBase64, type Message, type Part, type RefusalPart, type SystemMessage, type SystemMessagePart, type TextPart, type Tool, type ToolCall, type ToolChoice, type ToolExecuteOptions, type ToolExecuteResult, type ToolMessage, type ToolMessagePart, type Usage, type UserMessage, type UserMessagePart, chat, determineStepType, executeTool };
