/**
 * 简单的流式 Markdown 渲染器
 * 支持: **粗体**, *斜体*, `代码`, ```代码块```, # 标题, 列表, 引用, <think>思考
 */

const { BOLD, DIM, CLEAR, RED, GREEN, YELLOW, CYAN, BLUE, MAGENTA, WHITE } = require('./ansi');

// Markdown 标记对应的 ANSI 样式
const STYLES = {
  bold: { prefix: BOLD, suffix: CLEAR },
  italic: { prefix: DIM, suffix: CLEAR },
  code: { prefix: CYAN, suffix: CLEAR }, // dim = 暗色
  codeBlock: { prefix: YELLOW, suffix: CLEAR }, // yellow = 黄色
  h1: { prefix: BOLD, suffix: CLEAR }, // bold white
  h2: { prefix: BOLD, suffix: CLEAR }, // bold white
  h3: { prefix: BOLD, suffix: CLEAR },
  link: { prefix: '\x1B[34m\x1B[4m', suffix: CLEAR }, // blue underline
  list: { prefix: DIM, suffix: CLEAR }, // dim = 暗色
  blockquote: { prefix: DIM, suffix: CLEAR }, // dim = 暗色
  think: { prefix: `\x1B[38;5;240m`, suffix: CLEAR }, // yellow = 黄色
};

/**
 * 验证并修复UTF-16代理对
 */
function fixSurrogates(text) {
  if (!text) return '';
  const result = [];
  let i = 0;
  while (i < text.length) {
    const char = text[i];
    const code = text.charCodeAt(i);
    // 高代理
    if (code >= 0xd800 && code <= 0xdbff) {
      const nextCode = text.charCodeAt(i + 1);
      // 如果有低代理，配对
      if (nextCode >= 0xdc00 && nextCode <= 0xdfff) {
        result.push(char + text[i + 1]);
        i += 2;
        continue;
      }
      // 孤立的高代理，替换为方框
      result.push('\uFFFD');
      i += 1;
      continue;
    }
    // 低代理（不应该单独出现）
    if (code >= 0xdc00 && code <= 0xdfff) {
      result.push('\uFFFD');
      i += 1;
      continue;
    }
    result.push(char);
    i++;
  }
  return result.join('');
}

/**
 * 渲染单行 markdown（流式友好，简单处理）
 */
