package org.jeecg.module.custom.ocr.api.thread;

import cn.hutool.json.JSONUtil;
import com.alibaba.fastjson.JSONObject;
import com.alibaba.fastjson.serializer.SerializerFeature;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.jeecg.module.custom.ocr.api.entity.TaskCompletionRequest;
import org.jeecg.module.custom.ocr.common.entity.RequestData;
import org.jeecg.module.custom.ocr.common.entity.ResultData;
import org.jeecg.module.custom.ocr.config.ApiConfig;
import org.jeecg.module.custom.ocr.dataDao.DuplicateTaskMapper;
import org.jeecg.module.custom.ocr.dataDao.OcrPictureInfoMapper;
import org.jeecg.module.custom.ocr.dataDao.PictureCompareMapper;
import org.jeecg.module.custom.ocr.dataDao.TaskMapper;
import org.jeecg.module.custom.ocr.dataobject.*;
import org.jeecg.module.custom.ocr.service.OcrPictureInfoService;
import org.jeecg.module.custom.ocr.service.OcrPictureService;
import org.jeecg.module.custom.ocr.utils.ApiHelper;
import org.jeecg.module.custom.ocr.utils.HashCompareUtil;
import org.jeecg.module.custom.ocr.utils.NameConverterUtil;
import org.jeecg.module.custom.ocr.utils.StringUtils;
import org.jeecg.module.custom.ocr.utils.httputil.HttpClient;
import org.jeecg.module.custom.ocr.utils.httputil.HttpMethod;
import org.jeecg.module.custom.ocr.utils.httputil.HttpParamers;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import org.springframework.util.CollectionUtils;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Set;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * 重复任务运行器，负责处理未完成的 DuplicateTask
 */
@Slf4j
@Component
public class DuplicateTaskRunner {

    @Resource
    private DuplicateTaskMapper duplicateTaskMapper;

    @Resource
    private TaskMapper taskMapper;

    @Resource
    private OcrPictureService ocrPictureService;

    @Resource
    private OcrPictureInfoMapper ocrPictureInfoMapper;

    @Resource
    private PictureCompareMapper pictureCompareMapper;

    /**
     * 注入api 配置信息
     */
    @Autowired
    private ApiConfig apiConfig;

    @Value("${image.classifyBaseUrl}")
    private String classifyBaseUrl;

    @Value("${image.classifyPath}")
    private String classifyPath;

    private ScheduledExecutorService executor;
    @Autowired
    private OcrPictureInfoService ocrPictureInfoService;

    @PostConstruct
    public void init() {
        startTask();
    }

    private void startTask() {
        executor = Executors.newSingleThreadScheduledExecutor();
        executor.scheduleWithFixedDelay(this::processDuplicateTasks, 0, 10, TimeUnit.SECONDS);
    }

    private void processDuplicateTasks() {
        try {
            // 查询所有未完成的 DuplicateTask
            List<DuplicateTask> duplicateTasks = duplicateTaskMapper.getAllUnCompletedTask();
            if (duplicateTasks != null && !duplicateTasks.isEmpty()) {
                for (DuplicateTask duplicateTask : duplicateTasks) {
                    // 解析 queryConfig 为 QueryWrapper
//                    QueryWrapper<OcrPicture> queryWrapper = toQueryWrapper(duplicateTask);
//                    // 调用 OcrPictureService.listPage 查询图片
//                    List<OcrPicture> pictures = ocrPictureService.listPage(queryWrapper);

                    QueryConfig queryConfig = JSONObject.parseObject(duplicateTask.getQueryConfig(), QueryConfig.class);

                    boolean isCrossProject = "crossProject".equals(queryConfig.getValidateScope()) && !CollectionUtils.isEmpty(queryConfig.getCrossProjectLimit());
                    // 普通查重
                    List<Task> tasks = taskMapper.selectByAccountNoAndQueryConfig(duplicateTask.getAccountNo(), duplicateTask.getQueryConfig(), queryConfig.getValidateColumn());
                    checkDuplicate(duplicateTask, tasks, queryConfig, isCrossProject);

                    // 获取跨项目任务
                    if (isCrossProject) {
                        queryConfig.getCrossProjectLimit().forEach(crossProject -> crossProject.getField4().setName(NameConverterUtil.camelToSnakeCase(crossProject.getField4().getName())));
                        queryConfig.setValidateColumn(Lists.newArrayList(queryConfig.getCrossProjectLimit().get(0).getField().getName()));
                        List<Task> crossProjectTask = taskMapper.selectByQueryConfig(queryConfig);

                        // 若存在跨项目任务则进行查重
                        if (!CollectionUtils.isEmpty(crossProjectTask)) {
                            checkDuplicate(duplicateTask, crossProjectTask, queryConfig, false);
                        } else {
                            duplicateTaskMapper.updateCompletedById(duplicateTask.getId(), 1L);
                        }
                    }
                }
            }
        } catch (Exception e) {
            // 捕获异常，避免线程中断
            System.err.println("Error processing duplicate tasks: " + e.getMessage());
        } catch (Throwable t) {
            // 捕获致命错误，重新启动线程池
            System.err.println("Fatal error in task, restarting thread pool: " + t.getMessage());
            executor.shutdownNow();
            startTask(); // 创建新线程池并重启任务
        }
    }

