import { useBase } from '/$/base';
import { config } from '/@/config';

export function useAi() {
	const { user } = useBase();
	let abortController: AbortController | null = null;

	// 调用流程
	async function invokeFlow(
		label: string,
		params: any,
		options?: {
			isDebug?: boolean;
			nodeId?: string;
			requestId?: string;
			sessionId?: string;
			isStream?: boolean;
			streamCb?: (result: FlowNodeResult) => void;
		}
	): Promise<any> {
		const stream = !!options?.isStream;
		let cacheText = '';

		abortController = new AbortController();

		return new Promise((resolve, reject) => {
			const url = options?.isDebug ? '/admin/flow/run/debug' : '/open/code/gen/data';

			fetch(config.baseUrl + url, {
				method: 'POST',
				headers: {
					Authorization: user.token,
					'Content-Type': 'application/json'
				},
				body: JSON.stringify({
					params,
					label,
					stream,
					nodeId: options?.nodeId,
					requestId: options?.requestId,
					sessionId: options?.sessionId
				}),
				signal: abortController?.signal
			})
				.then(res => {
					if (res.body) {
						if (stream) {
							const reader = res.body.getReader();
							const decoder = new TextDecoder('utf-8');
							const stream = new ReadableStream({
								start(controller) {
									function push() {
										reader.read().then(({ done, value }) => {
											if (done) {
												controller.close();
												return;
											}

											let text = decoder.decode(value, { stream: true });

											if (options?.streamCb) {
												if (cacheText) {
													text = cacheText + text;
												}

												if (text.indexOf('data:') == 0) {
													text = '\n\n' + text;
												}

												try {
													const arr = text
														.split(/\n\ndata:/g)
														.filter(Boolean)
														.map(e => JSON.parse(e));

													arr.forEach(options?.streamCb);

													cacheText = '';
												} catch (_err) {
													console.error('[parse text]', text);
													cacheText = text;
												}
											}

											controller.enqueue(text);
											push();
										});
									}
									push();
								}
							});

							return new Response(stream);
						} else {
							return res.json();
						}
					}
				})
				.then(res => {
					if (stream) {
						return res;
					}

					if (res.code == 1000) {
						resolve(res.data.result);
					} else {
						reject(res);
					}
				})
				.catch(reject);
		});
	}

	// 取消流程
	function cancelFlow() {
		if (abortController) {
			abortController.abort();
			abortController = null;
		}
	}

	return {
		invokeFlow,
		cancelFlow
	};
}
