/**
 * AI 响应清理工具（LLM 服务层统一入口）
 *
 * 所有 LLM 响应都应经过此模块处理后再返回给调用方。
 * 职责：
 * 1. 过滤思考标签（<think/>、<thinking/> 等）
 * 2. 清理格式标记（Markdown 符号、代码块等）
 * 3. 提取纯文本 / JSON 内容
 */

/**
 * 清理 AI 响应中的思考标签和格式
 * 统一入口，所有 LLM 响应都应经过此函数处理
 *
 * 处理策略：
 * 1. 先移除成对思考标签及内容（如 <think ... </think >）
 * 2. 再移除未闭合思考标签（如 <think ... 到文本末尾）
 * 3. 移除孤立的闭标签
 */
export function cleanLlmResponse(raw: string): string {
  if (!raw || typeof raw !== 'string') return raw;

  let cleaned = raw;

  // 1. 移除成对思考标签及其内容（从开标签到闭标签，含中间内容）
  const thinkBlockPatterns = [
    /<think\b[^>]*>[\s\S]*?<\/think\s*>/gi,
    /<thinking\b[^>]*>[\s\S]*?<\/thinking\s*>/gi,
    /<thought\b[^>]*>[\s\S]*?<\/thought\s*>/gi,
    /<reflection\b[^>]*>[\s\S]*?<\/reflection\s*>/gi,
    /<reasoning\b[^>]*>[\s\S]*?<\/reasoning\s*>/gi,
    /<scratchpad\b[^>]*>[\s\S]*?<\/scratchpad\s*>/gi,
    /<internal\b[^>]*>[\s\S]*?<\/internal\s*>/gi,
    /<antthinking\b[^>]*>[\s\S]*?<\/antthinking\s*>/gi,
    /\[think\][\s\S]*?\[\/think\]/gi,
    /\[thinking\][\s\S]*?\[\/thinking\]/gi,
  ];

  for (const pattern of thinkBlockPatterns) {
    cleaned = cleaned.replace(pattern, '');
  }

  // 2. 移除未闭合思考标签（从开标签到文本末尾）
  const unclosedPatterns = [
    /<think\b[^>]*>[\s\S]*$/gi,
    /<thinking\b[^>]*>[\s\S]*$/gi,
    /<thought\b[^>]*>[\s\S]*$/gi,
    /<reflection\b[^>]*>[\s\S]*$/gi,
    /<reasoning\b[^>]*>[\s\S]*$/gi,
  ];

  for (const pattern of unclosedPatterns) {
    cleaned = cleaned.replace(pattern, '');
  }

  // 3. 移除自闭合标签
  cleaned = cleaned.replace(/<think\s*\/>/gi, '');
  cleaned = cleaned.replace(/<thinking\s*\/>/gi, '');

  // 4. 移除孤立的闭标签
  cleaned = cleaned.replace(/<\/think\s*>/gi, '');
  cleaned = cleaned.replace(/<\/thinking\s*>/gi, '');
  cleaned = cleaned.replace(/<\/thought\s*>/gi, '');
  cleaned = cleaned.replace(/<\/reflection\s*>/gi, '');
  cleaned = cleaned.replace(/<\/reasoning\s*>/gi, '');

  // 5. 压缩多余空行
  cleaned = cleaned.replace(/\n{3,}/g, '\n\n');

  return cleaned.trim();
}

/**
 * 清理 AI 响应并提取简短文本（适合标题、标签等场景）
 * 在 cleanLlmResponse 基础上额外处理：
 * - 去除 Markdown 格式标记
 * - 去除引号包裹
 * - 中文截断 / 英文截断
 */
export function cleanLlmShortText(
  raw: string,
  options: {
    maxLength?: number;       // 最大字符数（默认 50）
    maxChineseChars?: number; // 中文最大字数（默认 20）
    maxEnglishWords?: number; // 英文最大词数（默认 20）
  } = {}
): string {
  const { maxLength = 50, maxChineseChars = 20, maxEnglishWords = 20 } = options;

  let text = cleanLlmResponse(raw);

  // 去除 Markdown 格式
  text = text
    .replace(/^#+\s*/gm, '')                        // 标题标记
    .replace(/\*{1,3}([^*]+)\*{1,3}/g, '$1')        // 加粗/斜体
    .replace(/`{1,3}[^`]+`{1,3}/g, '')              // 代码块
    .replace(/\[([^\]]+)\]\([^)]+\)/g, '$1')        // 链接
    .replace(/["""《》''「」『』]/g, '')               // 各种引号
    .replace(/[\n\r]+/g, ' ')                        // 换行转空格
    .replace(/^书名[：:]\s*/i, '')                    // 去掉可能的"书名："前缀
    .trim();

  // 中文截断：如果中文字符超过限制
  const chineseChars = text.match(/[\u4e00-\u9fff]/g);
  if (chineseChars && chineseChars.length > maxChineseChars) {
    let count = 0;
    let cutIndex = 0;
    for (let i = 0; i < text.length; i++) {
      if (/[\u4e00-\u9fff]/.test(text[i])) {
        count++;
        if (count > maxChineseChars) {
          cutIndex = i;
          break;
        }
      }
    }
    if (cutIndex > 0) text = text.substring(0, cutIndex);
  }

  // 英文截断：如果英文单词超过限制
  const englishWords = text.match(/[a-zA-Z]+/g);
  if (englishWords && englishWords.length > maxEnglishWords) {
    const words = text.split(/\s+/);
    text = words.slice(0, maxEnglishWords).join(' ');
  }

  // 总长度截断保护
  if (text.length > maxLength) {
    text = text.substring(0, maxLength);
  }

  return text.trim();
}

/**
 * 从 AI 响应中提取 JSON
 * 在 cleanLlmResponse 基础上尝试提取 JSON 对象
 */
export function extractJsonFromResponse<T = any>(raw: string): T | null {
  const cleaned = cleanLlmResponse(raw);

  // 尝试直接解析
  try {
    return JSON.parse(cleaned);
  } catch {}

  // 提取 ```json ... ``` 代码块
  const codeBlockMatch = cleaned.match(/```(?:json)?\s*\n?([\s\S]*?)\n?```/);
  if (codeBlockMatch) {
    try {
      return JSON.parse(codeBlockMatch[1].trim());
    } catch {}
  }

  // 提取第一个 {...} 或 [...]
  const jsonMatch = cleaned.match(/[\[{][\s\S]*[}\]]/);
  if (jsonMatch) {
    try {
      return JSON.parse(jsonMatch[0]);
    } catch {}
  }

  return null;
}
