package cn.com.poc.writing.aggregate.impl;

import cn.com.poc.agent_application.entity.BizAgentApplicationGcConfigEntity;
import cn.com.poc.agent_application.service.BizAgentApplicationGcConfigService;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.service.BosConfigService;
import cn.com.poc.common.utils.DocumentLoad;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.SSEUtil;
import cn.com.poc.common.utils.UUIDTool;
import cn.com.poc.thirdparty.resource.demand.ai.constants.LLMRoleEnum;
import cn.com.poc.thirdparty.resource.demand.ai.entity.dialogue.Message;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelDemandResult;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.LargeModelResponse;
import cn.com.poc.thirdparty.resource.demand.ai.entity.largemodel.Thinking;
import cn.com.poc.thirdparty.service.LLMService;
import cn.com.poc.writing.aggregate.ExaminationService;
import cn.com.poc.writing.entity.*;
import cn.com.poc.writing.query.ExaminationQueryCondition;
import cn.com.poc.writing.query.ExaminationQueryItem;
import cn.com.poc.writing.service.BizExaminationService;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.com.yict.framemax.frame.service.FmxParamConfigService;
import com.fasterxml.jackson.core.type.TypeReference;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.poi.xwpf.usermodel.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 52747
 * @date 2025/8/14
 */
@Service
public class ExaminationServiceImpl implements ExaminationService {

    private final String startXML = "<examination_questions>";

    private final String endXML = "</examination_questions>";

    private final Logger logger = LoggerFactory.getLogger(ExaminationService.class);

    private final String GC_CONFIG_CODE = "AiGenerateExamination";

    @Resource
    private LLMService llmService;

    @Resource
    private BosConfigService bosConfigService;

    @Resource
    private BizAgentApplicationGcConfigService bizAgentApplicationGcConfigService;

    @Resource
    private BizExaminationService bizExaminationService;

    @Resource
    private FmxParamConfigService fmxParamConfigService;

    @Override
    public ExaminationConfigItemEntity getConfigurationItem() {
        ExaminationConfigItemEntity examinationConfigItemEntity = new ExaminationConfigItemEntity();
        String questionType = fmxParamConfigService.getParam("examination.config.item.question_type");
        String levels = fmxParamConfigService.getParam("examination.config.item.levels");
        String languages = fmxParamConfigService.getParam("examination.config.item.languages");
        String positions = fmxParamConfigService.getParam("examination.config.item.positions");
        if (StringUtils.isBlank(questionType)
                || StringUtils.isBlank(levels)
                || StringUtils.isBlank(languages)
                || StringUtils.isBlank(positions)) {
            throw new BusinessException("获取配置异常");
        }

        examinationConfigItemEntity.setQuestionType(Arrays.stream(questionType.split(";")).collect(Collectors.toList()));
        examinationConfigItemEntity.setLevels(Arrays.stream(levels.split(";")).collect(Collectors.toList()));
        examinationConfigItemEntity.setLanguages(Arrays.stream(languages.split(";")).collect(Collectors.toList()));
        examinationConfigItemEntity.setPositions(Arrays.stream(positions.split(";")).collect(Collectors.toList()));
        return examinationConfigItemEntity;
    }

