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

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

	// 调用
	async function invoke({
		url,
		method = 'POST',
		data,
		cb
	}: {
		url: string;
		method?: string;
		data?: any;
		cb?: (result: any) => void;
	}) {
		abortController = new AbortController();

		let cacheText = '';

		return fetch(config.baseUrl + url, {
			method,
			headers: {
				Authorization: user.token,
				'Content-Type': 'application/json'
			},
			body: JSON.stringify(data),
			signal: abortController?.signal
		})
			.then(res => {
				if (res.body) {
					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 (cb) {
										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(cb);

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

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

					return new Response(stream);
				}

				return res;
			})
			.catch(err => {
				console.error(err);
				throw err;
			});
	}

	// 取消
	function cancel() {
		if (abortController) {
			abortController.abort();
			abortController = null;
		}
	}

	return {
		invoke,
		cancel
	};
}
