package cn.com.poc.message.service.impl;

import cn.com.gsst.dify_client.DifyChatClient;
import cn.com.gsst.dify_client.DifyClientFactory;
import cn.com.gsst.dify_client.enums.ResponseMode;
import cn.com.gsst.dify_client.exception.DifyApiException;
import cn.com.gsst.dify_client.model.chat.ChatMessage;
import cn.com.gsst.dify_client.model.chat.ChatMessageResponse;
import cn.com.poc.ai_data_audit.constants.DataAuditEnum;
import cn.com.poc.ai_data_audit.dto.AuditResultDto;
import cn.com.poc.ai_data_audit.entity.BizAiDataAuditFileEntity;
import cn.com.poc.ai_data_audit.entity.BizAiDataAuditTaskEntity;
import cn.com.poc.ai_data_audit.query.AiDataAuditRuleQueryCondition;
import cn.com.poc.ai_data_audit.query.AiDataAuditRuleQueryItem;
import cn.com.poc.ai_data_audit.service.BizAiDataAuditFileService;
import cn.com.poc.ai_data_audit.service.BizAiDataAuditRuleService;
import cn.com.poc.ai_data_audit.service.BizAiDataAuditTaskService;
import cn.com.poc.common.constant.CommonConstant;
import cn.com.poc.common.service.RedisService;
import cn.com.poc.common.utils.DocumentLoad;
import cn.com.poc.common.utils.JsonUtils;
import cn.com.poc.common.utils.StringUtils;
import cn.com.poc.message.C2fResult;
import cn.com.poc.message.entity.AirportTaskCreateMessage;
import cn.com.poc.message.entity.AirportPDFPaperMessage;
import cn.com.poc.message.entity.OCRMessage;
import cn.com.poc.message.service.AirportConsumerService;
import cn.com.poc.message.service.AirportProducerService;
import cn.com.poc.message.service.OcrProducerService;
import cn.com.poc.message.topic.AirportTopic;
import cn.com.poc.ocr.entity.BizFileOcrCacheEntity;
import cn.com.poc.ocr.service.BizFileOcrCacheService;
import cn.com.yict.framemax.core.exception.BusinessException;
import cn.com.yict.framemax.tumbleweed.client.annotation.Consumer;
import com.alibaba.fastjson.JSONObject;
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.*;
import java.util.stream.Collectors;

/**
 * @author alex.yao
 * @date 2025/10/30
 */
@Service
public class AirportConsumerServiceImpl implements AirportConsumerService {

    private String DIFY_BASE_URL = "https://dify.gsstcloud.com/v1";

    private ThreadPoolExecutor executor = new ThreadPoolExecutor(10, 20, 10L,
            TimeUnit.SECONDS,
            new ArrayBlockingQueue<>(20),
            new ThreadFactoryBuilder().setNameFormat("pdf-paper-%d").build(),
            new ThreadPoolExecutor.DiscardPolicy());

    @Resource
    private BizFileOcrCacheService bizFileOcrCacheService;

    @Resource
    private BizAiDataAuditFileService bizAiDataAuditFileService;

    @Resource
    private BizAiDataAuditRuleService bizAiDataAuditRuleService;

    @Resource
    private BizAiDataAuditTaskService bizAiDataAuditTaskService;

    @Resource
    private OcrProducerService ocrProducerService;

    @Resource
    private RedisService redisService;

    @Resource
    private AirportProducerService airportProducerService;

