declare class ChatModelService {
	static readonly WPCOM_JETPACK_AI: 'wpcom-jetpack-ai';
	static readonly WPCOM_OPENAI: 'wpcom-openai'; // the wpcom OpenAI proxy
	static readonly OPENAI: 'openai';
	static readonly GROQ: 'groq';
	static readonly OLLAMA: 'ollama';
	static readonly LMSTUDIO: 'lmstudio';
	static readonly LOCALAI: 'localai';
	static readonly LOCAL_GRAPH: 'local-graph';
	static readonly WPCOM_GRAPH: 'wpcom-graph';

	static getAvailable: () => string[];
	static getDefault: () => string;
	static getDefaultApiKey: ( service: string ) => string | null;
}

declare class ChatModelType {
	static readonly GPT_4_TURBO: 'gpt-4-turbo';
	static readonly GPT_4O: 'gpt-4o';
	static readonly GPT_4O_MINI: 'gpt-4o-mini';
	static readonly LLAMA3_70B_8192: 'llama3-70b-8192';
	static readonly LLAMA3_70B_8192_WPCOM: 'llama3-70b';
	static readonly GEMMA_7b_INSTRUCT: 'gemma:7b-instruct-q5_K_M';
	static readonly PHI_3_MEDIUM: 'legraphista/Phi-3-medium-128k-instruct-IMat-GGUF';
	static readonly MISTRAL_03: 'mistral-0.3';
	static readonly HERMES_2_PRO_MISTRAL: 'hermes-2-pro-mistral';

	static isMultimodal: ( model: ChatModelType ) => boolean;
	static supportsToolMessages: ( model: ChatModelType ) => boolean;
	static getAvailable: ( service: ChatModelService ) => string[];
	static getDefault: ( service?: ChatModelService | null ) => string;
}

interface ChatCompletionRequest {
	model: ChatModelType;
	messages: Message[];
	tools: Tool[];
	temperature?: number;
	max_tokens?: number;
	tool_choice?: string | null;
	feature?: string;
}

declare class ChatModel {
	constructor( options: { apiKey?: string } );
	getDefaultModel(): ChatModelType;
	getDefaultApiKey(): string | null;
	getDefaultTemperature(): number;
	getParams( request: ChatCompletionRequest ): Record< string, any >;
	getHeaders( request: ChatCompletionRequest ): Record< string, string >;
	run( options: {
		model: ChatModelType;
		messages: Message[];
		tools?: Tool[];
		instructions: string;
		additionalInstructions?: string;
		temperature?: number;
		maxTokens?: number;
		feature?: string;
		response_format?: string;
	} ): Promise< any >;
	call( options: ChatCompletionRequest ): Promise< any >;
	static getInstance(
		service: ChatModelService,
		apiKey: string | null
	): ChatModel;
}

declare class GroqChatModel extends ChatModel {}
declare class OpenAIChatModel extends ChatModel {}
declare class OllamaChatModel extends ChatModel {}
declare class LocalAIChatModel extends ChatModel {}
declare class WPCOMJetpackAIChatModel extends ChatModel {}
declare class WPCOMOpenAIChatModel extends ChatModel {}
declare class LocalGraphChatModel extends ChatModel {}
declare class WPCOMGraphChatModel extends ChatModel {}

declare class AssistantModelService {
	static readonly WPCOM_OPENAI: 'wpcom-openai'; // the wpcom OpenAI proxy
	static readonly WPCOM: 'wpcom'; // the OpenAI API
	static readonly OPENAI: 'openai';

	static getAvailable: () => string[];
	static getDefault: () => string;
	static getDefaultApiKey: ( service: string ) => string | null;
}

declare function useChatModel( options: {
	apiKey: string | undefined;
	service: string;
	feature?: string;
	sessionId?: string;
} ): any;

interface ChatIconHook {
	rive: any;
	RiveComponent: any;
	playDone: () => void;
	playGenerate: () => void;
	startStateMachine: () => void;
	pauseStateMachine: () => void;
}

declare function useChatIcon(): ChatIconHook;
declare function useChat(): Chat;
declare function useToolkit( toolkit: Toolkit ): void;
declare function useAgentsToolkit(): void;

declare function AskUserComponent(): any;
declare function ConfirmComponent(): any;
declare function MessageContent( props: {
	content: MessageContentParts;
} ): JSX.Element;
declare function withToolCall(
	toolCallName: string,
	Component: any
): any;

/**
 * Chat
 */

