package com.lingyue.document.controller;

import com.lingyue.common.domain.AjaxResult;
import com.lingyue.document.dto.StructuredDocumentDTO;
import com.lingyue.document.entity.DocumentBlock;
import com.lingyue.document.entity.DocumentBlock.TextElement;
import com.lingyue.document.service.StructuredDocumentService;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.List;

/**
 * 结构化文档控制器（参考飞书设计）
 * 提供编辑器所需的结构化文档和实体标注接口
 * 
 * 核心设计：
 * - 文档由 Block 树组成
 * - 实体作为 TextElement 嵌入块中
 * - 编辑实体 = 修改块的 elements 数组
 * 
 * @author lingyue
 * @since 2026-01-21
 */
@Slf4j
@RestController
@RequestMapping("/api/v1/documents")
@RequiredArgsConstructor
@Tag(name = "结构化文档", description = "文档编辑器接口（参考飞书设计）")
public class StructuredDocumentController {
    
    private final StructuredDocumentService structuredDocumentService;
    
    /**
     * 获取结构化文档
     */
    @GetMapping("/{documentId}/structured")
    @Operation(summary = "获取结构化文档", description = "获取带实体标注的结构化文档，用于编辑器渲染")
    public AjaxResult<?> getStructuredDocument(
            @Parameter(description = "文档ID", required = true)
            @PathVariable String documentId) {
        
        StructuredDocumentDTO document = structuredDocumentService.getStructuredDocument(documentId);
        if (document == null) {
            return AjaxResult.error("文档不存在: " + documentId);
        }
        
        return AjaxResult.success(document);
    }
    
    // ==================== 块操作 ====================
    
    /**
     * 更新块的元素
     */
    @PutMapping("/{documentId}/blocks/{blockId}/elements")
    @Operation(summary = "更新块元素", description = "更新块的 elements 数组")
    public AjaxResult<?> updateBlockElements(
            @PathVariable String documentId,
            @PathVariable String blockId,
            @RequestBody UpdateElementsRequest request) {
        
        try {
            structuredDocumentService.updateBlockElements(blockId, request.getElements());
            return AjaxResult.success("更新成功");
        } catch (Exception e) {
            log.error("更新块元素失败: blockId={}", blockId, e);
            return AjaxResult.error("更新失败: " + e.getMessage());
        }
    }
    
    /**
     * 创建新块
     */
    @PostMapping("/{documentId}/blocks")
    @Operation(summary = "创建块", description = "在文档中创建新块")
    public AjaxResult<?> createBlock(
            @PathVariable String documentId,
            @RequestBody CreateBlockRequest request) {
        
        try {
            DocumentBlock block = structuredDocumentService.createBlock(
                    documentId,
                    request.getParentId(),
                    request.getIndex(),
                    request.getBlockType(),
                    request.getElements()
            );
            return AjaxResult.success("创建成功", block);
        } catch (Exception e) {
            log.error("创建块失败: documentId={}", documentId, e);
            return AjaxResult.error("创建失败: " + e.getMessage());
        }
    }
    
    /**
     * 删除块
     */
    @DeleteMapping("/{documentId}/blocks/{blockId}")
    @Operation(summary = "删除块", description = "删除指定块及其子块")
    public AjaxResult<?> deleteBlock(
            @PathVariable String documentId,
            @PathVariable String blockId) {
        
        structuredDocumentService.deleteBlock(blockId);
        return AjaxResult.success("删除成功");
    }
    
    // ==================== 实体操作 ====================
    
    /**
     * 标记实体（将文本转为实体）
     */
    @PostMapping("/{documentId}/blocks/{blockId}/mark-entity")
    @Operation(summary = "标记实体", description = "将块中的文本片段标记为实体")
    public AjaxResult<?> markEntity(
            @PathVariable String documentId,
            @PathVariable String blockId,
            @RequestBody MarkEntityRequest request) {
        
        try {
            String entityId = structuredDocumentService.markEntity(
                    blockId,
                    request.getElementIndex(),
                    request.getStartOffset(),
                    request.getEndOffset(),
                    request.getEntityType()
            );
            return AjaxResult.success("标记成功", entityId);
        } catch (Exception e) {
            log.error("标记实体失败: blockId={}", blockId, e);
            return AjaxResult.error("标记失败: " + e.getMessage());
        }
    }
    
    /**
     * 取消实体标记（将实体还原为文本）
     */
    @DeleteMapping("/{documentId}/blocks/{blockId}/entities/{entityId}")
    @Operation(summary = "取消实体标记", description = "将实体还原为普通文本")
    public AjaxResult<?> unmarkEntity(
            @PathVariable String documentId,
            @PathVariable String blockId,
            @PathVariable String entityId) {
        
        structuredDocumentService.unmarkEntity(blockId, entityId);
        return AjaxResult.success("取消成功");
    }
    
    /**
     * 更新实体类型
     */
    @PutMapping("/{documentId}/blocks/{blockId}/entities/{entityId}")
    @Operation(summary = "更新实体", description = "更新实体类型")
    public AjaxResult<?> updateEntity(
            @PathVariable String documentId,
            @PathVariable String blockId,
            @PathVariable String entityId,
            @RequestBody UpdateEntityRequest request) {
        
        structuredDocumentService.updateEntityType(blockId, entityId, request.getEntityType());
        return AjaxResult.success("更新成功");
    }
    
    /**
     * 确认实体
     */
    @PostMapping("/{documentId}/blocks/{blockId}/entities/{entityId}/confirm")
    @Operation(summary = "确认实体", description = "确认实体标注正确")
    public AjaxResult<?> confirmEntity(
            @PathVariable String documentId,
            @PathVariable String blockId,
            @PathVariable String entityId) {
        
        structuredDocumentService.confirmEntity(blockId, entityId);
        return AjaxResult.success("确认成功");
    }
    
    // ==================== 请求 DTO ====================
    
    @Data
    public static class UpdateElementsRequest {
        private List<TextElement> elements;
    }
    
    @Data
    public static class CreateBlockRequest {
        private String parentId;
        private Integer index;
        private String blockType;
        private List<TextElement> elements;
    }
    
    @Data
    public static class MarkEntityRequest {
        /** 要标记的元素在 elements 数组中的索引 */
        private Integer elementIndex;
        /** 在该元素文本中的起始位置 */
        private Integer startOffset;
        /** 在该元素文本中的结束位置 */
        private Integer endOffset;
        /** 实体类型 */
        private String entityType;
    }
    
    @Data
    public static class UpdateEntityRequest {
        private String entityType;
    }
}
