import request from "@/utils/request"
import { getToken } from "@/utils/auth"

/** AI 诊断会话列表 */
export function listAiConsultSessions(query) {
  return request({
    url: "/diseaseTreatment/onlineConsult/ai/session/list",
    method: "get",
    params: query
  })
}

/** 新建 AI 会话 */
export function createAiConsultSession(data) {
  return request({
    url: "/diseaseTreatment/onlineConsult/ai/session",
    method: "post",
    data: data || {}
  })
}

/** 会话历史消息 */
export function listAiConsultMessages(sessionId, query) {
  return request({
    url: "/diseaseTreatment/onlineConsult/ai/session/" + sessionId + "/messages",
    method: "get",
    params: query
  })
}

/** 提问（同步等待 AI，最长约 60s；后端 ConsultAiGateway） */
export function sendAiConsultMessage(sessionId, data) {
  return request({
    url: "/diseaseTreatment/onlineConsult/ai/session/" + sessionId + "/message",
    method: "post",
    data,
    timeout: 65000,
    headers: { repeatSubmit: false }
  })
}

/** 隐藏/删除 AI 诊断会话（vet_visible=0，列表不再展示） */
export function hideAiConsultSession(sessionId) {
  return request({
    url: "/diseaseTreatment/onlineConsult/ai/session/" + sessionId + "/hide",
    method: "post",
    headers: { repeatSubmit: false }
  })
}

/**
 * 从大模型 SSE/JSON 解析会话 id。
 * 网关流式首包及后续块中的 `id` 即为 sessionId（与 OpenAI chat id 一致）。
 */
export function extractLlmSessionIdFromJson(json) {
  if (!json || typeof json !== "object") {
    return null
  }
  if (json.id != null && json.id !== "") {
    return String(json.id)
  }
  if (json.session_id != null && json.session_id !== "") {
    return String(json.session_id)
  }
  if (json.sessionId != null && json.sessionId !== "") {
    return String(json.sessionId)
  }
  return null
}

function extractDeltaFromChatJson(json) {
  if (!json || typeof json !== "object") {
    return ""
  }
  const choice = json.choices && json.choices[0]
  if (!choice) {
    return ""
  }
  if (choice.delta && choice.delta.content != null) {
    return String(choice.delta.content)
  }
  if (choice.message && choice.message.content != null) {
    return String(choice.message.content)
  }
  if (choice.text != null) {
    return String(choice.text)
  }
  return ""
}

function parseChatJsonPayload(payload) {
  if (!payload || payload === "[DONE]") {
    return { done: true }
  }
  try {
    const json = JSON.parse(payload)
    const sessionId = extractLlmSessionIdFromJson(json)
    const delta = extractDeltaFromChatJson(json)
    const model =
      json.model != null && json.model !== "" ? String(json.model) : null
    return { sessionId, delta, model }
  } catch (e) {
    return null
  }
}

function parseChatSseDataLine(line) {
  const trimmed = (line || "").trim()
  if (!trimmed || trimmed.startsWith(":")) {
    return null
  }
  if (trimmed.startsWith("data:")) {
    return parseChatJsonPayload(trimmed.slice(5).trim())
  }
  if (trimmed.startsWith("{") || trimmed.startsWith("[")) {
    return parseChatJsonPayload(trimmed)
  }
  return null
}

function appendStreamDelta(state, delta) {
  if (!delta) {
    return
  }
  const prev = state.fullText || ""
  if (!prev) {
    state.fullText = delta
    return
  }
  if (delta === prev) {
    return
  }
  if (delta.startsWith(prev)) {
    state.fullText = delta
    return
  }
  if (prev.startsWith(delta)) {
    return
  }
  state.fullText += delta
}

function consumeSseLines(state, lines, callbacks) {
  for (const line of lines) {
    const parsed = parseChatSseDataLine(line)
    if (!parsed) {
      continue
    }
    if (parsed.sessionId) {
      const changed = state.sessionId !== parsed.sessionId
      state.sessionId = parsed.sessionId
      if (changed && callbacks.onSessionId) {
        callbacks.onSessionId(parsed.sessionId)
      }
    }
    if (parsed.model) {
      state.model = parsed.model
      if (callbacks.onModel) {
        callbacks.onModel(parsed.model)
      }
    }
    if (parsed.delta) {
      const before = state.fullText
      appendStreamDelta(state, parsed.delta)
      if (state.fullText !== before && callbacks.onDelta) {
        callbacks.onDelta(state.fullText, parsed.delta)
      }
    }
  }
}

