package org.jeecg.modules.database.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.database.constant.ExperimentReviewResultEnum;
import org.jeecg.modules.database.dto.ExperimentReviewDTO;
import org.jeecg.modules.database.entity.*;
import org.jeecg.modules.database.mapper.ExperimentReviewResultMapper;
import org.jeecg.modules.database.service.*;
import org.jeecg.modules.database.service.executor.ExecutorHolder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 试验评定结果
 * @Author: jeecg-boot
 * @Date: 2025-06-16
 * @Version: V1.0
 */
@Service
public class ExperimentReviewServiceImpl extends ServiceImpl<ExperimentReviewResultMapper, ExperimentReview>
        implements IExperimentReviewService {
    @Autowired
    private IExperimentReviewRuleService   experimentReviewRuleService;
    @Autowired
    private IExperimentReviewDetailService experimentReviewDetailService;
    @Autowired
    private ExecutorHolder                 executorHolder;
    @Autowired
    private IExperimentService             experimentService;
    @Autowired
    private IExperimentSampleInfoService   experimentSampleInfoService;

    //高估代表 0，低估代表 1,无法评定代表2，评定结果通过代表3，未通过代表 4
    @Override
    public ExperimentReview review(Experiment experiment, ExperimentSampleInfo sampleInfo, ExperimentReview experimentReview) {
        String processType = experimentReview.getProcessType();
        List<ExperimentReviewRule> ruleList = experimentReviewRuleService.getByType(processType);
        ExperimentReview result = new ExperimentReview();
        result.setExperimentId(experiment.getId());
        result.setProcessType(processType);
        result.setSampleId(sampleInfo.getId());
        for (int i = 0; i < ruleList.size(); i++) {
            ExperimentReviewRule rule = ruleList.get(i);
            String executeResult = executorHolder.execute(rule.getProcessType() + rule.getPriority(), experiment, sampleInfo,
                    experimentReview);
            if (StrUtil.isNotBlank(executeResult)) {
                ExperimentReviewDetail detail = new ExperimentReviewDetail();
                detail.setExperimentId(experiment.getId());
                detail.setSampleId(sampleInfo.getId());
                detail.setProcessType(processType);
                detail.setRuleId(rule.getId());
                detail.setPriority(rule.getPriority());
                detail.setResult(executeResult);
                experimentReviewDetailService.saveOrUpdate(detail);
            }
            if (i == 0) {
                continue;
            }

            String reviewResult = adjustResult(experiment.getId(), sampleInfo.getId(), result);
            if (StringUtils.isNotBlank(reviewResult)) {
                result.setResult(reviewResult);
                return result;
            }
        }
        String reviewResult = adjustResult(experiment.getId(), sampleInfo.getId(), result);
        if (StringUtils.isNotBlank(reviewResult)) {
            result.setResult(reviewResult);
        } else {
            result.setResult(ExperimentReviewResultEnum.UNKNOWN);
        }
        return result;
    }

    @Override
    public ExperimentReview getBySampleId(String experimentId, String sampleId) {
        return getOne(new LambdaQueryWrapper<ExperimentReview>().eq(ExperimentReview::getExperimentId, experimentId)
                .eq(ExperimentReview::getSampleId, sampleId), false);
    }

    @Override
    public List<ExperimentReviewDTO> getByExperimentId(String experimentId) {
        //Experiment experiment = experimentService.getById(experimentId);
        List<ExperimentSampleInfo> sampleInfoList = experimentSampleInfoService.getByExperimentId(experimentId);
        List<ExperimentReviewDTO> result = new ArrayList<>();
        sampleInfoList.forEach(sampleInfo -> {
            ExperimentReviewDTO dto = new ExperimentReviewDTO();
            dto.setExperimentId(experimentId);
            dto.setSampleId(sampleInfo.getId());
            dto.setSampleName(sampleInfo.getSampleName());
            ExperimentReview review = getBySampleId(experimentId, sampleInfo.getId());
            if (Objects.isNull(review)) {
                dto.setProcessType("");
                dto.setReviewResult("未评定");
            } else {
                dto.setProcessType(review.getProcessType());
                dto.setReviewResult(review.getResult());
            }
            result.add(dto);
        });
        return result;
    }

    private String adjustResult(String experimentId, String sampleId, ExperimentReview result) {
        List<ExperimentReviewDetail> detailList = experimentReviewDetailService.getBySample(experimentId, sampleId);
        List<ExperimentReviewRule> matchedRuleList = detailList.stream().map(v -> experimentReviewRuleService.getById(v.getRuleId()))
                .filter(v -> v != null).collect(Collectors.toList());
        result.setMatchedRuleList(matchedRuleList);
        ExperimentReviewDetail first = CollUtil.getFirst(detailList);
        ExperimentReviewDetail last = CollUtil.getLast(detailList);
        if (detailList.size() > 1 && !StrUtil.equals(first.getResult(), last.getResult())) {
            return ExperimentReviewResultEnum.UNKNOWN;
        }
        if (detailList.size() == 1 && first.getResult().equals(ExperimentReviewResultEnum.FINAL_PASS)) {
            return ExperimentReviewResultEnum.FINAL_PASS;
        }
        if (detailList.size() == 1 && first.getResult().equals(ExperimentReviewResultEnum.NOT_PASS)) {
            return ExperimentReviewResultEnum.NOT_PASS;
        }
        if (detailList.size() == 2 && StrUtil.equals(first.getResult(), last.getResult())) {
            return first.getResult();
        }
        if (detailList.size() == 2 && !StrUtil.equals(first.getResult(), last.getResult())) {
            return ExperimentReviewResultEnum.UNKNOWN;
        }
        if (detailList.size() > 2) {
            return ExperimentReviewResultEnum.UNKNOWN;
        }
        return null;
    }
}
