/**
 * Markdown Serializer
 * 将 ProseMirror 文档序列化为 Markdown 格式
 */

import type { Node, Mark, Schema } from 'prosemirror-model';

export interface MarkdownSerializerOptions {
  /** 是否使用严格模式（更规范的 Markdown） */
  strict?: boolean;
  /** 代码块围栏字符 */
  codeFence?: string;
  /** 无序列表标记 */
  bulletListMarker?: '-' | '*' | '+';
  /** 标题样式 */
  headingStyle?: 'atx' | 'setext';
}

const defaultOptions: MarkdownSerializerOptions = {
  strict: false,
  codeFence: '```',
  bulletListMarker: '-',
  headingStyle: 'atx',
};

interface SerializerState {
  output: string;
  options: MarkdownSerializerOptions;
  listDepth: number;
  listType: 'bullet' | 'ordered' | null;
  listCounter: number;
}

/**
 * 将 ProseMirror 文档转换为 Markdown
 */
export function serializeToMarkdown(
  doc: Node,
  options: MarkdownSerializerOptions = {}
): string {
  const state: SerializerState = {
    output: '',
    options: { ...defaultOptions, ...options },
    listDepth: 0,
    listType: null,
    listCounter: 1,
  };

  serializeNode(doc, state);

  // 清理多余的空行
  return state.output
    .replace(/\n{3,}/g, '\n\n')
    .trim();
}

/**
 * 序列化单个节点
 */
function serializeNode(node: Node, state: SerializerState): void {
  const serializer = nodeSerializers[node.type.name];
  if (serializer) {
    serializer(node, state);
  } else {
    // 默认处理：递归序列化子节点
    node.content.forEach((child) => serializeNode(child, state));
  }
}

/**
 * 序列化文本节点（包含 marks）
 */
function serializeText(node: Node, state: SerializerState): void {
  let text = node.text || '';

  // 按优先级排序 marks
  const marks = [...node.marks].sort((a, b) => {
    const order = ['link', 'bold', 'italic', 'strike', 'code', 'highlight'];
    return order.indexOf(a.type.name) - order.indexOf(b.type.name);
  });

  // 应用 marks
  marks.forEach((mark) => {
    const wrapper = markWrappers[mark.type.name];
    if (wrapper) {
      text = wrapper(text, mark);
    }
  });

  state.output += text;
}

/**
 * 获取列表前缀
 */
function getListPrefix(state: SerializerState): string {
  const indent = '  '.repeat(state.listDepth - 1);
  if (state.listType === 'bullet') {
    return `${indent}${state.options.bulletListMarker} `;
  }
  return `${indent}${state.listCounter}. `;
}

/**
 * 节点序列化器
 */
