package com.lanyuanxiaoyao.leopard.server.helper;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringJoiner;
import lombok.Getter;
import lombok.Setter;

/**
 * Markdown文档构建助手类
 *
 * <p>该类提供了一套流畅的API，用于构建结构化的Markdown文档。
 * 支持标题、列表、代码块、表格、链接等多种Markdown元素的构建。</p>
 *
 * <h2>开发说明</h2>
 * <p>MdHelper采用构建器模式和树形结构设计，通过Section（节）组织文档结构，
 * 每个Section可以包含子Section，形成树形的文档结构。使用时通过{@link #of()}方法
 * 获取初始构建器，然后通过链式调用添加各种元素，最后调用{@link SectionBuilder#build()}
 * 方法生成Markdown文本。</p>
 *
 * <h3>核心组件</h3>
 * <ul>
 *   <li>{@link Section}: 表示文档中的一个节，如标题、段落、列表等，是树形结构的基本单位</li>
 *   <li>{@link SectionBuilder}: 节构建器，提供添加各种元素的API</li>
 *   <li>{@link MetaData}: 元数据，表示一行数据，可以是普通文本或键值对</li>
 *   <li>{@link Fonts}: 字体样式处理类，用于处理文本样式</li>
 *   <li>{@link MdParser}: Markdown解析器，负责将树形结构解析为Markdown文本</li>
 * </ul>
 *
 * <h3>调用流程</h3>
 * <ol>
 *   <li>通过{@link #of()}方法创建根构建器</li>
 *   <li>通过构建器的各种方法添加文档元素，如标题、文本、列表等</li>
 *   <li>对于列表、引用等可嵌套的元素，会返回新的构建器实例</li>
 *   <li>通过{@link SectionBuilder#endXxx()}方法结束嵌套结构，返回上层构建器</li>
 *   <li>调用{@link SectionBuilder#build()}方法生成最终的Markdown文本</li>
 * </ol>
 *
 * <h3>数据流动</h3>
 * <ol>
 *   <li>用户调用构建器方法添加内容</li>
 *   <li>构建器方法创建对应的{@link Section}对象并添加到当前节的子节列表中</li>
 *   <li>对于嵌套结构，会创建新的构建器实例，形成链式调用关系</li>
 *   <li>调用{@link SectionBuilder#build()}时，触发{@link MdParser}进行深度优先遍历解析</li>
 *   <li>{@link MdParser}递归遍历所有节，根据节类型调用相应的解析方法生成Markdown文本</li>
 *   <li>最终返回完整的Markdown字符串</li>
 * </ol>
 *
 * <p>使用示例：</p>
 * <pre>
 * String markdown = MdHelper.of()
 *     .bigTitle("主标题")
 *     .title("副标题")
 *     .text("这是一段普通文本")
 *     .ul()
 *         .text("无序列表项1")
 *         .text("无序列表项2")
 *     .endUl()
 *     .build();
 * </pre>
 *
 * @author liuqichun03
 * @since 2022/11/8
 */
public class MdHelper {


  /**
   * 创建一个新的Markdown文档构建器
   *
   * @return SectionBuilder 文档构建器实例
   */
  public static SectionBuilder of() {
    return new SectionBuilder(new Section(Section.Type.NORMAL, null, null, null, 0));
  }


  /**
   * 文本样式枚举
   *
   * <p>定义了Markdown文本支持的各种样式，包括粗体、斜体、颜色等。</p>
   */
  @Getter
  public enum Style {
    /**
     * 普通文本样式
     */
    NORMAL("normal"),

    /**
     * 粗体样式
     */
    BOLD("bold"),

    /**
     * 斜体样式
     */
    ITALIC("italic"),

    /**
     * 红色文本
     */
    RED("red"),

    /**
     * 绿色文本
     */
    GREEN("green"),

    /**
     * 灰色文本
     */
    GRAY("gray"),

    /**
     * 黄色文本
     */
    YELLOW("gold"),

    /**
     * 蓝色文本
     */
    BLUE("blue");

    private final String name;

    Style(String name) {
      this.name = name;
    }
  }

  /**
   * 字体样式处理类
   *
   * <p>用于处理文本的样式，支持组合多种样式。</p>
   */
  public static class Fonts {
    /**
     * 空字体实例
     */
    public static final Fonts EMPTY = Fonts.of("");
    private final String text;
    private Set<Style> styles = Collections.emptySet();

