package com.lingyue.document.entity;

import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableName;
import com.lingyue.common.domain.entity.SimpleModel;
import com.lingyue.common.mybatis.PostgreSqlJsonbTypeHandler;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import lombok.EqualsAndHashCode;

import java.util.List;

/**
 * 文档块实体（参考飞书 Block 设计）
 * 表示文档中的一个结构化内容块（段落、标题、表格、列表等）
 * 
 * 核心设计：
 * - 块内容由多个 TextElement 组成，实体作为元素嵌入，而非通过字符偏移定位
 * - 这样编辑时只需修改对应元素，不会导致其他元素位置失效
 * 
 * @author lingyue
 * @since 2026-01-21
 */
@EqualsAndHashCode(callSuper = true)
@Data
@TableName(value = "document_blocks", autoResultMap = true)
@Schema(description = "文档块实体")
public class DocumentBlock extends SimpleModel {
    
    @Schema(description = "文档ID")
    @TableField("document_id")
    private String documentId;
    
    @Schema(description = "父块ID（支持嵌套结构）")
    @TableField("parent_id")
    private String parentId;
    
    @Schema(description = "子块ID列表")
    @TableField(value = "children", typeHandler = PostgreSqlJsonbTypeHandler.class)
    private List<String> children;
    
    @Schema(description = "块序号（在同级中的顺序）")
    @TableField("block_index")
    private Integer blockIndex;
    
    @Schema(description = "块类型", example = "page/heading1/heading2/text/bullet/ordered/table/image/code/quote")
    @TableField("block_type")
    private String blockType;
    
    @Schema(description = "块内元素列表（TextElement数组）", 
            example = "[{\"type\":\"text_run\",\"content\":\"Hello\"},{\"type\":\"entity\",\"entityId\":\"xxx\"}]")
    @TableField(value = "elements", typeHandler = PostgreSqlJsonbTypeHandler.class)
    private List<TextElement> elements;
    
    @Schema(description = "块样式")
    @TableField(value = "style", typeHandler = PostgreSqlJsonbTypeHandler.class)
    private Object style;
    
    @Schema(description = "块元数据")
    @TableField(value = "metadata", typeHandler = PostgreSqlJsonbTypeHandler.class)
    private Object metadata;
    
    /**
     * 文本元素（内嵌类）
     * 参考飞书的 TextElement 设计
     */
    @Data
    @Schema(description = "文本元素")
    public static class TextElement {
        
        @Schema(description = "元素类型", example = "text_run/entity/mention_doc/link/equation")
        private String type;
        
        // ===== text_run 类型 =====
        @Schema(description = "文本内容（type=text_run时）")
        private String content;
        
        @Schema(description = "文本样式")
        private TextStyle style;
        
        // ===== entity 类型（我们的特色：实体标注）=====
        @Schema(description = "实体ID（type=entity时）")
        private String entityId;
        
        @Schema(description = "实体显示文本")
        private String entityText;
        
        @Schema(description = "实体类型", example = "PERSON/ORG/LOC/DATE/MONEY")
        private String entityType;
        
        @Schema(description = "是否已确认")
        private Boolean confirmed;
        
        // ===== link 类型 =====
        @Schema(description = "链接URL")
        private String url;
        
        // ===== mention_doc 类型 =====
        @Schema(description = "引用文档ID")
        private String refDocId;
        
        @Schema(description = "引用文档标题")
        private String refDocTitle;
    }
    
    /**
     * 文本样式
     */
    @Data
    @Schema(description = "文本样式")
    public static class TextStyle {
        private Boolean bold;
        private Boolean italic;
        private Boolean underline;
        private Boolean strikethrough;
        private String textColor;
        private String backgroundColor;
        private Boolean inlineCode;
    }
    
    /**
     * 获取块的纯文本内容（用于搜索和NER）
     */
    public String getPlainText() {
        if (elements == null || elements.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (TextElement el : elements) {
            if ("text_run".equals(el.getType()) && el.getContent() != null) {
                sb.append(el.getContent());
            } else if ("entity".equals(el.getType()) && el.getEntityText() != null) {
                sb.append(el.getEntityText());
            }
        }
        return sb.toString();
    }
    
    /**
     * 获取块的HTML渲染（原文视图）
     */
    public String toHtml() {
        if (elements == null || elements.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (TextElement el : elements) {
            if ("text_run".equals(el.getType())) {
                sb.append(escapeHtml(el.getContent()));
            } else if ("entity".equals(el.getType())) {
                sb.append(escapeHtml(el.getEntityText()));
            } else if ("link".equals(el.getType())) {
                sb.append("<a href=\"").append(el.getUrl()).append("\">")
                  .append(escapeHtml(el.getContent())).append("</a>");
            }
        }
        return wrapWithTag(sb.toString());
    }
    
    /**
     * 获取块的HTML渲染（标记视图，实体高亮）
     */
    public String toMarkedHtml() {
        if (elements == null || elements.isEmpty()) {
            return "";
        }
        StringBuilder sb = new StringBuilder();
        for (TextElement el : elements) {
            if ("text_run".equals(el.getType())) {
                sb.append(escapeHtml(el.getContent()));
            } else if ("entity".equals(el.getType())) {
                String cssClass = getEntityCssClass(el.getEntityType());
                String safeEntityId = escapeHtml(el.getEntityId());
                String safeEntityType = escapeHtml(el.getEntityType());
                sb.append("<span class=\"").append(cssClass).append("\" ")
                  .append("data-entity-id=\"").append(safeEntityId).append("\" ")
                  .append("data-type=\"").append(safeEntityType).append("\" ")
                  .append("onclick=\"showEntityEditModal(event,'").append(safeEntityId).append("')\" ")
                  .append("contenteditable=\"false\">")
                  .append(escapeHtml(el.getEntityText()))
                  .append("</span>");
            }
        }
        return wrapWithTag(sb.toString());
    }
    
    private String wrapWithTag(String content) {
        return switch (blockType) {
            case "heading1" -> "<h1>" + content + "</h1>";
            case "heading2" -> "<h2>" + content + "</h2>";
            case "heading3" -> "<h3>" + content + "</h3>";
            case "bullet" -> "<li>" + content + "</li>";
            case "ordered" -> "<li>" + content + "</li>";
            case "quote" -> "<blockquote>" + content + "</blockquote>";
            case "code" -> "<pre><code>" + content + "</code></pre>";
            default -> "<p>" + content + "</p>";
        };
    }
    
    private String getEntityCssClass(String entityType) {
        return switch (entityType) {
            case "PERSON" -> "entity-highlight person";
            case "ORG" -> "entity-highlight org";
            case "LOC" -> "entity-highlight location";
            case "DATE" -> "entity-highlight date";
            case "NUMBER", "MONEY", "DATA" -> "entity-highlight data";
            case "CONCEPT" -> "entity-highlight concept";
            default -> "entity-highlight entity";
        };
    }
    
    private String escapeHtml(String text) {
        if (text == null) return "";
        return text.replace("&", "&amp;")
                   .replace("<", "&lt;")
                   .replace(">", "&gt;")
                   .replace("\"", "&quot;");
    }
}
