/**
 * Markdown 渲染工具
 * 支持流式输出的实时渲染
 */
import DOMPurify from 'dompurify';
import { Marked } from 'marked';

// 创建 marked 实例
const marked = new Marked({
  breaks: true, // 支持换行
  gfm: true, // 支持 GitHub 风格 Markdown
});

// 配置 DOMPurify
DOMPurify.setConfig({
  ADD_ATTR: ['target', 'rel'],
  ADD_TAGS: ['iframe'],
});

/**
 * 渲染 Markdown 为 HTML
 * 支持流式输出的不完整 Markdown
 */
export function renderMarkdown(content: string): string {
  if (!content) return '';

  try {
    // 处理流式输出中可能不完整的代码块
    const processedContent = handleIncompleteCodeBlocks(content);

    // 渲染 Markdown
    const html = marked.parse(processedContent) as string;

    // 清理 HTML 防止 XSS
    return DOMPurify.sanitize(html, {
      ADD_ATTR: ['target', 'rel'],
    });
  } catch (error) {
    console.error('Markdown 渲染错误:', error);
    return escapeHtml(content);
  }
}

/**
 * 处理不完整的代码块
 * 流式输出时代码块可能还没闭合
 */
function handleIncompleteCodeBlocks(content: string): string {
  // 计算代码块标记数量
  const codeBlockMatches = content.match(/```/g);
  const codeBlockCount = codeBlockMatches ? codeBlockMatches.length : 0;

  // 如果代码块标记是奇数，说明有未闭合的代码块
  if (codeBlockCount % 2 !== 0) {
    // 添加闭合标记
    return `${content}\n\`\`\``;
  }

  return content;
}

/**
 * 转义 HTML 特殊字符
 */
function escapeHtml(text: string): string {
  const map: Record<string, string> = {
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#039;',
  };
  return text.replaceAll(/[&<>"']/g, (m) => map[m] || m);
}

/**
 * 检查内容是否包含 Markdown 语法
 */
export function hasMarkdownSyntax(content: string): boolean {
  // 常见 Markdown 语法模式
  const patterns = [
    /^#{1,6}\s/m, // 标题
    /\*\*[^*]+\*\*/, // 粗体
    /\*[^*]+\*/, // 斜体
    /`[^`]+`/, // 行内代码
    /```[\s\S]*```/, // 代码块
    /^\s*[-*+]\s/m, // 无序列表
    /^\s*\d+\.\s/m, // 有序列表
    /\[.+\]\(.+\)/, // 链接
    /!\[.*\]\(.+\)/, // 图片
    /^\s*>/m, // 引用
    /\|.+\|/, // 表格
  ];

  return patterns.some((pattern) => pattern.test(content));
}