    private Fonts(String text, Style... style) {
      this.text = text != null ? text : "";
      if (style != null && style.length > 0) {
        this.styles = new HashSet<>(Arrays.asList(style));
      }
    }


    /**
     * 创建普通文本字体
     *
     * @param text 文本内容
     * @return Fonts 字体实例
     */
    public static Fonts of(String text) {
      return new Fonts(text, Style.NORMAL);
    }

    /**
     * 创建带指定样式的字体
     *
     * @param text  文本内容
     * @param style 样式列表
     * @return Fonts 字体实例
     */
    public static Fonts of(String text, Style... style) {
      return new Fonts(text, style);
    }

    /**
     * 判断字体是否为空
     *
     * @return boolean 如果文本为空则返回true
     */
    public boolean isEmpty() {
      return this.text == null || this.text.isEmpty();
    }

    @Override
    public String toString() {
      if (styles.contains(Style.NORMAL)) {
        return text;
      }
      String last = text;
      for (Style style : styles) {
        last = parseStyle(last, style);
      }
      return last;
    }


    /**
     * 解析并应用指定样式到文本
     *
     * @param text  原始文本
     * @param style 要应用的样式
     * @return String 应用样式后的文本
     */
    private String parseStyle(String text, Style style) {
      if (text == null || style == null) {
        return text;
      }
      switch (style) {
        case NORMAL:
          break;
        case BOLD:
          return "**" + text + "**";
        case ITALIC:
          return "*" + text + "*";
        case RED:
        case GREEN:
        case BLUE:
        case YELLOW:
          return "<font color='" + style.getName() + "'>" + text + "</font>";
      }
      return text;
    }
  }

  /**
   * 元数据类
   *
   * <p>代表一行数据，可以是一个普通文本或一个键值对数据。</p>
   */
  public static class MetaData {
    /**
     * 默认键值分隔符
     */
    public static final String DEFAULT_SEPARATOR = "：";

    /**
     * 默认值分隔符
     */
    public static final String DEFAULT_VALUE_SEPARATOR = " | ";

    /**
     * 链接模板
     */
    public static final String LINK_TEMPLATE = "[%s▸](%s)";

    private final Type type;
    private final Fonts text;
    private final Collection<Fonts> values;
    private final String separator = DEFAULT_SEPARATOR;
    private final String valueSeparator = DEFAULT_VALUE_SEPARATOR;

    /**
     * 创建普通文本元数据
     *
     * @param text 文本内容
     */
    public MetaData(Fonts text) {
      this(text, null);
    }

    /**
     * 创建指定类型的元数据
     *
     * @param type 元数据类型
     */
    public MetaData(Type type) {
      this(type, null, null);
    }

    /**
     * 创建键值对元数据
     *
     * @param text   键文本
     * @param values 值集合
     */
    public MetaData(Fonts text, Collection<Fonts> values) {
      this(Type.NORMAL, text, values);
    }

    /**
     * 创建指定类型的键值对元数据
     *
     * @param type   元数据类型
     * @param text   键文本
     * @param values 值集合
     */
    public MetaData(Type type, Fonts text, Collection<Fonts> values) {
      this.type = type;
      this.text = text;
      this.values = values;
    }

    @Override
    public String toString() {
      return generateString(this.valueSeparator);
    }

    /**
     * 生成字符串表示
     *
     * @param valueSeparator 值分隔符
     * @return String 字符串表示
     */
    private String generateString(String valueSeparator) {
      boolean hasValues = values != null && !values.isEmpty();
      boolean hasText = text != null && !text.isEmpty();
      StringJoiner joiner = new StringJoiner(valueSeparator);
      String ret = "";
      switch (type) {
        case NORMAL:
          if (hasText && hasValues) {
            values.forEach(v -> joiner.add(v.toString()));
            ret = text + separator + joiner;
          } else if (!hasText && hasValues) {
            values.forEach(v -> joiner.add(v.toString()));
            ret = joiner.toString();
          } else if (hasText) {
            ret = text.toString();
          }
          break;
        case LINK:
          if (hasText && hasValues) {
            Fonts fonts = values.stream().findFirst().orElse(null);
            if (fonts == null) {
              break;
            }
            ret = String.format(LINK_TEMPLATE, text, fonts);
          } else if (!hasText && hasValues) {
            Fonts url = values.stream().findFirst().orElse(null);
            if (url == null) {
              break;
            }
            ret = String.format(LINK_TEMPLATE, url, url);
          } else if (hasText) {
            ret = String.format(LINK_TEMPLATE, text, text);
          }
          break;
        case LINK_LIST:
          if (hasText && hasValues) {
            ret = text + separator + generateLinkList(values);
          } else if (!hasText && hasValues) {
            ret = generateLinkList(values);
          } else if (hasText) {
            ret = String.format(LINK_TEMPLATE, text, text);
          }
          break;
        case BR:
          ret = "<br>";
      }
      return ret;
    }