function renderInline(text) {
  if (!text) return '';

  // 修复不完整的代理对
  const fixed = fixSurrogates(text);
  let result = fixed;

  // 处理行内代码 `code`
  result = result.replace(/`([^`]+)`/g, (match, code) => {
    return `${STYLES.code.prefix}${code}${STYLES.code.suffix}`;
  });

  // 处理 **粗体**
  result = result.replace(/\*\*([^*]+)\*\*/g, (match, bold) => {
    return `${STYLES.bold.prefix}${bold}${STYLES.bold.suffix}`;
  });

  // 处理 *斜体*（不匹配已处理的粗体内部）
  result = result.replace(/(?<!\*)\*([^*\n]+)\*(?!\*)/g, (match, italic) => {
    return `${STYLES.italic.prefix}${italic}${STYLES.italic.suffix}`;
  });

  // 处理 ~~删除线~~ (简单处理)
  result = result.replace(/~~([^~]+)~~/g, (match, strikethrough) => {
    return `${DIM}${strikethrough}${CLEAR}`;
  });

  // 处理行内链接 [text](url) -> text
  result = result.replace(/\[([^\]]+)\]\([^)]+\)/g, (match, text) => {
    return `${STYLES.link.prefix}${text}${STYLES.link.suffix}`;
  });

  return result;
}

/**
 * 渲染包含思考标签的行
 */
function renderThink(line, state = { inThink: false }) {
  // <think>思考内容</think> -> 思考内容用暗色显示
  let result = '';

  let i = 0;
  let lastEnd = 0;

  // 如果在思考块中但这行没有开始标签，在行首添加黄色前缀
  if (state.inThink && !line.includes('<think>')) {
    result += STYLES.think.prefix;
  }

  while (i < line.length) {
    // 检查 <think> (7个字符)
    if (line.substring(i, i + 7) === '<think>') {
      if (i > lastEnd) {
        result += renderInline(line.substring(lastEnd, i));
      }
      result += STYLES.think.prefix + '<think>';
      i += 7;
      lastEnd = i;
      state.inThink = true;
      // 如果这行只有<think>标签，不要在这里添加CLEAR
      // 后续行会继续使用黄色
      if (i >= line.length) {
        // 没有更多内容，return时不添加CLEAR，保持黄色状态
        return result;
      }
      continue;
    }

    // 检查</think> (8个字符)
    if (line.substring(i, i + 8) === '</think>') {
      if (i > lastEnd) {
        result += line.substring(lastEnd, i) + STYLES.think.suffix;
      }
      result += '</think>' + CLEAR;
      i += 8;
      lastEnd = i;
      state.inThink = false;
      continue;
    }

    i++;
  }

  if (lastEnd < line.length) {
    result += renderInline(line.substring(lastEnd));
  }

  return result;
}

/**
 * 渲染一行 markdown（处理标题、列表等）
 * state: { inThink: boolean, inCodeBlock: boolean } - 状态，会被修改
 */
function renderLine(line, state = { inThink: false, inCodeBlock: false }) {
  // 思考标签 - 保留首尾换行符
  const leadingNL = line.match(/^\n*/)[0];
  const trailingNL = line.match(/\n*$/)[0];
  const trimmed = line.trim();

  // 代码块处理
  if (trimmed.startsWith('```')) {
    if (state.inCodeBlock) {
      // 结束代码块
      state.inCodeBlock = false;
      return `\`\`\`${trimmed.slice(3) ? ' ' + trimmed.slice(3) : ''}${STYLES.codeBlock.suffix}`;
    } else {
      // 开始代码块
      state.inCodeBlock = true;
      const lang = trimmed.slice(3).trim();
      return `${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}`;
    }
  }

  // 如果在代码块中，整行用代码样式
  if (state.inCodeBlock) {
    return `${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}`;
  }

  // 如果在思考块中或者有思考标签
  if (state.inThink || trimmed.includes('<think>') || trimmed.includes('</think>')) {
    const result = leadingNL + renderThink(trimmed, state) + trailingNL;
    return result;
  }

  // 标题
  if (line.startsWith('### ')) {
    return `${STYLES.h3.prefix}${renderInline(line.substring(4))}${STYLES.h3.suffix}`;
  }
  if (line.startsWith('## ')) {
    return `${STYLES.h2.prefix}${renderInline(line.substring(3))}${STYLES.h2.suffix}`;
  }
  if (line.startsWith('# ')) {
    return `${STYLES.h1.prefix}${renderInline(line.substring(2))}${STYLES.h1.suffix}`;
  }

  // 无序列表
  if (line.match(/^[-*+] /)) {
    return line.replace(/^([-*+] )(.*)/, (match, bullet, content) => {
      return `${STYLES.list.prefix}${bullet}${CLEAR}${renderInline(content)}`;
    });
  }

  // 有序列表
  if (line.match(/^\d+\. /)) {
    return line.replace(/^(\d+\. )(.*)/, (match, bullet, content) => {
      return `${STYLES.list.prefix}${bullet}${CLEAR}${renderInline(content)}`;
    });
  }

  // 引用
  if (line.startsWith('> ')) {
    return line.replace(/^> (.*)/, (match, content) => {
      return `${STYLES.blockquote.prefix}| ${renderInline(content)}${STYLES.blockquote.suffix}`;
    });
  }

  return renderInline(line);
}

/**
 * 渲染完整的 markdown 文本
 */
function render(text) {
  if (!text) return '';

  const lines = text.split('\n');
  const rendered = [];

  let inCodeBlock = false;

  for (const line of lines) {
    // 代码块
    if (line.startsWith('```')) {
      if (inCodeBlock) {
        rendered.push(`\`\`\`${STYLES.codeBlock.suffix}`);
        inCodeBlock = false;
      } else {
        const lang = line.substring(3).trim() || '';
        rendered.push(`${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}`);
        inCodeBlock = true;
      }
      continue;
    }

    if (inCodeBlock) {
      rendered.push(`${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}`);
    } else {
      rendered.push(renderLine(line));
    }
  }

  return rendered.join('\n');
}

/**
 * 流式渲染 - 每次返回一个完整的行
 * 返回 { done: boolean, line: string }
 */
function* streamRender(text) {
  if (!text) return;

  const lines = text.split('\n');
  let inCodeBlock = false;

  for (const line of lines) {
    // 代码块
    if (line.startsWith('```')) {
      if (inCodeBlock) {
        yield { done: false, line: `${STYLES.codeBlock.suffix}` };
        inCodeBlock = false;
      } else {
        const lang = line.substring(3).trim() || '';
        yield { done: false, line: `${STYLES.codeBlock.prefix}\`\`\`${lang ? ' ' + lang : ''}` };
        inCodeBlock = true;
      }
      continue;
    }

    if (inCodeBlock) {
      yield { done: false, line: `${STYLES.codeBlock.prefix}${line}${STYLES.codeBlock.suffix}` };
    } else {
      yield { done: false, line: renderLine(line) };
    }
  }

  yield { done: true };
}

module.exports = { render, renderInline, renderLine, streamRender, STYLES };