    @Override
    public void generateExamination(GenerateExaminationEntity generateExaminationEntity, Long userId) {

        BizAgentApplicationGcConfigEntity gcConfigEntity = bizAgentApplicationGcConfigService.getByConfigCode(GC_CONFIG_CODE);
        if (gcConfigEntity == null) {
            throw new BusinessException("无法找到配置，联系管理员");
        }

        Message[] messages = buildMessage(gcConfigEntity.getConfigSystem(), generateExaminationEntity);
        LargeModelResponse largeModelResponse = new LargeModelResponse();
        largeModelResponse.setModel(gcConfigEntity.getLargeModel());
        largeModelResponse.setMessages(messages);
        largeModelResponse.setStream(true);
        largeModelResponse.setMaxTokens(32768);
//        largeModelResponse.setThinking(new Thinking() {{
//            setType("disabled");
//        }});
        largeModelResponse.setUser("GENERATE_EXAMINATION");

        try {
            String examinationId = StringUtils.isNotBlank(generateExaminationEntity.getExaminationId())
                    ? generateExaminationEntity.getExaminationId() : "EXAMINATION_" + UUIDTool.getUUID();

            BufferedReader bufferedReader = llmService.chatChunk(largeModelResponse);
            SSEUtil sseUtil = new SSEUtil();
            List<ExaminationDetail> examinationDetailEntities = outputExaminationBuffer(bufferedReader, sseUtil, examinationId);
            if (CollectionUtils.isEmpty(examinationDetailEntities)) {
                throw new BusinessException("生成试卷题目失败,联系管理员");
            }
            //保存试卷内容
            List<String> questionTypes = generateExaminationEntity.getQuestionType();
            String questionType = StringUtils.join(questionTypes, ",");

            //保存试卷内容
            BizExaminationEntity bizExaminationEntity = new BizExaminationEntity();
            bizExaminationEntity.setExaminationId(examinationId);
            bizExaminationEntity.setMemberId(userId);
            bizExaminationEntity.setIsDeleted(CommonConstant.IsDeleted.N);

            List<BizExaminationEntity> bizExaminationEntities = bizExaminationService.findByExample(bizExaminationEntity, null);
            if (StringUtils.isBlank(generateExaminationEntity.getExaminationId()) || CollectionUtils.isEmpty(bizExaminationEntities)) {
                BizExaminationEntity saveExaminationEntity = new BizExaminationEntity();
                saveExaminationEntity.setExaminationId(examinationId);
                saveExaminationEntity.setMemberId(userId);
                saveExaminationEntity.setTitle(generateExaminationEntity.getTitle());
                saveExaminationEntity.setQuestionType(questionType);
                saveExaminationEntity.setTotalScore(generateExaminationEntity.getTotalScore());
                saveExaminationEntity.setN(generateExaminationEntity.getN());
                saveExaminationEntity.setLevel(generateExaminationEntity.getLevel());
                saveExaminationEntity.setLanguage(generateExaminationEntity.getLanguage());
                saveExaminationEntity.setPositions(generateExaminationEntity.getPositions());
                saveExaminationEntity.setFileUrl(generateExaminationEntity.getFileUrl());
                saveExaminationEntity.setContent(generateExaminationEntity.getContent());
                saveExaminationEntity.setExaminationDetail(JsonUtils.serialize(examinationDetailEntities));
                bizExaminationService.save(saveExaminationEntity);
            } else {
                BizExaminationEntity updateExaminationEntity = bizExaminationEntities.get(0);
                updateExaminationEntity.setTitle(generateExaminationEntity.getTitle());
                updateExaminationEntity.setQuestionType(questionType);
                updateExaminationEntity.setTotalScore(generateExaminationEntity.getTotalScore());
                updateExaminationEntity.setN(generateExaminationEntity.getN());
                updateExaminationEntity.setLevel(generateExaminationEntity.getLevel());
                updateExaminationEntity.setLanguage(generateExaminationEntity.getLanguage());
                updateExaminationEntity.setFileUrl(generateExaminationEntity.getFileUrl());
                updateExaminationEntity.setContent(generateExaminationEntity.getContent());
                updateExaminationEntity.setPositions(generateExaminationEntity.getPositions());
                updateExaminationEntity.setExaminationDetail(JsonUtils.serialize(examinationDetailEntities));
                bizExaminationService.update(updateExaminationEntity);
            }


        } catch (Exception e) {
            throw new BusinessException("生成题目异常");
        }
    }