    /**
     * 生成链接列表
     *
     * @param values 链接值集合
     * @return String 链接列表字符串
     */
    private String generateLinkList(Collection<Fonts> values) {
      if (values == null || values.isEmpty()) {
        return "";
      }
      Object[] valueArr = values.toArray();
      StringJoiner linkList = new StringJoiner(valueSeparator);
      for (int i = 0; i + 1 < valueArr.length; i += 2) {
        linkList.add(String.format(LINK_TEMPLATE, valueArr[i], valueArr[i + 1]));
      }
      boolean isPairNum = (valueArr.length % 2) == 0;
      if (!isPairNum) {
        String lastUrl = valueArr[valueArr.length - 1].toString();
        linkList.add(String.format(LINK_TEMPLATE, lastUrl, lastUrl));
      }
      return linkList.toString();
    }

    /**
     * 元数据类型枚举
     */
    private enum Type {
      /**
       * 普通文本类型
       */
      NORMAL,

      /**
       * 链接类型
       */
      LINK,

      /**
       * 链接列表类型
       */
      LINK_LIST,

      /**
       * 换行类型
       */
      BR,
    }
  }


  /**
   * 文档节类
   *
   * <p>表示Markdown文档中的一个节，可以包含子节，形成树状结构。</p>
   */
  @Getter
  private static class Section {
    private final int depth;
    @Setter
    private Type type;
    @Setter
    private Object data;
    @Setter
    private Section parent;
    @Setter
    private List<Section> children;

    // 添加language字段用于存储代码语言
    @Setter
    private String language;

    /**
     * 构造一个新的文档节
     *
     * @param type     节类型
     * @param data     节数据
     * @param parent   父节
     * @param children 子节列表
     * @param depth    节深度
     */
    private Section(Type type, Object data, Section parent, List<Section> children, int depth) {
      this.type = type;
      this.data = data;
      this.parent = parent;
      this.children = children;
      this.depth = depth;
    }


    /**
     * 添加子节
     *
     * @param child 子节
     */
    public void addChild(Section child) {
      lazyInitChildren();
      children.add(child);
    }

    /**
     * 判断子节是否为空
     *
     * @return boolean 如果没有子节则返回true
     */
    public boolean childIsEmpty() {
      return children == null || children.isEmpty();
    }

    /**
     * 解析节内容
     *
     * @param latestData 最新数据
     * @return StringBuilder 解析后的内容
     */
    private StringBuilder parse(StringBuilder latestData) {
      switch (type) {
        case LINK:
        case NORMAL:
          latestData.append('\n').append(parseData(""));
          return latestData;
        case BIG_TITLE:
          latestData.append('\n').append(parseData("## "));
          return latestData;
        case TITLE:
          latestData.append('\n').append(parseData("### "));
          return latestData;
        case SUBTITLE:
          latestData.append('\n').append(parseData("#### "));
          return latestData;
        case REF:
          return parseRefSection(latestData);
        case CODE:
          StringBuilder codeBlock = new StringBuilder(latestData.length() + 10);
          String lang = language != null ? language : "";
          codeBlock.append("\n```").append(lang).append(latestData).append("\n```");
          return codeBlock;
        case ORDER_LIST:
          return parseOrderListSection(latestData);
        case UN_ORDER_LIST:
          return parseUnOrderListSection(latestData);
        case TABLE:
          return parseTableSection(latestData);
        case BR:
          return latestData.append(parseData(""));
        case DIVIDER:
          return latestData.append("\n---");
      }
      return latestData;
    }

    /**
     * 解析数据前缀
     *
     * @param prefix 前缀
     * @return String 解析后的数据
     */
    private String parseData(String prefix) {
      if (data == null) {
        return "";
      }
      return prefix + data;
    }

