/**
 * Helpers to parse LLM raw_response for observability display.
 * Ranking responses use <rank> and <explain> tags; optimization uses markdown code blocks.
 * raw_response is often the full API JSON (e.g. OpenAI); we extract message content when present.
 */

/** Extract message content from OpenAI-style API response JSON, or return null */
export function extractMessageContentFromApiResponse(raw: string): string | null {
  try {
    const parsed = JSON.parse(raw) as {
      choices?: Array<{ message?: { content?: string } }>
    }
    const content = parsed?.choices?.[0]?.message?.content
    return typeof content === "string" ? content : null
  } catch {
    return null
  }
}

/** Get the string to use for rank/explain and markdown parsing (inner content if API JSON, else raw) */
export function getResponseContentForParsing(rawResponse: string): string {
  return extractMessageContentFromApiResponse(rawResponse) ?? rawResponse
}

/** Extract content inside <rank>...</rank> */
export function extractRankTag(content: string): string | null {
  const m = content.match(/<rank>([\s\S]*?)<\/rank>/i)
  return m ? m[1].trim() : null
}

/** Extract content inside <explain>...</explain> */
export function extractExplainTag(content: string): string | null {
  const m = content.match(/<explain>([\s\S]*?)<\/explain>/i)
  return m ? m[1].trim() : null
}

export type ResponseSegment =
  | { kind: "text"; content: string }
  | { kind: "code"; language: string; content: string }

/**
 * Split markdown-like content into text and code blocks (```lang ... ```).
 * Language is taken from the first word after ```; default "text".
 */
export function splitMarkdownCodeBlocks(content: string): ResponseSegment[] {
  const segments: ResponseSegment[] = []
  const re = /```(\w*)\n?([\s\S]*?)```/g
  let lastEnd = 0
  let m: RegExpExecArray | null
  while ((m = re.exec(content)) !== null) {
    if (m.index > lastEnd) {
      const text = content.slice(lastEnd, m.index)
      if (text.trim()) {
        segments.push({ kind: "text", content: text })
      }
    }
    const lang = m[1] || "text"
    segments.push({ kind: "code", language: lang, content: m[2].trim() })
    lastEnd = re.lastIndex
  }
  if (lastEnd < content.length) {
    const text = content.slice(lastEnd)
    if (text.trim()) {
      segments.push({ kind: "text", content: text })
    }
  }
  return segments
}