    @Override
    public ExaminationEntity getExaminations(String examinationId, Long userId) {
        ExaminationEntity result = new ExaminationEntity();

        BizExaminationEntity bizExaminationEntity = new BizExaminationEntity();
        bizExaminationEntity.setExaminationId(examinationId);
        bizExaminationEntity.setMemberId(userId);
        bizExaminationEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizExaminationEntity> bizExaminationEntities = bizExaminationService.findByExample(bizExaminationEntity, null);
        if (CollectionUtils.isEmpty(bizExaminationEntities)) {
            return result;
        }

        BizExaminationEntity examinationEntity = bizExaminationEntities.get(0);
        String examinationDetail = examinationEntity.getExaminationDetail();
        if (StringUtils.isBlank(examinationDetail)) {
            return result;
        }
        List<ExaminationDetail> examinationDetailEntities = JsonUtils.deSerialize(examinationDetail, new TypeReference<List<ExaminationDetail>>() {
        }.getType());

        result.setExaminationDetails(examinationDetailEntities);
        result.setExaminationId(examinationEntity.getExaminationId());
        result.setTitle(examinationEntity.getTitle());
        result.setN(examinationEntity.getN());
        result.setLevel(examinationEntity.getLevel());
        result.setQuestionType(Arrays.stream(examinationEntity.getQuestionType().split(",")).collect(Collectors.toList()));
        result.setDate(examinationEntity.getModifiedTime());
        result.setTotalScore(examinationEntity.getTotalScore());
        result.setPositions(examinationEntity.getPositions());
        result.setFileUrl(examinationEntity.getFileUrl());
        result.setContent(examinationEntity.getContent());
        return result;
    }

    @Override
    public List<ExaminationEntity> getList(String query, Long userId) {
        List<ExaminationEntity> res = new ArrayList<>();

        ExaminationQueryCondition condition = new ExaminationQueryCondition();
        condition.setQuery(query);
        condition.setMemberId(userId);
        List<ExaminationQueryItem> examinationQueryItems = bizExaminationService.examinationQuery(condition, null);
        if (CollectionUtils.isNotEmpty(examinationQueryItems)) {
            res = examinationQueryItems.stream().map(item -> {
                ExaminationEntity examinationEntity = new ExaminationEntity();
                examinationEntity.setExaminationId(item.getExaminationId());
                examinationEntity.setTitle(item.getTitle());
                examinationEntity.setTotalScore(item.getTotalScore());
                examinationEntity.setPositions(item.getPositions());
                examinationEntity.setN(item.getN());
                examinationEntity.setLevel(item.getLevel());
                examinationEntity.setDate(item.getModifiedTime());
                return examinationEntity;
            }).collect(Collectors.toList());
        }
        return res;
    }

    @Override
    public boolean batchDelete(List<String> examinationIds, Long userId) {
        ExaminationQueryCondition condition = new ExaminationQueryCondition();
        condition.setExaminationIds(examinationIds);
        condition.setMemberId(userId);
        List<ExaminationQueryItem> examinationQueryItems = bizExaminationService.examinationQuery(condition, null);
        if (CollectionUtils.isNotEmpty(examinationQueryItems)) {
            try {
                for (ExaminationQueryItem examinationQueryItem : examinationQueryItems) {
                    bizExaminationService.deletedById(examinationQueryItem.getId());
                }
            } catch (Exception e) {
                logger.error("删除试卷失败:", e);
                return false;
            }
        }
        return true;
    }


    @Override
    public String downloadExamination(String examinationId, Long userId) {
        BizExaminationEntity bizExaminationEntity = new BizExaminationEntity();
        bizExaminationEntity.setExaminationId(examinationId);
        bizExaminationEntity.setMemberId(userId);
        bizExaminationEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizExaminationEntity> bizExaminationEntities = bizExaminationService.findByExample(bizExaminationEntity, null);
        if (CollectionUtils.isEmpty(bizExaminationEntities) || StringUtils.isBlank(bizExaminationEntities.get(0).getExaminationDetail())) {
            throw new BusinessException("无法获取试卷内容");
        }
        BizExaminationEntity examinationEntity = bizExaminationEntities.get(0);
        File file = buildExaminationFile(examinationEntity);
        try (FileInputStream fileInputStream = new FileInputStream(file)) {
            return bosConfigService.upload(fileInputStream, "docx", "");
        } catch (Exception e) {
            logger.error("------------ 生成试卷文件失败 ---------------", e);
            throw new BusinessException("生成文件失败");
        } finally {
            if (file.exists()) {
                file.delete();
            }
        }
    }