    @Override
    @Consumer(topic = AirportTopic.AIRPORT_CREATE_TOPIC)
    public void createTask(AirportTaskCreateMessage message) throws Exception {
        // 配置Redis AI_DATA_AUDIT_TASK , 表示消息队列已经获取到任务 [用于定时任务(AiDataAuditScheduler)判断该任务下的 OCR任务是否已经全部完成]
        redisService.set("AI_DATA_AUDIT_TASK:" + message.getTaskId(), "Get");

        BizAiDataAuditFileEntity bizAiDataAuditFileEntity = new BizAiDataAuditFileEntity();
        bizAiDataAuditFileEntity.setTaskId(message.getTaskId());
        bizAiDataAuditFileEntity.setIsDeleted(CommonConstant.IsDeleted.N);
        List<BizAiDataAuditFileEntity> aiDataAuditFileEntities = bizAiDataAuditFileService.findByExample(bizAiDataAuditFileEntity, null);

        // 判断OCR是否完成
        // 1. 判断OCR缓存表是否有数据
        // 2. 若缓存表有数据，则判断是否完成
        // 3. 若缓存表无数据，则发送OCR任务
        // 4. 最后判断是否全部任务已完成
        boolean isAllComplete = true;
        for (BizAiDataAuditFileEntity aiDataAuditFileEntity : aiDataAuditFileEntities) {
            String md5 = aiDataAuditFileEntity.getMd5();

            BizFileOcrCacheEntity bizFileOcrCacheEntity = new BizFileOcrCacheEntity();
            bizFileOcrCacheEntity.setMd5(md5);
            bizFileOcrCacheEntity.setIsDeleted(CommonConstant.IsDeleted.N);
            List<BizFileOcrCacheEntity> bizFileOcrCacheEntities = bizFileOcrCacheService.findByExample(bizFileOcrCacheEntity, null);

            if (CollectionUtils.isEmpty(bizFileOcrCacheEntities)) {
                BizFileOcrCacheEntity saveFileOcrCacheEntity = new BizFileOcrCacheEntity();
                saveFileOcrCacheEntity.setMd5(md5);
                saveFileOcrCacheEntity.setParseStatus("create");
                saveFileOcrCacheEntity.setFileUrl(aiDataAuditFileEntity.getUploadFileUrl());
                BizFileOcrCacheEntity save = bizFileOcrCacheService.save(saveFileOcrCacheEntity);

                //发送OCR 任务
                OCRMessage ocrMessage = new OCRMessage();
                ocrMessage.setId(save.getId());
                ocrMessage.setMd5(md5);
                ocrMessage.setFileURL(aiDataAuditFileEntity.getUploadFileUrl());
                ocrProducerService.OCR(ocrMessage);
                continue;
            }

            BizFileOcrCacheEntity fileOcrCacheEntity = bizFileOcrCacheEntities.get(0);
            if (!fileOcrCacheEntity.getParseStatus().equals("complete")) {
                isAllComplete = false;
            }

            if (fileOcrCacheEntity.getParseStatus().equals("fail")) {
                //若是失败，重新发送OCR任务
                OCRMessage ocrMessage = new OCRMessage();
                ocrMessage.setId(fileOcrCacheEntity.getId());
                ocrMessage.setMd5(md5);
                ocrMessage.setFileURL(aiDataAuditFileEntity.getUploadFileUrl());
                ocrProducerService.OCR(ocrMessage);
                isAllComplete = false;
            }
        }

        if (isAllComplete) { //OCR 已完成
            redisService.set("AI_DATA_AUDIT_TASK:" + message.getTaskId(), "Finish");
            //执行规则判断任务
            AirportPDFPaperMessage pdfPaperMessage = new AirportPDFPaperMessage();
            pdfPaperMessage.setTaskId(message.getTaskId());
            airportProducerService.pdfPaper(pdfPaperMessage);
        }

    }


    @Override
    @Consumer(topic = AirportTopic.AIRPORT_PDF_PAPER_TOPIC)
    public void pdfPaper(AirportPDFPaperMessage message) throws Exception {
        BizAiDataAuditTaskEntity bizAiDataAuditTaskEntity = null;
        try {
            List<AuditResultDto> results = new CopyOnWriteArrayList<>();
            Long taskId = message.getTaskId();

            //根据任务id查找任务
            bizAiDataAuditTaskEntity = bizAiDataAuditTaskService.getWithToken(taskId);
            if (bizAiDataAuditTaskEntity == null) {
                throw new BusinessException("任务不存在");
            }

            //查找任务下的所有文件
            BizAiDataAuditFileEntity bizAiDataAuditFileEntity = new BizAiDataAuditFileEntity();
            bizAiDataAuditFileEntity.setTaskId(taskId);
            List<BizAiDataAuditFileEntity> bizAiDataAuditFileEntities = bizAiDataAuditFileService.findByExample(bizAiDataAuditFileEntity, null);

            if (CollectionUtils.isEmpty(bizAiDataAuditFileEntities)) {
                throw new BusinessException("找不到该任务下的文件");
            }


            //获取所有的规则
            AiDataAuditRuleQueryCondition aiDataAuditRuleQueryCondition = new AiDataAuditRuleQueryCondition();
            aiDataAuditRuleQueryCondition.setIsDeleted("N");
            List<AiDataAuditRuleQueryItem> aiDataAuditRuleQueryItems = bizAiDataAuditRuleService.aiDataAuditRuleQueryItemList(aiDataAuditRuleQueryCondition, null);
            CountDownLatch countDownLatch = new CountDownLatch(aiDataAuditRuleQueryItems.size());

            for (AiDataAuditRuleQueryItem aiDataAuditRuleQueryItem : aiDataAuditRuleQueryItems) {
                String ruleType = aiDataAuditRuleQueryItem.getDataAuditRuleType();
                if (ruleType.equals("c2c")) {
                    c2c(bizAiDataAuditFileEntities, aiDataAuditRuleQueryItem, results, countDownLatch);
                } else if (ruleType.equals("c2f")) {
                    c2f(bizAiDataAuditFileEntities, aiDataAuditRuleQueryItem, results, countDownLatch);
                } else if (ruleType.equals("f2f")) {
                    f2f(bizAiDataAuditFileEntities, aiDataAuditRuleQueryItem, results, countDownLatch);
                } else {
                    countDownLatch.countDown();
                }
            }
            countDownLatch.await(10 * 60, TimeUnit.SECONDS);

            //更新结果和任务状态
            bizAiDataAuditTaskEntity.setAuditResult(JSONObject.toJSONString(results));
            bizAiDataAuditTaskEntity.setStatus("end");
            bizAiDataAuditTaskService.update(bizAiDataAuditTaskEntity);
        } catch (Exception e) {
            redisService.set("ERROR_MSG_AI_DATA_AUDIT_TASK:" + message.getTaskId(), e.getMessage(), 60 * 60 * 24 * 7);
            if (bizAiDataAuditTaskEntity != null) {
                bizAiDataAuditTaskEntity = new BizAiDataAuditTaskEntity();
                bizAiDataAuditTaskEntity.setDataAuditTaskId(message.getTaskId());
                bizAiDataAuditTaskEntity.setStatus("fail");
                bizAiDataAuditTaskService.update(bizAiDataAuditTaskEntity);
            }
        }
    }

