/**
 * 解析 Markdown 中的 JSON 代码块，将文档拆分为「普通 Markdown 段落」与「可渲染组件」的混合结构。
 * 根据组件类型调用不同位置的解析器，解析结果中 configName 用于 getConfigByName，data 传入组件。
 *
 * 支持的 JSON 格式（以 x-list 为例）：
 * 1. 完整格式：{ "type": "x-list", "configName": "aiConsultationSuggestionListConfig", "data": [...] }
 *    - type: 组件类型
 *    - configName: 配置名，表示去哪里获取配置（通过 getConfigByName(configName) 拉取 listMode、label 等），
 *      用于区分同一种组件的不同展示场景（如 AI 建议列表 vs 药品列表）
 *    - data: 组件数据
 * 2. 临时格式（无 configName）：{ "type": "x-list", "data": [...] }，使用组件默认配置
 * 3. 纯数组：需传入 defaultXListConfigName，推断为 x-list
 */

import { parseBlockByType } from './blockParsers'

// 匹配 ```lang\n...\n``` 形式的代码块（lang 可为空）
const CODE_BLOCK_RE = /```(\w*)\r?\n([\s\S]*?)```/gm

/**
 * 尝试解析 JSON，失败返回 null
 * @param {string} str
 * @returns {any|null}
 */
function tryParseJson (str) {
  if (str == null || typeof str !== 'string') return null
  const trimmed = str.trim()
  if (!trimmed) return null
  try {
    return JSON.parse(trimmed)
  } catch {
    return null
  }
}

/**
 * 推断 JSON 对应的组件类型（用于选择解析器）
 * @param {any} parsed
 * @returns {string|null} 如 'x-list'
 */
function inferComponentType (parsed) {
  if (parsed == null) return null
  if (parsed && typeof parsed === 'object' && !Array.isArray(parsed) && parsed.type) {
    const type = String(parsed.type).toLowerCase()
    if (type === 'x-list') return 'x-list'
    return null
  }
  if (Array.isArray(parsed) && parsed.length > 0) return 'x-list'
  return null
}

/**
 * 将 Markdown 文本拆分为段落数组
 * @param {string} md - 原始 Markdown 文本
 * @param {object} [options] - 解析选项
 * @param {string} [options.defaultXListConfigName] - 纯数组时 x-list 的默认 configName
 * @returns {Array<{ type: 'md' | 'component', content?: string, componentType?: string, configName?: string, data?: any }>}
 */
export function parseMarkdownWithJsonBlocks (md, options = {}) {
  if (md == null || typeof md !== 'string') return [{ type: 'md', content: '' }]

  const { defaultXListConfigName } = options
  const segments = []
  let lastIndex = 0

  CODE_BLOCK_RE.lastIndex = 0
  let match
  while ((match = CODE_BLOCK_RE.exec(md)) !== null) {
    const fullMatch = match[0]
    const lang = (match[1] || '').toLowerCase()
    const codeContent = match[2] || ''

    // 前面的 Markdown 段落
    const beforeMd = md.slice(lastIndex, match.index)
    if (beforeMd) {
      segments.push({ type: 'md', content: beforeMd })
    }

    const parsed = tryParseJson(codeContent)
    const componentType = parsed ? inferComponentType(parsed) : null
    const parserOptions = componentType === 'x-list' ? { defaultConfigName: defaultXListConfigName } : {}
    const component = componentType ? parseBlockByType(componentType, parsed, parserOptions) : null

    if (component && (lang === 'json' || lang === '')) {
      segments.push({
        type: 'component',
        componentType: component.componentType,
        configName: component.configName,
        data: component.data
      })
    } else {
      // 非组件 JSON 或非 json 代码块，按普通代码块保留（用原始 md 片段）
      segments.push({ type: 'md', content: fullMatch })
    }

    lastIndex = match.index + fullMatch.length
  }

  // 剩余部分
  const rest = md.slice(lastIndex)
  if (rest) {
    segments.push({ type: 'md', content: rest })
  }

  return segments.length ? segments : [{ type: 'md', content: md }]
}