    /**
     * 生成试卷文件
     *
     * @param examinationEntity
     * @return
     */
    private File buildExaminationFile(BizExaminationEntity examinationEntity) {
        // 遍历试卷题目，写入试卷
        List<ExaminationDetail> examinationDetails = JsonUtils.deSerialize(examinationEntity.getExaminationDetail(), new TypeReference<List<ExaminationDetail>>() {
        }.getType());

        try (XWPFDocument document = new XWPFDocument()) {
            // 写入标题
            XWPFParagraph titleParagraph = document.createParagraph();
            titleParagraph.setAlignment(ParagraphAlignment.CENTER);
            titleParagraph.setVerticalAlignment(TextAlignment.CENTER);
            XWPFRun titleParagraphRun = titleParagraph.createRun();
            titleParagraphRun.setText(examinationEntity.getTitle());
            titleParagraphRun.setBold(true);
            titleParagraphRun.setFontSize(22);

            // 详情
            XWPFParagraph detailParagraph = document.createParagraph();
            detailParagraph.setAlignment(ParagraphAlignment.CENTER);
            detailParagraph.setVerticalAlignment(TextAlignment.CENTER);
            XWPFRun detailParagraphRun = detailParagraph.createRun();
            detailParagraphRun.setText("总分: " + examinationEntity.getTotalScore() + "分     难度级别：" + examinationEntity.getLevel() + "     总题数: " + examinationDetails.size());
            detailParagraphRun.addBreak();


            //问题
            for (int i = 0; i < examinationDetails.size(); i++) {
                ExaminationDetail examinationDetail = examinationDetails.get(i);

                //题目类型/分数
                XWPFParagraph questionTypeParagraph = document.createParagraph();
                questionTypeParagraph.setAlignment(ParagraphAlignment.LEFT);
                questionTypeParagraph.setVerticalAlignment(TextAlignment.AUTO);
                XWPFRun questionTypeParagraphRun = questionTypeParagraph.createRun();
                questionTypeParagraphRun.setText(i + 1 + "." + examinationDetail.getQuestionType() + "(" + examinationDetail.getScore() + "分)");

                // 问题
                XWPFParagraph questionParagraph = document.createParagraph();
                questionParagraph.setAlignment(ParagraphAlignment.LEFT);
                questionParagraph.setVerticalAlignment(TextAlignment.AUTO);
                XWPFRun questionParagraphRun = questionParagraph.createRun();
                String question = examinationDetail.getQuestion();
                questionParagraphRun.setText(question + "(    )");
                //选项
                XWPFParagraph choiceParagraph = document.createParagraph();
                choiceParagraph.setAlignment(ParagraphAlignment.LEFT);
                choiceParagraph.setVerticalAlignment(TextAlignment.AUTO);
                XWPFRun choiceParagraphRun = choiceParagraph.createRun();
                List<String> choice = examinationDetail.getChoice();
                for (int j = 0; j < choice.size(); j++) {
                    choiceParagraphRun.setText(choice.get(j), j);
                    choiceParagraphRun.addBreak();
                }
            }
            File tempFile = File.createTempFile(UUIDTool.getUUID(), ".docx");
            try (FileOutputStream out = new FileOutputStream(tempFile)) {
                document.write(out);
            }
            return tempFile;
        } catch (IOException e) {
            throw new BusinessException(e);
        }
    }