function appendSseChunk(state, chunk, callbacks) {
  if (!chunk) {
    return
  }
  const text = String(chunk)
  if (!state.buffer && text.trim().startsWith("{") && text.includes('"choices"')) {
    const parsed = parseChatJsonPayload(text.trim())
    if (parsed && parsed.delta) {
      const before = state.fullText
      appendStreamDelta(state, parsed.delta)
      if (state.fullText !== before && callbacks.onDelta) {
        callbacks.onDelta(state.fullText, parsed.delta)
      }
      if (parsed.sessionId) {
        const changed = state.sessionId !== parsed.sessionId
        state.sessionId = parsed.sessionId
        if (changed && callbacks.onSessionId) {
          callbacks.onSessionId(parsed.sessionId)
        }
      }
      if (parsed.model) {
        state.model = parsed.model
        if (callbacks.onModel) {
          callbacks.onModel(parsed.model)
        }
      }
      return
    }
  }
  state.buffer += text
  const lines = state.buffer.split(/\r?\n/)
  state.buffer = lines.pop() || ""
  consumeSseLines(state, lines, callbacks)
}

function flushSseBuffer(state, callbacks) {
  if (!state.buffer) {
    return
  }
  const tail = state.buffer
  state.buffer = ""
  consumeSseLines(state, [tail], callbacks)
}

function chatCompletionsUrl() {
  const base = process.env.VUE_APP_BASE_API || ""
  return base.replace(/\/$/, "") + "/v1/chat/completions"
}

function streamRequestHeaders() {
  const headers = {
    "Content-Type": "application/json",
    Accept: "text/event-stream",
    "Cache-Control": "no-cache"
  }
  const token = getToken()
  if (token) {
    headers.Authorization = "Bearer " + token
  }
  return headers
}

/** 流式：fetch + ReadableStream 逐块解析（axios XHR 常会缓冲到结束才触发 progress） */
async function sendChatMessageStream(data, options) {
  const startMs = Date.now()
  const { onDelta, onSessionId, onModel, signal } = options
  const state = { buffer: "", fullText: "", sessionId: null, model: null }
  const callbacks = { onDelta, onSessionId, onModel }

  const res = await fetch(chatCompletionsUrl(), {
    method: "POST",
    headers: streamRequestHeaders(),
    body: JSON.stringify(data),
    signal
  })
  if (!res.ok) {
    const text = await res.text()
    let msg = "requestFailed"
    try {
      const err = JSON.parse(text)
      msg = (err && (err.message || err.msg)) || msg
    } catch (e) {
      if (text) {
        msg = text.slice(0, 200)
      }
    }
    throw new Error(msg)
  }
  const reader = res.body && res.body.getReader()
  if (!reader) {
    throw new Error("requestFailed")
  }
  const decoder = new TextDecoder()
  while (true) {
    const { done, value } = await reader.read()
    if (done) {
      break
    }
    appendSseChunk(state, decoder.decode(value, { stream: true }), callbacks)
  }
  appendSseChunk(state, decoder.decode(), callbacks)
  flushSseBuffer(state, callbacks)
  return {
    content: state.fullText,
    sessionId: state.sessionId,
    model: state.model,
    durationMs: Date.now() - startMs
  }
}

/**
 * 聊天 POST /v1/chat/completions（默认 stream: true）
 * - stream: false → JSON（走 request 默认响应）
 * - 其余情况 → SSE，options 可传 onDelta / onSessionId / onModel / signal
 * - 流式 resolve：{ content, sessionId, model, durationMs }，durationMs 为整段流式请求耗时（毫秒）
 */
export function sendChatMessage(data, options = {}) {
  const body = { stream: true, ...(data || {}) }
  if (body.stream !== false) {
    return sendChatMessageStream(body, options)
  }
  return request({
    url: "/v1/chat/completions",
    method: "post",
    data: body,
    timeout: 600000
  })
}

/** 获取模型列表 **/
export function getModelList() {
  return request({
    url: "/v1/models",
    method: "get"
  })
}