    // 字段对字段
    private void c2c(List<BizAiDataAuditFileEntity> fileList, AiDataAuditRuleQueryItem aiDataAuditRuleQueryItem, List<AuditResultDto> results, CountDownLatch countDownLatch) {
        class C2CResult {
            private boolean need_judge;

            private boolean comply;

            private String risk_analysis;

            private String risk_description;

            private String modification_suggestions;

            public boolean getNeed_judge() {
                return need_judge;
            }

            public void setNeed_judge(boolean need_judge) {
                this.need_judge = need_judge;
            }

            public boolean getComply() {
                return comply;
            }

            public void setComply(boolean comply) {
                this.comply = comply;
            }

            public String getRisk_analysis() {
                return risk_analysis;
            }

            public void setRisk_analysis(String risk_analysis) {
                this.risk_analysis = risk_analysis;
            }

            public String getRisk_description() {
                return risk_description;
            }

            public void setRisk_description(String risk_description) {
                this.risk_description = risk_description;
            }

            public String getModification_suggestions() {
                return modification_suggestions;
            }

            public void setModification_suggestions(String modification_suggestions) {
                this.modification_suggestions = modification_suggestions;
            }
        }

        executor.submit(() -> {
            try {
                Map<String, List<BizAiDataAuditFileEntity>> groupedByTemplateCode = fileList.stream()
                        .collect(Collectors.groupingBy(BizAiDataAuditFileEntity::getOrginalTemplateCode));

                String ruleDesc = aiDataAuditRuleQueryItem.getRuleDesc();// 规则描述
                String firstFileCode = aiDataAuditRuleQueryItem.getFirstFile();// 文件1
                String firstField = aiDataAuditRuleQueryItem.getFirstField();// 字段1
                String secondFileCode = aiDataAuditRuleQueryItem.getSecondFile();// 文件2
                String secondField = aiDataAuditRuleQueryItem.getSecondField();// 字段2

                // 找到文件 并下载对应的md 或 json 文件
                String firstFileContent = getFileContentByOCRCache(groupedByTemplateCode, firstFileCode);
                String secondFileContent = getFileContentByOCRCache(groupedByTemplateCode, secondFileCode);

                if (StringUtils.isBlank(firstFileContent) || StringUtils.isBlank(secondFileContent)) {
                    return;
                }

                // 执行工作流
                Map<String, Object> inputs = new LinkedHashMap<>();
                inputs.put("rule", ruleDesc);
                inputs.put("doc1", firstFileContent);
                inputs.put("doc2", secondFileContent);
                inputs.put("filed_1", firstField);
                inputs.put("filed_2", secondField);
                // 创建聊天客户端
                DifyChatClient chatClient = DifyClientFactory.createChatClient(DIFY_BASE_URL, "app-AVURkM0NaoE5gBt2wEo9cN8E");
                // 创建聊天消息
                ChatMessage message = ChatMessage.builder()
                        .query("run")
                        .user("0")
                        .inputs(inputs)
                        .conversationId(StringUtils.EMPTY)
                        .responseMode(ResponseMode.BLOCKING)
                        .build();

                // 发送消息并获取响应
                ChatMessageResponse response = chatClient.sendChatMessage(message);
                String result = response.getAnswer();
                C2CResult c2cResult = JSONObject.parseObject(result, C2CResult.class);

                if (c2cResult == null) {
                    throw new BusinessException("c2c result is null");
                }

                if (!c2cResult.getNeed_judge() || c2cResult.getComply()) {
                    return;
                }

                AuditResultDto auditResultDto = new AuditResultDto();
                auditResultDto.setRiskLevel(aiDataAuditRuleQueryItem.getRiskLevel());
                auditResultDto.setRiskTitle(aiDataAuditRuleQueryItem.getTitle());
                auditResultDto.setRiskAnalysis(c2cResult.getRisk_analysis());//分析
                auditResultDto.setRiskDescription(c2cResult.getRisk_description());//风险描述
                auditResultDto.setModificationSuggestions(c2cResult.getModification_suggestions());//建议

                results.add(auditResultDto);
            } catch (Exception e) {
                throw new BusinessException(e);
            } finally {
                countDownLatch.countDown();
            }
        });
    }