    /**
     * 解析引用节
     *
     * @param latestData 最新数据
     * @return StringBuilder 解析后的内容
     */
    private StringBuilder parseRefSection(StringBuilder latestData) {
      String dataStr = latestData.toString();
      if (dataStr.isEmpty()) {
        return latestData;
      }
      StringBuilder data = new StringBuilder(dataStr.length() * 2);
      if (!dataStr.startsWith("\n")) {
        data.append("> ");
      }
      char last = 0;
      for (int i = 0; i < dataStr.length(); i++) {
        char c = dataStr.charAt(i);
        if (last == '\n' && c != '\n') {
          data.append("> ");
        }
        data.append(c);
        last = c;
      }
      return data;
    }

    /**
     * 解析有序列表节
     *
     * @param latestData 最新数据
     * @return StringBuilder 解析后的内容
     */
    private StringBuilder parseOrderListSection(StringBuilder latestData) {
      char[] chars = latestData.toString().toCharArray();
      if (chars.length == 0) {
        return latestData;
      }
      StringBuilder data = new StringBuilder(chars.length * 2);
      String padding = String.join("", Collections.nCopies(depth * 4, " "));
      int order = 1;
      if (chars[0] != '\n') {
        data.append(padding).append(order++).append(". ");
      }
      char last = 0;
      for (char c : chars) {
        if (last == '\n' && c != '\n' && c != ' ') {
          data.append(padding).append(order++).append(". ");
        }
        data.append(c);
        last = c;
      }
      return data;
    }

    /**
     * 解析无序列表节
     *
     * @param latestData 最新数据
     * @return StringBuilder 解析后的内容
     */
    private StringBuilder parseUnOrderListSection(StringBuilder latestData) {
      char[] chars = latestData.toString().toCharArray();
      if (chars.length == 0) {
        return latestData;
      }
      StringBuilder data = new StringBuilder(chars.length * 2);
      String padding = String.join("", Collections.nCopies(depth * 4, " "));
      if (chars[0] != '\n') {
        data.append(padding).append("- ");
      }
      char last = 0;
      for (char c : chars) {
        if (last == '\n' && c != '\n' && c != ' ') {
          data.append(padding).append("- ");
        }
        data.append(c);
        last = c;
      }
      return data;
    }

    /**
     * 解析表格节
     *
     * @param latestData 最新数据
     * @return StringBuilder 解析后的内容
     */
    private StringBuilder parseTableSection(StringBuilder latestData) {
      if (data != null) {
        Object[][] tableData = (Object[][]) data;
        if (tableData.length > 0 && tableData[0].length > 0) {
          StringJoiner titles = new StringJoiner(" | "), extras = new StringJoiner(" | ");
          for (Object t : tableData[0]) {
            titles.add(t != null ? t.toString() : "");
            extras.add("-");
          }
          latestData.append("\n")
            .append("| ").append(titles).append(" |")
            .append('\n')
            .append("| ").append(extras).append(" |");
          for (int i = 1; i < tableData.length; i++) {
            StringJoiner dataJoiner = new StringJoiner(" | ");
            for (int j = 0; j < tableData[i].length; j++) {
              dataJoiner.add(tableData[i][j] != null ? tableData[i][j].toString() : "");
            }
            latestData.append('\n')
              .append("| ").append(dataJoiner).append(" |");
          }
        }
      }
      return latestData.append('\n');
    }

    /**
     * 延迟初始化子节列表
     */
    private void lazyInitChildren() {
      if (children == null) {
        children = new ArrayList<>();
      }
    }

    /**
     * 节类型枚举
     */
    private enum Type {
      /**
       * 普通文本节
       */
      NORMAL,

      /**
       * 大标题节（h2）
       */
      BIG_TITLE,

      /**
       * 标题节（h3）
       */
      TITLE,

      /**
       * 子标题节（h4）
       */
      SUBTITLE,

      /**
       * 引用节
       */
      REF,

      /**
       * 代码节
       */
      CODE,

      /**
       * 表格节
       */
      TABLE,

      /**
       * 有序列表节
       */
      ORDER_LIST,

      /**
       * 无序列表节
       */
      UN_ORDER_LIST,

      /**
       * 链接节
       */
      LINK,

      /**
       * 换行节
       */
      BR,

      /**
       * 分割线节
       */
      DIVIDER
    }
  }

  /**
   * 文档节构建器
   *
   * <p>提供流畅的API用于构建Markdown文档的各个节。</p>
   */
  public static class SectionBuilder {
    private static final MdParser parser = new MdParser();
    private final Section curSec;
    private Section parentSec;
    private SectionBuilder parentBuilder;