    private Message[] buildMessage(String prompt, GenerateExaminationEntity generateExaminationEntity) {
        String fileContent = StringUtils.EMPTY;
        if (StringUtils.isNoneBlank(generateExaminationEntity.getFileUrl())) {
            File file = DocumentLoad.downloadURLDocument(generateExaminationEntity.getFileUrl());
            fileContent = DocumentLoad.documentToText(file);
        }

        String content = prompt.replace("${file_content}", fileContent)
                .replace("${content}", StringUtils.isBlank(generateExaminationEntity.getContent()) && StringUtils.isBlank(fileContent) ? generateExaminationEntity.getTitle() : generateExaminationEntity.getContent())
                .replace("${number}", generateExaminationEntity.getN().toString())
                .replace("${total_score}", generateExaminationEntity.getTotalScore().toString())
                .replace("${level}", generateExaminationEntity.getLevel())
                .replace("${position}", StringUtils.isBlank(generateExaminationEntity.getPositions()) ? StringUtils.EMPTY : generateExaminationEntity.getPositions())
                .replace("${question_type}", StringUtils.join(generateExaminationEntity.getQuestionType(), ","));

        Message userMessage = new Message();
        userMessage.setRole(LLMRoleEnum.USER.getRole());
        userMessage.setContent(content);
        return new Message[]{userMessage};
    }


    private List<ExaminationDetail> outputExaminationBuffer(BufferedReader bufferedReader, SSEUtil sseUtil, String examinationId) throws IOException {
        String res = "";
        StringBuilder output = new StringBuilder();
        StringBuilder reasoningContent = new StringBuilder();
        StringBuilder examinationRecordBuilder = new StringBuilder();
        sseUtil.send("{\"examinationId\":\"" + examinationId + "\"}");
        List<ExaminationDetail> examinationDetailEntities = new ArrayList<>();
        try {
            while ((res = bufferedReader.readLine()) != null) {
                if (StringUtils.isEmpty(res)) {
                    continue;
                }
                res = StringUtils.replace(res, "data: ", StringUtils.EMPTY);
                LargeModelDemandResult result = JsonUtils.deSerialize(res, LargeModelDemandResult.class);
                if (!"0".equals(result.getCode())) {
                    logger.error("LLM Error,code:{}", result.getCode());
                    BusinessException ex = new BusinessException("exception/call.failure");
                    result.setMessage(ex.getMessage());
                    sseUtil.send(JsonUtils.serialize(result));
                    sseUtil.send("[DONE]");
                    sseUtil.complete();
                    throw ex;
                }
                if (StringUtils.isNotEmpty(result.getMessage())) {
                    output.append(result.getMessage());
                    examinationRecordBuilder.append(result.getMessage());
                }
                // 构造题目参数
                if (examinationRecordBuilder.length() > 0) {
                    int startIndex = examinationRecordBuilder.indexOf(startXML);
                    if (startIndex != -1) {
                        int contentStart = startIndex + startXML.length();
                        int endIndex = examinationRecordBuilder.indexOf(endXML, contentStart);
                        if (endIndex != -1) {
                            String subStr = examinationRecordBuilder.substring(contentStart, endIndex);
                            ExaminationDetail examinationDetail = JsonUtils.deSerialize(subStr, ExaminationDetail.class);
                            if (examinationDetail != null) {
                                sseUtil.send(JsonUtils.serialize(examinationDetail));
                                examinationDetailEntities.add(examinationDetail);
                                examinationRecordBuilder = new StringBuilder(examinationRecordBuilder.substring(endIndex));
                            }
                        }
                    }
                }
                if (StringUtils.isNotEmpty(result.getReasoningContent())) {
                    reasoningContent.append(result.getReasoningContent());
                }
            }


            // 关闭资源
            sseUtil.send("[DONE]");
            sseUtil.complete();
            return examinationDetailEntities;

        } catch (IOException e) {
            logger.error("连接断开,code:{}", e.getMessage());
            sseUtil.completeByError("连接断开");
            throw new BusinessException("连接断开");
        } finally {
            bufferedReader.close();
            sseUtil.complete();
        }
    }
}
