package com.lingyue.ai.controller;

import com.lingyue.ai.dto.ner.*;
import com.lingyue.ai.service.NerService;
import com.lingyue.common.domain.AjaxResult;
import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.web.bind.annotation.*;

import java.util.concurrent.CompletableFuture;

/**
 * NER（命名实体识别）控制器
 *
 * @author lingyue
 * @since 2026-01-19
 */
@Slf4j
@RestController
@RequestMapping("/api/ner")
@RequiredArgsConstructor
@Tag(name = "NER 服务", description = "命名实体识别相关接口")
public class NerController {

    private final NerService nerService;

    /**
     * 从文本中提取实体（同步）
     */
    @PostMapping("/extract")
    @Operation(summary = "提取实体", description = "从给定文本中提取命名实体")
    public AjaxResult extractEntities(@RequestBody NerRequest request) {
        log.info("开始提取实体: documentId={}, textLength={}", 
                request.getDocumentId(), 
                request.getText() != null ? request.getText().length() : 0);
        
        try {
            NerResponse response = nerService.extractEntities(request);
            log.info("实体提取完成: documentId={}, entityCount={}, relationCount={}", 
                    request.getDocumentId(), 
                    response.getEntityCount(), 
                    response.getRelationCount());
            return AjaxResult.success(response);
        } catch (Exception e) {
            log.error("实体提取失败: documentId={}", request.getDocumentId(), e);
            return AjaxResult.error("实体提取失败: " + e.getMessage());
        }
    }

    /**
     * 从文本中提取实体（异步）
     */
    @PostMapping("/extract/async")
    @Operation(summary = "异步提取实体", description = "异步方式从给定文本中提取命名实体")
    public AjaxResult extractEntitiesAsync(@RequestBody NerRequest request) {
        log.info("开始异步提取实体: documentId={}", request.getDocumentId());
        
        try {
            CompletableFuture<NerResponse> future = nerService.extractEntitiesAsync(request);
            // 返回任务已提交的确认
            return AjaxResult.success("NER 任务已提交", "documentId: " + request.getDocumentId());
        } catch (Exception e) {
            log.error("异步实体提取提交失败: documentId={}", request.getDocumentId(), e);
            return AjaxResult.error("异步实体提取提交失败: " + e.getMessage());
        }
    }

    /**
     * 从已提取的实体中抽取关系
     */
    @PostMapping("/relations")
    @Operation(summary = "提取关系", description = "从已提取的实体中抽取实体间的关系")
    public AjaxResult extractRelations(@RequestBody RelationRequest request) {
        log.info("开始提取关系: documentId={}, entityCount={}", 
                request.getDocumentId(), 
                request.getEntities() != null ? request.getEntities().size() : 0);
        
        try {
            RelationResponse response = nerService.extractRelations(request);
            log.info("关系提取完成: documentId={}, relationCount={}", 
                    request.getDocumentId(), 
                    response.getRelationCount());
            return AjaxResult.success(response);
        } catch (Exception e) {
            log.error("关系提取失败: documentId={}", request.getDocumentId(), e);
            return AjaxResult.error("关系提取失败: " + e.getMessage());
        }
    }

    /**
     * 对已解析的文档执行 NER 并保存结果
     */
    @PostMapping("/document/{documentId}")
    @Operation(summary = "文档 NER", description = "对已解析的文档执行 NER 并保存结果到图数据库")
    public AjaxResult extractForDocument(
            @Parameter(description = "文档ID") @PathVariable String documentId,
            @Parameter(description = "用户ID") @RequestParam(required = false) String userId) {
        log.info("开始对文档执行 NER: documentId={}, userId={}", documentId, userId);
        
        try {
            NerResponse response = nerService.extractAndSaveForDocument(documentId, userId);
            if (response.getSuccess()) {
                log.info("文档 NER 完成: documentId={}, entityCount={}, relationCount={}", 
                        documentId, response.getEntityCount(), response.getRelationCount());
                return AjaxResult.success(response);
            } else {
                return AjaxResult.error(response.getErrorMessage());
            }
        } catch (Exception e) {
            log.error("文档 NER 失败: documentId={}", documentId, e);
            return AjaxResult.error("文档 NER 失败: " + e.getMessage());
        }
    }

    /**
     * 对已解析的文档执行 NER 并保存结果（异步）
     */
    @PostMapping("/document/{documentId}/async")
    @Operation(summary = "异步文档 NER", description = "异步对已解析的文档执行 NER 并保存结果")
    public AjaxResult extractForDocumentAsync(
            @Parameter(description = "文档ID") @PathVariable String documentId,
            @Parameter(description = "用户ID") @RequestParam(required = false) String userId) {
        log.info("开始异步对文档执行 NER: documentId={}, userId={}", documentId, userId);
        
        try {
            CompletableFuture<NerResponse> future = nerService.extractAndSaveForDocumentAsync(documentId, userId);
            return AjaxResult.success("文档 NER 任务已提交", "documentId: " + documentId);
        } catch (Exception e) {
            log.error("异步文档 NER 提交失败: documentId={}", documentId, e);
            return AjaxResult.error("异步文档 NER 提交失败: " + e.getMessage());
        }
    }
}
