import { getToken } from "@/api/request.js";

const CHART_INTERPRETATION_URL = "/aiAnalysis/chart_interpretation";
const API_KEY = "aircasKEY19491001";

/**
 * 从模型返回的 markdown code fence 中提取数组 JSON
 * 例如：```json\n[ ... ]\n```
 * @param {string} buffer
 * @returns {unknown[]}
 */
function parseChartInterpretationArray(buffer) {
	// 可能带有前后空白、换行、以及 ```/```json 包裹
	let cleaned = String(buffer || "").trim();

	// 移除开头 fence
	cleaned = cleaned.replace(/^```(?:json)?\s*/i, "");
	// 移除结尾 fence（允许末尾有换行）
	cleaned = cleaned.replace(/```[\s\r\n]*$/i, "").trim();

	// 优先直接解析
	try {
		const parsed = JSON.parse(cleaned);
		if (Array.isArray(parsed)) return parsed;
	} catch (_) { }

	// 兜底：从 first '[' 到 last ']' 截取
	const start = cleaned.indexOf("[");
	const end = cleaned.lastIndexOf("]");
	if (start !== -1 && end !== -1 && end > start) {
		const arrStr = cleaned.slice(start, end + 1);
		const parsed = JSON.parse(arrStr);
		if (Array.isArray(parsed)) return parsed;
	}

	throw new Error("无法解析图表解读 JSON 数组");
}

/**
 * 图表解读（SSE 流式）
 * @param {object} data - 请求体
 * @param {object} [options] - 可选配置
 * @param {function(string): void} [options.onChunk] - 每收到一条 SSE 消息时回调，参数为当前 chunk 的 text
 * @returns {Promise<{data: unknown[]}>}
 */
export function getChartAnalysis(data, options = {}) {
	const { onChunk } = options;
	return new Promise((resolve, reject) => {
		let buffer = "";
		let settled = false;
		const abortController = new AbortController();

		const safeResolve = value => {
			if (settled) return;
			settled = true;
			resolve(value);
		};

		const safeReject = err => {
			if (settled) return;
			settled = true;
			reject(err);
		};

		(async () => {
			try {
				const { fetchEventSource } = await import("@microsoft/fetch-event-source");

				await fetchEventSource(CHART_INTERPRETATION_URL, {
					method: "POST",
					headers: {
						"Content-Type": "application/json",
						Accept: "text/event-stream",
						"Cache-Control": "no-cache",
						"X-API-Key": API_KEY,
						// 后端同项目其它接口使用 token 字段名（axios 拦截器里就是这样注入的）
						token: getToken()
					},
					body: JSON.stringify(data),
					signal: abortController.signal,
					openWhenHidden: true,
					retryDelay: 1000,
					maxRetries: 2,
					onopen: response => {
						const contentType = response.headers.get("content-type") || "";
						if (!contentType.includes("text/event-stream")) {
							throw new Error("SSE连接格式异常：content-type 不是 text/event-stream");
						}
					},
					onmessage: event => {
						const raw = (event?.data || "").trim();
						if (!raw) return;
						if (raw === "[DONE]") return;

						let chunk = "";
						// 兼容后端返回格式：
						// - {"text":"```"} / {"text":"json\n[\n"}
						// - {"type":"reasoning","chunk":"..."}（新格式）
						try {
							const msg = JSON.parse(raw);
							if (Array.isArray(msg?.chunk)) {
								safeResolve({ data: msg.chunk });
								abortController.abort();
								return;
							}

							if (msg && typeof msg === "object" && "chunk" in msg) {
								chunk = typeof msg.chunk === "string" ? msg.chunk : "";
								if (chunk) buffer += chunk;
							} else if (msg && typeof msg === "object" && "text" in msg) {
								chunk = String(msg.text ?? "");
								if (chunk) buffer += chunk;
							} else {
								chunk = raw;
								buffer += raw;
							}
						} catch (e) {
							chunk = raw;
							buffer += raw;
						}

						// 每收到一条消息即回调，用于流式渲染
						if (chunk && typeof onChunk === "function") {
							onChunk(chunk);
						}

						// 如果 buffer 已经拼完 markdown code fence，则提前解析并中断连接
						const trimmed = buffer.trim();
						if (trimmed.endsWith("```")) {
							try {
								const arr = parseChartInterpretationArray(trimmed);
								safeResolve({ data: arr });
								abortController.abort();
							} catch (_) { }
						}
					},
					onclose: () => {
						try {
							const arr = parseChartInterpretationArray(buffer);
							safeResolve({ data: arr });
						} catch (e) {
							safeReject(e);
						}
					},
					onerror: error => {
						if (error?.name === "AbortError") return true;
						safeReject(error);
						return true;
					}
				});
			} catch (error) {
				safeReject(error);
			}
		})();
	});
}