    /**
     * 构造一个新的节构建器
     *
     * @param curSec 当前节
     */
    private SectionBuilder(Section curSec) {
      this.curSec = curSec;
    }

    /**
     * 构造一个新的节构建器
     *
     * @param curSec        当前节
     * @param parentSec     父节
     * @param parentBuilder 父构建器
     */
    private SectionBuilder(Section curSec, Section parentSec, SectionBuilder parentBuilder) {
      this.curSec = curSec;
      this.parentSec = parentSec;
      this.parentBuilder = parentBuilder;
    }


    /**
     * 添加普通文本
     *
     * @param text 文本内容
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder text(String text) {
      return text(text, (String) null);
    }

    /**
     * 添加键值对文本
     *
     * @param name  键名
     * @param value 值
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder text(String name, String value) {
      if (name != null) {
        Collection<Fonts> values
          = value != null ? Collections.singletonList(Fonts.of(value)) : Collections.emptyList();
        curSec.addChild(new Section(Section.Type.NORMAL,
          new MetaData(MetaData.Type.NORMAL, Fonts.of(name, (Style) null), values),
          curSec, null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 添加带样式的文本
     *
     * @param text  文本内容
     * @param style 样式
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder text(String text, Style... style) {
      if (text != null) {
        curSec.addChild(new Section(Section.Type.NORMAL, new MetaData(Fonts.of(text, style)), curSec,
          null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 添加值列表文本
     *
     * @param values 值列表
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder text(Collection<String> values) {
      if (values != null && !values.isEmpty()) {
        text(null, values);
      }
      return this;
    }

    /**
     * 添加带键名的值列表文本
     *
     * @param name   键名
     * @param values 值列表
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder text(String name, Collection<String> values) {
      if (values == null || values.isEmpty()) {
        return text(name);
      }
      return text(name, null, values);
    }

    /**
     * 添加带样式的值列表文本
     *
     * @param name       键名
     * @param valueStyle 值样式
     * @param values     值列表
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder text(String name, Style valueStyle, Collection<String> values) {
      if (values == null || values.isEmpty()) {
        return text(name);
      }
      if (valueStyle == null) {
        valueStyle = Style.NORMAL;
      }
      List<Fonts> ele = new ArrayList<>(values.size());
      for (String value : values) {
        ele.add(Fonts.of(value, valueStyle));
      }
      curSec.addChild(new Section(Section.Type.NORMAL, new MetaData(Fonts.of(name), ele), curSec, null,
        curSec.getDepth()));
      return this;
    }

    /**
     * 添加大标题（h2）
     *
     * @param title 标题内容
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder bigTitle(String title) {
      if (title != null && !title.isBlank()) {
        curSec.addChild(new Section(Section.Type.BIG_TITLE, new MetaData(Fonts.of(title)), curSec,
          null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 添加标题（h3）
     *
     * @param title 标题内容
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder title(String title) {
      return title(title, Style.NORMAL);
    }

    /**
     * 添加带颜色的标题（h3）
     *
     * @param title 标题内容
     * @param color 标题颜色
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder title(String title, Style color) {
      if (title != null && !title.isBlank()) {
        curSec.addChild(new Section(Section.Type.TITLE, new MetaData(Fonts.of(title, color)),
          curSec, null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 添加带标签的标题（h3）
     *
     * @param title 标题内容
     * @param label 标签列表
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder title(String title, Fonts... label) {
      return title(title, null, label);
    }

    /**
     * 添加带颜色和标签的标题（h3）
     *
     * @param title      标题内容
     * @param titleColor 标题颜色
     * @param label      标签列表
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder title(String title, Style titleColor, Fonts... label) {
      if (title != null && !title.isBlank()) {
        if (titleColor == null) {
          titleColor = Style.NORMAL;
        }
        List<Fonts> labelList = label != null ? Arrays.asList(label) : Collections.emptyList();
        curSec.addChild(new Section(Section.Type.TITLE, new MetaData(Fonts.of(title, titleColor), labelList),
          curSec, null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 添加子标题（h4）
     *
     * @param title 子标题内容
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder subTitle(String title) {
      if (title != null && !title.isBlank()) {
        curSec.addChild(new Section(Section.Type.SUBTITLE, new MetaData(Fonts.of(title)),
          curSec, null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 开始引用节
     *
     * @return SectionBuilder 引用节构建器实例
     */
    public SectionBuilder ref() {
      Section refSection = new Section(Section.Type.REF, null, curSec, new ArrayList<>(), curSec.getDepth());
      curSec.addChild(refSection);
      return new SectionBuilder(refSection, curSec, this);
    }