    // 查重逻辑
    private void checkDuplicate(DuplicateTask duplicateTask, List<Task> tasks, QueryConfig queryConfig, boolean isCrossProject) {
        List<String> taskNos = Arrays.asList(duplicateTask.getTaskNos().split(","));
        List<TaskCompletionRequest.HisPictureRepeat> historyLists = Lists.newArrayList();

        // 可根据查重任务的taskNo再过滤一次task
        if (StringUtils.isNotEmpty(duplicateTask.getTaskNos())) {
            if (!CollectionUtils.isEmpty(taskNos)) {
                tasks = tasks.stream().filter(item -> taskNos.contains(String.valueOf(item.getTaskNo()))).collect(Collectors.toList());
            }
        }

        if (CollectionUtils.isEmpty(tasks)) {
            for (String taskNo : taskNos) {
                notifyTaskCompletion(taskNo, duplicateTask.getTenantNo(), duplicateTask.getAccountNo(), 0, Lists.newArrayList(), historyLists);
            }

            // 存在跨项目查重说明任务还没完成，不能更新任务状态
            duplicateTaskMapper.updateCompletedAndMaxSimilarity(duplicateTask.getId(), isCrossProject ? 0 : 1, "0");
            return;
        }

        Set<Long> pictureIds = Sets.newHashSet();
        List<Long> taskNoList = tasks.stream().map(Task::getTaskNo).distinct().collect(Collectors.toList());
        List<OcrPictureInfo> pictures = ocrPictureInfoMapper.selectByTaskNos(taskNoList);
        if (!CollectionUtils.isEmpty(pictures)) {
            pictures = pictures.stream().filter(item -> queryConfig.getValidateColumn().contains(item.getType())).collect(Collectors.toList());
        }

        // 如果图片数量大于 1，进行两两对比
        double maxSimilarity = 0.0;
        if (pictures != null && pictures.size() > 1) {
            for (int i = 0; i < pictures.size(); i++) {
                for (int j = i + 1; j < pictures.size(); j++) {
                    OcrPictureInfo first = pictures.get(i);
                    OcrPictureInfo second = pictures.get(j);

                    // 计算相似度
                    String similarityScore = HashCompareUtil.cmpHash(first.getImgHash(), second.getImgHash());
                    double similarityValue = Double.parseDouble(similarityScore);
                    if (!pictureIds.contains(first.getId()) && similarityValue > queryConfig.getConfidenceLevel()) {
                        TaskCompletionRequest.HisPictureRepeat hisPictureRepeat = new TaskCompletionRequest.HisPictureRepeat();
                        hisPictureRepeat.setHisTaskNo(first.getTaskNo());
                        hisPictureRepeat.setHisRepeatImgUrl(first.getImageUrl());
                        hisPictureRepeat.setHisRepeatImgNo(first.getId());
                        pictureIds.add(first.getId());
                        historyLists.add(hisPictureRepeat);
                    }

                    maxSimilarity = Math.max(maxSimilarity, similarityValue);

                    // 保存对比结果到 PictureCompare
                    PictureCompare compare = new PictureCompare();
                    compare.setFirstImgNo(first.getId());
                    compare.setFirstImgUrl(first.getImageUrl());
                    compare.setFirstLocalImgUrl(first.getLocalImageUrl());
                    compare.setFirstImgHash(first.getImgHash());
                    compare.setSecondImgNo(second.getId());
                    compare.setSecondImgUrl(second.getImageUrl());
                    compare.setSecondLocalImgUrl(second.getLocalImageUrl());
                    compare.setSecondImgHash(second.getImgHash());
                    compare.setSimilarityScore(similarityScore);
                    pictureCompareMapper.save(compare);
                }
            }

            // 存在跨项目查重说明任务还没完成，不能更新任务状态
            // 更新 DuplicateTask 状态和最大相似度
            duplicateTaskMapper.updateCompletedAndMaxSimilarity(duplicateTask.getId(), isCrossProject ? 0 : 1, String.valueOf(maxSimilarity));
        } else {
            // 更新 DuplicateTask 状态和最大相似度
            duplicateTaskMapper.updateCompletedAndMaxSimilarity(duplicateTask.getId(), isCrossProject ? 0 : 1, "0");
        }

        for (String taskNo : taskNos) {
            notifyTaskCompletion(taskNo, duplicateTask.getTenantNo(), duplicateTask.getAccountNo(), maxSimilarity, pictures, historyLists);
        }
    }