const nodeSerializers: Record<string, (node: Node, state: SerializerState) => void> = {
  doc(node, state) {
    node.content.forEach((child) => serializeNode(child, state));
  },

  text(node, state) {
    serializeText(node, state);
  },

  paragraph(node, state) {
    node.content.forEach((child) => serializeNode(child, state));
    state.output += '\n\n';
  },

  heading(node, state) {
    const level = node.attrs.level || 1;

    if (state.options.headingStyle === 'setext' && level <= 2) {
      node.content.forEach((child) => serializeNode(child, state));
      state.output += '\n';
      state.output += level === 1 ? '=' : '-';
      state.output += level === 1 ? '===' : '---';
      state.output += '\n\n';
    } else {
      state.output += '#'.repeat(level) + ' ';
      node.content.forEach((child) => serializeNode(child, state));
      state.output += '\n\n';
    }
  },

  bulletList(node, state) {
    const prevType = state.listType;
    const prevDepth = state.listDepth;

    state.listType = 'bullet';
    state.listDepth++;

    node.content.forEach((child) => serializeNode(child, state));

    state.listType = prevType;
    state.listDepth = prevDepth;

    if (state.listDepth === 0) {
      state.output += '\n';
    }
  },

  orderedList(node, state) {
    const prevType = state.listType;
    const prevDepth = state.listDepth;
    const prevCounter = state.listCounter;

    state.listType = 'ordered';
    state.listDepth++;
    state.listCounter = node.attrs.start || 1;

    node.content.forEach((child) => serializeNode(child, state));

    state.listType = prevType;
    state.listDepth = prevDepth;
    state.listCounter = prevCounter;

    if (state.listDepth === 0) {
      state.output += '\n';
    }
  },

  listItem(node, state) {
    const prefix = getListPrefix(state);
    state.output += prefix;

    // 序列化内容，处理多段落
    let isFirst = true;
    node.content.forEach((child) => {
      if (child.type.name === 'paragraph') {
        if (!isFirst) {
          state.output += '  '.repeat(state.listDepth);
        }
        child.content.forEach((c) => serializeNode(c, state));
        state.output += '\n';
        isFirst = false;
      } else {
        serializeNode(child, state);
      }
    });

    if (state.listType === 'ordered') {
      state.listCounter++;
    }
  },

  blockquote(node, state) {
    const lines: string[] = [];
    let tempState: SerializerState = { ...state, output: '' };

    node.content.forEach((child) => serializeNode(child, tempState));

    // 为每行添加 > 前缀
    tempState.output.split('\n').forEach((line) => {
      if (line.trim()) {
        lines.push(`> ${line}`);
      } else {
        lines.push('>');
      }
    });

    state.output += lines.join('\n').replace(/>\s*$/, '') + '\n\n';
  },

  codeBlock(node, state) {
    const language = node.attrs.language || '';
    const fence = state.options.codeFence;

    state.output += `${fence}${language}\n`;
    state.output += node.textContent;
    state.output += `\n${fence}\n\n`;
  },

  horizontalRule(_node, state) {
    state.output += '---\n\n';
  },

  image(node, state) {
    const { src, alt, title } = node.attrs;
    let markdown = `![${alt || ''}](${src || ''})`;
    if (title) {
      markdown = `![${alt || ''}](${src || ''} "${title}")`;
    }
    state.output += markdown + '\n\n';
  },

  callout(node, state) {
    const type = node.attrs.type || 'info';
    state.output += `:::${type}\n`;

    node.content.forEach((child) => serializeNode(child, state));

    state.output += ':::\n\n';
  },

  table(node, state) {
    const rows: string[][] = [];
    let headerRow: string[] | null = null;

    node.content.forEach((row, rowIndex) => {
      const cells: string[] = [];
      let isHeader = false;

      row.content.forEach((cell) => {
        let tempState: SerializerState = { ...state, output: '' };
        cell.content.forEach((child) => serializeNode(child, tempState));
        cells.push(tempState.output.trim());

        if (cell.attrs.header) {
          isHeader = true;
        }
      });

      if (isHeader && rowIndex === 0) {
        headerRow = cells;
      } else {
        rows.push(cells);
      }
    });

    // 输出表头
    if (headerRow) {
      state.output += '| ' + headerRow.join(' | ') + ' |\n';
      state.output += '| ' + headerRow.map(() => '---').join(' | ') + ' |\n';
    }

    // 输出数据行
    rows.forEach((row) => {
      state.output += '| ' + row.join(' | ') + ' |\n';
    });

    state.output += '\n';
  },

  tableRow(_node, _state) {
    // 由 table 统一处理
  },

  tableCell(_node, _state) {
    // 由 table 统一处理
  },

  hardBreak(_node, state) {
    state.output += '  \n';
  },
};

/**
 * Mark 包装器
 */
const markWrappers: Record<string, (text: string, mark: Mark) => string> = {
  bold(text) {
    return `**${text}**`;
  },

  italic(text) {
    return `*${text}*`;
  },

  strike(text) {
    return `~~${text}~~`;
  },

  code(text) {
    // 处理包含反引号的情况
    if (text.includes('`')) {
      return `\`\` ${text} \`\``;
    }
    return `\`${text}\``;
  },

  link(text, mark) {
    const href = mark.attrs.href || '';
    const title = mark.attrs.title;
    if (title) {
      return `[${text}](${href} "${title}")`;
    }
    return `[${text}](${href})`;
  },

  highlight(text) {
    return `==${text}==`;
  },

  underline(text) {
    // Markdown 不原生支持下划线，使用 HTML
    return `<u>${text}</u>`;
  },
};

export default serializeToMarkdown;