    private String getFileContentByOCRCache(Map<String, List<BizAiDataAuditFileEntity>> groupedByTemplateCode
            , String fileCode) {
        String fileContent = StringUtils.EMPTY;
        if (!groupedByTemplateCode.containsKey(fileCode) || groupedByTemplateCode.get(fileCode).size() == 0) {
            return fileContent;
        }
        BizAiDataAuditFileEntity auditFileEntity = groupedByTemplateCode.get(fileCode).get(0);
        BizFileOcrCacheEntity fileOcrCacheEntity = bizFileOcrCacheService.findByMd5(auditFileEntity.getMd5());
        String mdFileURL = fileOcrCacheEntity.getMdFileUrl();
        String jsonFileURL = fileOcrCacheEntity.getJsonFileUrl();
        if (StringUtils.isNotBlank(jsonFileURL)) {
            File file = DocumentLoad.downloadURLDocument(StringUtils.isBlank(jsonFileURL) ? mdFileURL : jsonFileURL);
            fileContent = DocumentLoad.documentToText(file);
        }
        return fileContent;
    }

    // 字段对文件
    private void c2f(List<BizAiDataAuditFileEntity> fileList, AiDataAuditRuleQueryItem aiDataAuditRuleQueryItem, List<AuditResultDto> results, CountDownLatch countDownLatch) throws Exception {
        executor.submit(() -> {
            try {
                String ruleDesc = aiDataAuditRuleQueryItem.getRuleDesc();// 规则描述
                String firstFile = aiDataAuditRuleQueryItem.getFirstFile();// 文件1
                String firstField = aiDataAuditRuleQueryItem.getFirstField();// 字段1
                String secondFile = aiDataAuditRuleQueryItem.getSecondFile();// 文件2
                String secondField = aiDataAuditRuleQueryItem.getSecondField();// 字段2

                String firstFileContent = StringUtils.EMPTY;
//                String secondFileContent = StringUtils.EMPTY;

                //需要拿到第一个的字段
                Map<String, List<BizAiDataAuditFileEntity>> groupedByTemplateCode = fileList.stream()
                        .collect(Collectors.groupingBy(BizAiDataAuditFileEntity::getOrginalTemplateCode));

                // 找到文件 并下载对应的md 或 json 文件
                BizAiDataAuditFileEntity firstAuditFileEntity = groupedByTemplateCode.get(firstFile).get(0);
                BizFileOcrCacheEntity bizFileOcrCacheEntity = new BizFileOcrCacheEntity();
                bizFileOcrCacheEntity.setMd5(firstAuditFileEntity.getMd5());
                List<BizFileOcrCacheEntity> firstocrCacheEntities = bizFileOcrCacheService.findByExample(bizFileOcrCacheEntity, null);
                BizFileOcrCacheEntity firstFileOcrCacheEntity = firstocrCacheEntities.get(0);
                String firstMdFileUrl = firstFileOcrCacheEntity.getMdFileUrl();
                String firstJsonFileUrl = firstFileOcrCacheEntity.getJsonFileUrl();
                if (StringUtils.isNotBlank(firstJsonFileUrl)) {
                    File file = DocumentLoad.downloadURLDocument(StringUtils.isBlank(firstJsonFileUrl) ? firstMdFileUrl : firstJsonFileUrl);
                    firstFileContent = DocumentLoad.documentToText(file);
                }


                //需要判断是否有第二个文件
                //执行c2f判断

                //如果成立就需要走文件是否为空的判断
                // 执行工作流
                Map<String, Object> inputs = new LinkedHashMap<>();
                inputs.put("rule", ruleDesc);
                inputs.put("doc1", firstFileContent);
                inputs.put("filed_1", firstField);
                // 创建聊天客户端
                DifyChatClient chatClient = DifyClientFactory.createChatClient("https://dify.gsstcloud.com/v1", "app-z52CVvKwnoYPcjP3hpxlwKRC");
                // 创建聊天消息
                ChatMessage message = ChatMessage.builder()
                        .query("run")
                        .user("0")
                        .inputs(inputs)
                        .conversationId(StringUtils.EMPTY)
                        .responseMode(ResponseMode.BLOCKING)
                        .build();

                // 发送消息并获取响应
                ChatMessageResponse response = chatClient.sendChatMessage(message);
                String result = response.getAnswer();

                C2fResult c2fResult = JSONObject.parseObject(result, C2fResult.class);

                if (c2fResult != null && "Y".equals(c2fResult.getFlag()) && CollectionUtils.isEmpty(groupedByTemplateCode.get(secondFile))) {
                    AuditResultDto auditResultDto = new AuditResultDto();
                    auditResultDto.setRiskLevel(aiDataAuditRuleQueryItem.getRiskLevel());
                    auditResultDto.setRiskTitle(aiDataAuditRuleQueryItem.getTitle());

                    String templateName = DataAuditEnum.getTemplateNameByCode(secondFile);
                    auditResultDto.setRiskAnalysis(templateName + " file has not been submitted.");
                    auditResultDto.setRiskDescription(c2fResult.getDesc());
                    auditResultDto.setModificationSuggestions("Please submit " + templateName + " file");
                    results.add(auditResultDto);
                }
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                countDownLatch.countDown();
            }
        });
    }


