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

interface AudioContentPart {
    input_audio: {
        data: string;
        format: 'mp3' | 'wav';
    };
    type: 'input_audio';
}
/** @internal */
type CommonContentPart = AudioContentPart | FileContentPart | ImageContentPart | TextContentPart;
interface FileContentPart {
    file: {
        file_data?: string;
        file_id?: string;
        filename?: string;
    };
    type: 'file';
}
interface ImageContentPart {
    image_url: {
        detail?: 'auto' | 'high' | 'low';
        url: string;
    };
    type: 'image_url';
}
interface RefusalContentPart {
    refusal: string;
    type: 'refusal';
}
interface TextContentPart {
    text: string;
    type: 'text';
}

interface ToolCall {
    function: ToolCallFunction | ToolCallFunctionWithoutArguments | ToolCallFunctionWithoutName;
    id: string;
    type: 'function';
}
interface ToolCallFunction {
    arguments: string;
    name: string;
}
interface ToolCallFunctionWithoutArguments {
    arguments?: never;
    name: string;
}
interface ToolCallFunctionWithoutName {
    arguments: string;
    name?: never;
}

interface AssistantMessage {
    content?: (RefusalContentPart | TextContentPart)[] | string;
    name?: string;
    /** @see {@link https://cookbook.openai.com/articles/gpt-oss/handle-raw-cot#chat-completions-api} */
    reasoning?: string;
    /** @remarks OpenAI doesn't support this, but some providers do. */
    reasoning_content?: string;
    refusal?: string;
    role: 'assistant';
    tool_calls?: ToolCall[];
}
interface DeveloperMessage {
    content: string | TextContentPart[];
    name?: string;
    /** @remarks Before using, confirm that your model supports this. */
    role: 'developer';
}
type Message = AssistantMessage | DeveloperMessage | SystemMessage | ToolMessage | UserMessage;
interface SystemMessage {
    content: string | TextContentPart[];
    name?: string;
    role: 'system';
}
interface ToolMessage {
    /** @remarks considering the support of ecosystems (such as MCP), we have relaxed this type. */
    content: CommonContentPart[] | string;
    role: 'tool';
    tool_call_id: string;
}
interface UserMessage {
    content: CommonContentPart[] | string;
    name?: string;
    role: 'user';
}

interface CompletionToolCall {
    args: string;
    toolCallId: string;
    toolCallType: 'function';
    toolName: string;
}
interface CompletionToolResult {
    args: Record<string, unknown>;
    result: ToolExecuteResult;
    toolCallId: string;
    toolName: string;
}
type PostToolCall = (toolResult: CompletionToolResult, options: ToolExecuteOptions) => CompletionToolResult | Promise<CompletionToolResult | void> | void;
type PreToolCall = (toolCall: CompletionToolCall, options: ToolExecuteOptions) => CompletionToolCall | CompletionToolResult | Promise<CompletionToolCall | CompletionToolResult | void> | void;
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 ChatCompletionUsage {
    completion_tokens: number;
    prompt_tokens: number;
    total_tokens: number;
}
interface Usage {
    inputTokens: number;
    outputTokens: number;
    totalTokens: number;
}

interface ErrorEvent {
    cause?: unknown;
    message: string;
    type: 'error';
}
type Event = ErrorEvent | ReasoningDeltaEvent | ReasoningDoneEvent | ReasoningStartEvent | StepDoneEvent | StepStartEvent | TextDeltaEvent | TextDoneEvent | TextStartEvent | ToolCallDeltaEvent | ToolCallDoneEvent | ToolCallStartEvent | ToolResultDoneEvent;
type EventType = Event['type'];
interface ReasoningDeltaEvent {
    delta: string;
    type: 'reasoning.delta';
}
interface ReasoningDoneEvent {
    content: string;
    type: 'reasoning.done';
}
interface ReasoningStartEvent {
    type: 'reasoning.start';
}
interface StepDoneEvent {
    type: 'step.done';
    usage?: Usage;
}
interface StepStartEvent {
    type: 'step.start';
}
interface TextDeltaEvent {
    delta: string;
    type: 'text.delta';
}
interface TextDoneEvent {
    content: string;
    type: 'text.done';
}
interface TextStartEvent {
    type: 'text.start';
}
interface ToolCallDeltaEvent {
    delta: string;
    type: 'tool-call.delta';
}
interface ToolCallDoneEvent extends CompletionToolCall {
    type: 'tool-call.done';
}
interface ToolCallStartEvent extends Omit<CompletionToolCall, 'args' | 'toolCallType'> {
    type: 'tool-call.start';
}
interface ToolResultDoneEvent extends CompletionToolResult {
    type: 'tool-result.done';
}

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

type CompletionStep<T extends boolean = false> = (T extends true ? {
    usage: Usage;
} : {
    usage?: Usage;
}) & {
    finishReason: FinishReason;
    text?: string;
    toolCalls: CompletionToolCall[];
    toolResults: CompletionToolResult[];
};

type ToolChoice = AllowedTools | ToolChoiceMode | ToolChoiceTool;
interface AllowedTools {
    mode: 'auto' | 'required';
    tools: ToolChoiceTool[];
    type: 'allowed_tools';
}
type ToolChoiceMode = 'auto' | 'none' | 'required';
interface ToolChoiceTool {
    function: {
        name: string;
    };
    type: 'function';
}