    /**
     * 结束引用节
     *
     * @return SectionBuilder 父构建器实例
     */
    public SectionBuilder endRef() {
      return this.parentBuilder != null ? this.parentBuilder : this;
    }

    /**
     * 开始表格节
     *
     * @return TableDataBuilder 表格数据构建器实例
     */
    public TableDataBuilder table() {
      return new TableDataBuilder(curSec, this);
    }

    /**
     * 添加链接
     *
     * @param url 链接地址
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder link(String url) {
      return link(null, url);
    }

    /**
     * 添加带名称的链接
     *
     * @param name 链接名称
     * @param url  链接地址
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder link(String name, String url) {
      if (name == null || name.isBlank()) {
        name = url;
      }
      if (url != null && !url.isBlank()) {
        MetaData links = new MetaData(MetaData.Type.LINK, Fonts.of(name),
          Collections.singletonList(Fonts.of(url)));
        curSec.addChild(new Section(Section.Type.NORMAL, links, curSec, null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 添加链接映射
     *
     * @param urlMappings 链接映射
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder links(Map<String, String> urlMappings) {
      return links(null, urlMappings);
    }

    /**
     * 添加带名称的链接映射
     *
     * @param name        链接组名称
     * @param urlMappings 链接映射
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder links(String name, Map<String, String> urlMappings) {
      if (urlMappings != null && !urlMappings.isEmpty()) {
        List<Fonts> serialUrlInfos = new ArrayList<>(urlMappings.size() * 2);
        for (Map.Entry<String, String> entry : urlMappings.entrySet()) {
          String key = entry.getKey();
          String value = entry.getValue();
          serialUrlInfos.add(Fonts.of(key != null ? key : ""));
          serialUrlInfos.add(Fonts.of(value != null ? value : ""));
        }
        Fonts wrappedName = name != null && !name.isBlank() ? Fonts.of(name) : Fonts.EMPTY;
        MetaData linksGroup = new MetaData(MetaData.Type.LINK_LIST, wrappedName, serialUrlInfos);
        curSec.addChild(new Section(Section.Type.NORMAL, linksGroup, curSec, null, curSec.getDepth()));
      }
      return this;
    }

    /**
     * 开始有序列表节
     *
     * @return SectionBuilder 有序列表构建器实例
     */
    public SectionBuilder ol() {
      int depth = (curSec.getType() == Section.Type.ORDER_LIST || curSec.getType() == Section.Type.UN_ORDER_LIST)
        ? curSec.getDepth() + 1
        : curSec.getDepth();
      Section OrderListSec = new Section(Section.Type.ORDER_LIST, null, curSec, new ArrayList<>(), depth);
      curSec.addChild(OrderListSec);
      return new SectionBuilder(OrderListSec, curSec, this);
    }

    /**
     * 结束有序列表节
     *
     * @return SectionBuilder 父构建器实例
     */
    public SectionBuilder endOl() {
      return this.parentBuilder != null ? this.parentBuilder : this;
    }

    /**
     * 开始无序列表节
     *
     * @return SectionBuilder 无序列表构建器实例
     */
    public SectionBuilder ul() {
      int depth = (curSec.getType() == Section.Type.ORDER_LIST || curSec.getType() == Section.Type.UN_ORDER_LIST)
        ? curSec.getDepth() + 1
        : curSec.getDepth();
      Section unOrderListSec = new Section(Section.Type.UN_ORDER_LIST, null, curSec, new ArrayList<>(), depth);
      curSec.addChild(unOrderListSec);
      return new SectionBuilder(unOrderListSec, curSec, this);
    }

    /**
     * 结束无序列表节
     *
     * @return SectionBuilder 父构建器实例
     */
    public SectionBuilder endUl() {
      return this.parentBuilder != null ? this.parentBuilder : this;
    }

    /**
     * 开始代码节
     *
     * @return SectionBuilder 代码节构建器实例
     */
    public SectionBuilder code() {
      Section codeSec = new Section(Section.Type.CODE, null, curSec, new ArrayList<>(), curSec.getDepth());
      curSec.addChild(codeSec);
      return new SectionBuilder(codeSec, curSec, this);
    }