    // 文件对文件
    private void f2f(List<BizAiDataAuditFileEntity> fileList, AiDataAuditRuleQueryItem aiDataAuditRuleQueryItem, List<AuditResultDto> results, CountDownLatch countDownLatch) {

        executor.submit(() -> {
            try {
                String ruleDesc = aiDataAuditRuleQueryItem.getRuleDesc();// 规则描述
                String firstFile = aiDataAuditRuleQueryItem.getFirstFile();// 文件1
                String secondFile = aiDataAuditRuleQueryItem.getSecondFile();// 文件2

                Map<String, List<BizAiDataAuditFileEntity>> groupedByTemplateCode = fileList.stream()
                        .collect(Collectors.groupingBy(BizAiDataAuditFileEntity::getOrginalTemplateCode));

                List<BizAiDataAuditFileEntity> firstFileFileEntities = groupedByTemplateCode.get(firstFile);
                List<BizAiDataAuditFileEntity> secondFileFileEntities = groupedByTemplateCode.get(secondFile);

                if (CollectionUtils.isNotEmpty(firstFileFileEntities)) {
                    if (CollectionUtils.isEmpty(secondFileFileEntities)) {
                        AuditResultDto auditResultDto = new AuditResultDto();
                        auditResultDto.setRiskLevel(aiDataAuditRuleQueryItem.getRiskLevel());
                        auditResultDto.setRiskTitle(aiDataAuditRuleQueryItem.getTitle());

                        String templateName = DataAuditEnum.getTemplateNameByCode(secondFile);
                        auditResultDto.setRiskAnalysis(templateName + " file has not been submitted.");
                        auditResultDto.setRiskDescription(ruleDesc);
                        auditResultDto.setModificationSuggestions("Please submit " + templateName + " file");
                        results.add(auditResultDto);
                    }
                }
//                else {
//                    AuditResultDto auditResultDto = new AuditResultDto();
//                    auditResultDto.setRiskLevel(aiDataAuditRuleQueryItem.getRiskLevel());
//                    auditResultDto.setRiskTitle(aiDataAuditRuleQueryItem.getTitle());
//                    auditResultDto.setRiskAnalysis("Work Permit Application Details or Work Permit Extension Details has not been submitted");
//                    auditResultDto.setRiskDescription("file has not been submitted");
//                    auditResultDto.setModificationSuggestions("Please submit Work Permit Application Details or Work Permit Extension Details file");
//                    results.add(auditResultDto);
//                }
                countDownLatch.countDown();
            } catch (Exception e) {
                throw new RuntimeException(e);
            } finally {
                countDownLatch.countDown();
            }
        });
    }
}