type PrepareStep<TInput = Message[], TToolChoice = ToolChoice> = (options: PrepareStepOptions<TInput>) => PrepareStepResult<TInput, TToolChoice> | Promise<PrepareStepResult<TInput, TToolChoice>>;
interface PrepareStepOptions<TInput = Message[]> {
    input: TInput;
    model: string;
    stepNumber: number;
    steps: CompletionStep[];
}
interface PrepareStepResult<TInput = Message[], TToolChoice = ToolChoice> {
    input?: TInput;
    model?: string;
    toolChoice?: TToolChoice;
}

type StopCondition<Input = unknown> = (context: StopContext<Input>) => boolean;
interface StopContext<Input = unknown> {
    input: readonly Input[];
    step: CompletionStep;
    steps: readonly CompletionStep[];
}

/** @see {@link https://platform.openai.com/docs/api-reference/chat/create} */
interface ChatOptions extends CommonRequestOptions {
    /**
     * number between -2.0 and 2.0.
     * @default 0
     */
    frequencyPenalty?: number;
    messages: Message[];
    /** Whether to enable parallel function calling during tool use. */
    parallelToolCalls?: boolean;
    /**
     * number between -2.0 and 2.0.
     * @default 0
     */
    presencePenalty?: number;
    /** Constrains effort on reasoning for reasoning models. */
    reasoningEffort?: 'high' | 'medium' | 'minimal' | 'none' | 'xhigh';
    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;
    /** Controls which (if any) tool is called by the model. */
    toolChoice?: ToolChoice;
    /** A list of tools the model may call. */
    tools?: Tool[];
    /** @remarks OpenAI doesn't support this, but some providers do. */
    topK?: number;
    /** @default 1 */
    topP?: number;
}
declare const chat: <T extends WithUnknown<ChatOptions>>(options: T) => Promise<Response>;

interface ExecuteToolOptions<T = ToolMessage['content']> {
    abortSignal?: AbortSignal;
    messages: Message[];
    postToolCall?: PostToolCall;
    preToolCall?: PreToolCall;
    toolCall: ToolCall;
    tools?: Tool[];
    wrapResult?: (result: ToolExecuteResult) => T;
}
interface ExecuteToolResult<T = ToolMessage['content']> {
    completionToolCall: CompletionToolCall;
    completionToolResult: CompletionToolResult;
    result: T;
}
declare const executeTool: <T = ToolMessage["content"]>({ abortSignal, messages, postToolCall, preToolCall, toolCall, tools, wrapResult }: ExecuteToolOptions<T>) => Promise<ExecuteToolResult<T>>;

interface ResolvePrepareStepOptions<TInput = Message[], TToolChoice = ToolChoice> {
    input: TInput;
    model: string;
    prepareStep?: PrepareStep<TInput, TToolChoice>;
    stepNumber: number;
    steps: CompletionStep[];
    toolChoice?: TToolChoice;
}
interface ResolvePrepareStepResult<TInput = Message[], TToolChoice = ToolChoice> {
    input: TInput;
    model: string;
    toolChoice?: TToolChoice;
}
declare const resolvePrepareStep: <TInput, TToolChoice>({ input, model, prepareStep, stepNumber, steps, toolChoice }: ResolvePrepareStepOptions<TInput, TToolChoice>) => Promise<ResolvePrepareStepResult<TInput, TToolChoice>>;

declare const and: <Input = unknown>(...conditions: StopCondition<Input>[]) => StopCondition<Input>;
declare const or: <Input = unknown>(...conditions: StopCondition<Input>[]) => StopCondition<Input>;
declare const not: <Input = unknown>(condition: StopCondition<Input>) => StopCondition<Input>;
declare const stepCountAtLeast: (count: number) => StopCondition;
declare const hasToolCall: (name?: string) => StopCondition;
/** @internal */
declare const shouldStop: <Input = unknown>(stopWhen: StopCondition<Input>, context: StopContext<Input>) => boolean;

declare const computeTotalUsage: (totalUsage: undefined | Usage, usage: Usage) => Usage;
declare const normalizeChatCompletionUsage: (usage: ChatCompletionUsage) => Usage;

export { and, chat, computeTotalUsage, executeTool, hasToolCall, normalizeChatCompletionUsage, not, or, resolvePrepareStep, shouldStop, stepCountAtLeast };
export type { AssistantMessage, AudioContentPart, ChatCompletionUsage, ChatOptions, CommonContentPart, CompletionStep, CompletionToolCall, CompletionToolResult, DeveloperMessage, ErrorEvent, Event, EventType, ExecuteToolOptions, ExecuteToolResult, FileContentPart, FinishReason, ImageContentPart, Message, PostToolCall, PreToolCall, PrepareStep, PrepareStepOptions, PrepareStepResult, ReasoningDeltaEvent, ReasoningDoneEvent, ReasoningStartEvent, RefusalContentPart, ResolvePrepareStepOptions, ResolvePrepareStepResult, StepDoneEvent, StepStartEvent, StopCondition, StopContext, SystemMessage, TextContentPart, TextDeltaEvent, TextDoneEvent, TextStartEvent, Tool, ToolCall, ToolCallDeltaEvent, ToolCallDoneEvent, ToolCallStartEvent, ToolChoice, ToolExecuteOptions, ToolExecuteResult, ToolMessage, ToolResultDoneEvent, Usage, UserMessage };