// define MessageRole enum
declare enum MessageRole {
	ASSISTANT = 'assistant',
	USER = 'user',
	TOOL = 'tool',
}

interface BaseMessage {
	role: MessageRole;
	content: MessageContentParts;
}

interface AssistantMessage extends BaseMessage {
	role: MessageRole.ASSISTANT;
	tool_calls?: ToolCall[];
}

interface UserMessage extends BaseMessage {
	role: MessageRole.USER;
}

interface ToolMessage extends BaseMessage {
	role: MessageRole.TOOL;
	tool_call_id: string;
}

type Message = AssistantMessage | UserMessage | ToolMessage;

interface TextMessageContentPart {
	type: 'text';
	text: string;
}

interface ImageMessageContentPart {
	type: 'image_url';
	image_url: string;
}

type MessageContentPart = TextMessageContentPart | ImageMessageContentPart;
type MessageContentParts = string | MessageContentPart[];

interface ToolCall {
	id: string;
	type: 'function';
	function: {
		name: string;
		arguments: any;
	};
}

interface ToolFunction {
	name: string;
	description?: string;
	parameters?: Record< string, unknown >;
}

interface Tool {
	function: ToolFunction;
	type: 'function';
}

interface Chat {
	running: boolean;
	enabled: boolean;
	setEnabled: ( enabled: boolean ) => void;
	started: boolean;
	error?: any;
	messages: Message[];
	clearMessages: () => void;
	userSay: ( content: string, image_urls?: string[] ) => void;
	assistantMessage?: MessageContentParts;
	call: ( name: string, args: any, id?: string ) => void;
	setToolResult: ( toolCallId: string, result: any ) => void;
	pendingToolCalls: ToolCall[];
	runChat: (
		messages: Message[],
		tools: any,
		instructions: string,
		additionalInstructions: string
	) => void;
	reset: () => void;
}

/**
 * Formatter and Prompt Templates
 */

declare class Formatter {
	format( values: any ): string;
}

type FormattingEngine = ( values: any ) => string;

declare class StringPromptTemplate extends Formatter {
	constructor( options: {
		inputVariables: string[];
		template: string;
		engine: FormattingEngine;
		formatters?: any;
	} );
	validate( engine: FormattingEngine, inputVariables: string[] ): void;
}

declare class FStringPromptTemplate extends StringPromptTemplate {
	constructor( options: { template: string } );
	static fromString( tmpl: string, options?: any ): FStringPromptTemplate;
}

declare class DotPromptTemplate extends StringPromptTemplate {
	constructor( options: { template: string; inputVariables: string[] } );
	static fromString(
		tmpl: string,
		templateVariables?: string[],
		options?: any
	): FStringPromptTemplate;
}

type InvokeTools = { [ key: string ]: () => void }

/**
 * Agents
 */

declare class Agent {
	constructor();
	get id(): string;
	get description(): string;
	get assistantId(): string;
	tools( context: any ): Tool[];
	toolkits( context: any ): Array<Toolkit | string>;
	instructions( context: any ): string;
	additionalInstructions( context: any ): string;
	onToolResult( toolName: string, value: any, invoke: InvokeTools, context: any ): void;
	onStart( invoke: InvokeTools ): void;
}

/**
 * Agent Toolkit
 */

interface ToolkitCallbacks {
	[ toolName: string ]: ( args: any ) => string;
}

interface Toolkit {
	reset: () => void;
	tools: Tool[] | (( context: any ) => Tool[]);
	context: any;
	callbacks: ToolkitCallbacks;
}

/**
 * Agent UI
 */
declare function AgentUI(): JSX.Element;

/**
 * Chat UI
 */
declare function AgentControls(): JSX.Element;
declare function ChatModelControls( props: {
	onApiKeyChanged: ( apiKey: string ) => void;
} ): JSX.Element;

declare function ToolCallControls(): JSX.Element;

export { Agent, AgentControls, AgentUI, AskUserComponent, AssistantModelService, ChatModel, ChatModelControls, ChatModelService, ChatModelType, ConfirmComponent, DotPromptTemplate, FStringPromptTemplate, Formatter, type FormattingEngine, GroqChatModel, LocalAIChatModel, LocalGraphChatModel, type Message, MessageContent, OllamaChatModel, OpenAIChatModel, StringPromptTemplate, type Tool, ToolCallControls, type ToolFunction, WPCOMGraphChatModel, WPCOMJetpackAIChatModel, WPCOMOpenAIChatModel, useAgentsToolkit, useChat, useChatIcon, useChatModel, useToolkit, withToolCall };