    private boolean notifyTaskCompletion(String taskNo, Long tenantNo, Long accountNo, double maxSimilarity, List<OcrPictureInfo> pictures, List<TaskCompletionRequest.HisPictureRepeat> historyLists) {
        try {
            // 构造任务完成数据
            TaskCompletionRequest.TaskCompletionData data = new TaskCompletionRequest.TaskCompletionData();
            data.setTenantNo(tenantNo);
            data.setAccountNo(accountNo);
            data.setTaskNo(Long.parseLong(taskNo));
            data.setApproveRemark("Task completed successfully");
            data.setPictureMatchDegree(new BigDecimal(maxSimilarity));
            data.setExtendField(null);
            data.setIsPictureRepeat(maxSimilarity > 90 ? 1 : 0); // 假设相似度 > 90% 表示重复
            data.setIsPictureRight(1); // 假设图片为真
            data.setIsBriefRepeat(0); // 假设无小结重复

            // 构造 pictureRepeatList
            List<TaskCompletionRequest.PictureRepeat> pictureRepeatList = pictures.stream()
                    .map(p -> {
                        TaskCompletionRequest.PictureRepeat repeat = new TaskCompletionRequest.PictureRepeat();
                        repeat.setImgNo(p.getId());
                        repeat.setImgUrl(p.getImageUrl());
                        repeat.setDynamicFields(new HashMap<>()); // 动态字段待补充
                        repeat.setHisPictureRepeatList(historyLists);
                        return repeat;
                    })
                    .collect(Collectors.toList());
            data.setPictureRepeatList(pictureRepeatList);

            if (CollectionUtils.isEmpty(pictureRepeatList)) {
                // 通过
                data.setApproveResult(0);
            } else {
                // 不通过
                data.setApproveResult(1);
            }

            // 其他列表暂设为空（需补充逻辑）
            data.setFalseImgList(Arrays.asList());
            data.setBriefRepeatTaskList(Arrays.asList());
            data.setApproveDetailList(Arrays.asList());

            // 序列化 data 为 JSON
            String jsonData = JSONObject.toJSONString(data, SerializerFeature.DisableCircularReferenceDetect);

            // 加密请求参数
//            RequestData requestData = ApiHelper.buildRequest(
//                    tenantNo.toString(),
//                    apiConfig.getAccessKey(),
//                    apiConfig.getAccessCode(),
//                    jsonData
//            );
            ResultData<String> stringResultData = ApiHelper.buildResponse(
                    apiConfig.getAccessCode(),
                    jsonData
            );

            RequestData requestData = new RequestData();
            requestData.setAccessKey(apiConfig.getAccessKey());
            requestData.setSignature(stringResultData.getSignature());
            requestData.setTimestamp(stringResultData.getTimestamp());
            requestData.setTenantCode(tenantNo.toString());
            requestData.setData(stringResultData.getData());

            // 组装请求
            // TODO: 需提供实际路径
            String url = apiConfig.getInterfaceDomain();
            String requestBodyJson = JSONObject.toJSONString(requestData);
            HttpParamers httpParamers = new HttpParamers(HttpMethod.POST);
            httpParamers.setJsonParamer(requestBodyJson);

            // 发起请求
            String responseJsonStr = HttpClient.doPost(
                    url,
                    httpParamers,
                    null,
                    apiConfig.getConnectTimeout(),
                    apiConfig.getReadTimeout()
            );

            // 解析响应
            ResultData<String> resultData = JSONUtil.toBean(responseJsonStr, ResultData.class);
            log.info("Task completion notification response: msg={}, status={}", resultData.getMessage(), resultData.getStatus());

            // 处理响应
            if (resultData.getStatus() == 100) {
                log.info("Task {} completion notified successfully", taskNo);
                return true;
            } else {
                log.error("Failed to notify task completion, taskNo={}, response={}", taskNo, responseJsonStr);
                return false;
            }
        } catch (Exception e) {
            log.error("Error notifying task completion, taskNo={}", taskNo, e);
            return false;
        }
    }
}