    /**
     * 创建带有指定语言的代码块
     *
     * @param language 代码语言，如java、python等
     * @return SectionBuilder 代码节构建器实例
     */
    public SectionBuilder code(String language) {
      Section codeSec = new Section(Section.Type.CODE, null, curSec, new ArrayList<>(), curSec.getDepth());
      codeSec.setLanguage(language);
      curSec.addChild(codeSec);
      return new SectionBuilder(codeSec, curSec, this);
    }

    /**
     * 结束代码节
     *
     * @return SectionBuilder 父构建器实例
     */
    public SectionBuilder endCode() {
      return this.parentBuilder != null ? this.parentBuilder : this;
    }

    /**
     * 添加换行
     *
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder br() {
      curSec.addChild(new Section(Section.Type.BR, new MetaData(MetaData.Type.BR), parentSec, null,
        curSec.getDepth()));
      return this;
    }

    /**
     * 添加分割线
     *
     * @return SectionBuilder 构建器实例
     */
    public SectionBuilder divider() {
      curSec.addChild(new Section(Section.Type.DIVIDER, null, curSec, null, curSec.getDepth()));
      return this;
    }

    /**
     * 构建Markdown文档
     *
     * @return String Markdown文档字符串
     */
    public String build() {
      return parser.parse(curSec);
    }
  }

  /**
   * 表格数据构建器
   *
   * <p>用于构建表格数据。</p>
   */
  public static class TableDataBuilder {
    private final Section parentSec;
    private final SectionBuilder parentBuilder;
    private Object[][] tableData;

    /**
     * 构造一个新的表格数据构建器
     *
     * @param parentSec     父节
     * @param parentBuilder 父构建器
     */
    private TableDataBuilder(Section parentSec, SectionBuilder parentBuilder) {
      this.parentSec = parentSec;
      this.parentBuilder = parentBuilder;
    }


    /**
     * 设置表格数据
     *
     * @param table 表格数据
     * @return TableDataBuilder 构建器实例
     */
    public TableDataBuilder data(Object[][] table) {
      if (table != null && table.length > 0 && table[0].length > 0) {
        tableData = table;
      }
      return this;
    }

    /**
     * 设置带标题的表格数据
     *
     * @param title 标题行
     * @param data  数据行
     * @return TableDataBuilder 构建器实例
     */
    public TableDataBuilder data(Object[] title, Object[][] data) {
      if (title == null && data != null) {
        return data(data);
      }
      if (data != null && data.length > 0 && data[0].length > 0) {
        int minCol = Math.min(title.length, data[0].length);
        tableData = new Object[data.length + 1][minCol];
        tableData[0] = Arrays.copyOfRange(title, 0, minCol);
        for (int i = 0; i < data.length; i++) {
          tableData[i + 1] = Arrays.copyOfRange(data[i], 0, minCol);
        }
      }
      return this;
    }

    /**
     * 结束表格节
     *
     * @return SectionBuilder 父构建器实例
     */
    public SectionBuilder endTable() {
      parentSec.addChild(new Section(Section.Type.TABLE, tableData, parentSec, null, parentSec.getDepth()));
      return parentBuilder;
    }
  }

  /**
   * Markdown解析器
   *
   * <p>用于解析文档节树并生成最终的Markdown字符串。</p>
   */
  private static class MdParser {
    /**
     * 解析文档节并生成Markdown字符串
     *
     * @param sec 文档节
     * @return String Markdown字符串
     */
    public String parse(Section sec) {
      Section root = findRoot(sec);
      return doParse(root, root).toString().trim();
    }

    /**
     * 查找根节
     *
     * @param sec 文档节
     * @return Section 根节
     */
    private Section findRoot(Section sec) {
      if (sec.getParent() == null) {
        return sec;
      }
      return findRoot(sec.getParent());
    }

    /**
     * 递归解析文档节
     *
     * @param cur  当前节
     * @param root 根节
     * @return StringBuilder 解析后的内容
     */
    private StringBuilder doParse(Section cur, Section root) {
      if (cur == null) {
        return null;
      }
      if (cur.childIsEmpty()) {
        return cur.parse(new StringBuilder());
      }
      StringBuilder childData = new StringBuilder();
      for (Section child : cur.getChildren()) {
        StringBuilder part = doParse(child, root);
        if (part != null) {
          childData.append(part);
        }
      }
      return cur.parse(childData).append(cur.getParent() == root ? '\n' : "");
    }
  }
}