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

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.jeecg.modules.database.constant.ExperimentReportStatus;
import org.jeecg.modules.database.constant.ExperimentStatus;
import org.jeecg.modules.database.entity.*;
import org.jeecg.modules.database.mapper.ExperimentMapper;
import org.jeecg.modules.database.service.*;
import org.jeecg.modules.system.entity.SysUser;
import org.jeecg.modules.system.service.ISysUserService;
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: 2024-08-30
 * @Version: V1.0
 */
@Service
public class ExperimentServiceImpl extends ServiceImpl<ExperimentMapper, Experiment> implements IExperimentService {
    @Autowired
    private ISysUserService                      userService;
    @Autowired
    private IExperimentUserService               experimentUserService;
    @Autowired
    private IExperimentSampleInfoService         experimentSampleInfoService;
    @Autowired
    private IExperimentDeviationConditionService experimentDeviationConditionService;
    @Autowired
    private IExperimentDeviationEquipmentService experimentDeviationEquipmentService;
    @Autowired
    private IExperimentIrradiationBoardService   experimentIrradiationBoardService;

    @Autowired
    private IExperimentSequenceService experimentSequenceService;
    @Autowired
    private IExperimentReportService   experimentReportService;
    @Autowired
    private IExperimentRatingService   experimentRatingService;

    @Autowired
    private IExperimentFileService             experimentFileService;
    @Autowired
    private IExperimentAnnealProcessService    experimentAnnealProcessService;
    @Autowired
    private IExperimentRadiationProcessService experimentRadiationProcessService;
    @Autowired
    private IExperimentTestProcessService      experimentTestProcessService;
    @Autowired
    IComponentSearchService componentSearchService;

    @Override
    public List<Experiment> list(Wrapper<Experiment> queryWrapper) {
        List<Experiment> list = super.list(queryWrapper);
        list.forEach(this::fetchExperimentDetail);
        return list;
    }

    @Override
    public void fetchExperimentDetail(Experiment experiment) {
        if (StringUtils.isNotBlank(experiment.getSupervisor())) {
            SysUser user = userService.getById(experiment.getSupervisor());
            if (Objects.nonNull(user)) {
                experiment.setSupervisorName(user.getRealname());
            }
        }
        List<ExperimentUser> userList = experimentUserService.getByExperimentId(experiment.getId());
        if (CollUtil.isNotEmpty(userList)) {
            userList.forEach(experimentUser -> {
                SysUser sysUser = userService.getById(experimentUser.getUserId());
                if (Objects.nonNull(sysUser)) {
                    experimentUser.setUserName(sysUser.getRealname());
                }
            });
            experiment.setExperimentUserList(userList);
            experiment.setExperimentUser(userList.stream().map(ExperimentUser::getUserId).collect(Collectors.joining(",")));
        } else {
            experiment.setExperimentUserList(new ArrayList<>());
        }

        List<ExperimentSampleInfo> sampleInfoList = experimentSampleInfoService.getByExperimentId(experiment.getId());
        if (CollUtil.isNotEmpty(sampleInfoList)) {
            experiment.setSampleInfoList(sampleInfoList);
        } else {
            experiment.setSampleInfoList(new ArrayList<>());
        }

        List<ExperimentDeviationCondition> deviationConditionList = experimentDeviationConditionService.getByExperimentId(
                experiment.getId());
        if (CollUtil.isNotEmpty(deviationConditionList)) {
            experiment.setDeviationConditionList(deviationConditionList);
        } else {
            experiment.setDeviationConditionList(new ArrayList<>());
        }

        List<ExperimentDeviationEquipment> deviationEquipmentList = experimentDeviationEquipmentService.getByExperimentId(
                experiment.getId());
        if (CollUtil.isNotEmpty(deviationEquipmentList)) {
            experiment.setDeviationEquipmentList(deviationEquipmentList);
        } else {
            experiment.setDeviationEquipmentList(new ArrayList<>());
        }

        List<ExperimentIrradiationBoard> irradiationBoardList = experimentIrradiationBoardService.getByExperimentId(experiment.getId());
        if (CollUtil.isNotEmpty(irradiationBoardList)) {
            experiment.setIrradiationBoardList(irradiationBoardList);
        } else {
            experiment.setIrradiationBoardList(new ArrayList<>());
        }

        List<ExperimentFile> experimentFileList = experimentFileService.getByExperimentId(experiment.getId());
        if (CollUtil.isNotEmpty(experimentFileList)) {
            experiment.setFileList(experimentFileList);
        } else {
            experiment.setFileList(new ArrayList<>());
        }
        List<ExperimentReport> reportList = experimentReportService.getByExperimentId(experiment.getId());
        if (CollUtil.isNotEmpty(reportList)) {
            experiment.setExperimentReportList(reportList);
            //给试验报告审核页面显示报告状态
            List<ExperimentReport> unFinishedReportList = reportList.stream().filter(v -> !v.getStatus().equals(ExperimentReportStatus.PASSED)).collect(Collectors.toList());
            if (CollUtil.isNotEmpty(unFinishedReportList)) {
                experiment.setReportStatus(unFinishedReportList.get(0).getStatus());
            }else {
                experiment.setReportStatus(ExperimentReportStatus.PASSED);
            }
        } else {
            experiment.setExperimentReportList(new ArrayList<>());
        }
        List<ExperimentRating> ratingList = experimentRatingService.getByExperimentId(experiment.getId());
        if (CollUtil.isNotEmpty(ratingList)) {
            ratingList.forEach(this::fetchExperimentRateDetail);
            experiment.setExperimentRatingList(ratingList);
        } else {
            experiment.setExperimentRatingList(new ArrayList<>());
        }
        //List<ExperimentAnnealProcess> experimentAnnealProcessList = experimentAnnealProcessService.getByExperimentId(experiment.getId());
        //List<ExperimentRadiationProcess> radiationProcessList = experimentRadiationProcessService.getByExperimentId(experiment.getId());
        //List<ExperimentTestProcess> experimentTestProcesses = experimentTestProcessService.getByExperimentId(experiment.getId());
        //if (CollUtil.isNotEmpty(experimentAnnealProcessList)) {
        //    experiment.setExperimentAnnealProcessList(experimentAnnealProcessList);
        //}
        //if (CollUtil.isNotEmpty(radiationProcessList)) {
        //    experiment.setExperimentRadiationProcessList(radiationProcessList);
        //}
        //if (CollUtil.isNotEmpty(experimentTestProcesses)) {
        //    experiment.setExperimentTestProcessList(experimentTestProcesses);
        //}
    }

    @Override
    public Experiment copy(Experiment oldExperiment) {
        Experiment experiment = new Experiment();
        BeanUtil.copyProperties(oldExperiment, experiment);
        experiment.setId(null);
        experiment.setExperimentNo(experimentSequenceService.next());
        experiment.setCopyCount(0);
        experiment.setIndexNo(getLastIndex() + 1);
        experiment.setStatus(ExperimentStatus.PRE_TEST);
        experiment.setStartDate(null);
        experiment.setEndDate(null);
        experiment.setCreateTime(new Date());
        save(experiment);
        List<ExperimentSampleInfo> sampleInfoList = oldExperiment.getSampleInfoList();
        if (CollUtil.isNotEmpty(sampleInfoList)) {
            sampleInfoList.forEach(sampleInfo -> {
                ExperimentSampleInfo target = new ExperimentSampleInfo();
                BeanUtil.copyProperties(sampleInfo, target);
                target.setId(null);
                target.setExperimentId(experiment.getId());
                experimentSampleInfoService.save(target);
            });
        }

        List<ExperimentIrradiationBoard> irradiationBoardList = oldExperiment.getIrradiationBoardList();
        if (CollUtil.isNotEmpty(irradiationBoardList)) {
            irradiationBoardList.forEach(board -> {
                ExperimentIrradiationBoard target = new ExperimentIrradiationBoard();
                BeanUtil.copyProperties(board, target);
                target.setId(null);
                target.setMeasurementValidity(null);
                target.setSourceArea(null);
                target.setSampleImage(null);
                target.setExperimentId(experiment.getId());
                experimentIrradiationBoardService.save(target);
            });
        }
        List<ExperimentDeviationEquipment> deviationEquipmentList = oldExperiment.getDeviationEquipmentList();
        if (CollUtil.isNotEmpty(deviationEquipmentList)) {
            deviationEquipmentList.forEach(board -> {
                ExperimentDeviationEquipment target = new ExperimentDeviationEquipment();
                BeanUtil.copyProperties(board, target);

                target.setId(null);
                target.setMeasurementValidity(null);
                target.setSampleImage(null);
                target.setExperimentId(experiment.getId());
                experimentDeviationEquipmentService.save(target);
            });
        }

        List<ExperimentDeviationCondition> deviationConditionList = oldExperiment.getDeviationConditionList();
        if (CollUtil.isNotEmpty(deviationConditionList)) {
            deviationConditionList.forEach(board -> {
                ExperimentDeviationCondition target = new ExperimentDeviationCondition();
                BeanUtil.copyProperties(board, target);
                target.setId(null);
                target.setExperimentId(experiment.getId());
                experimentDeviationConditionService.save(target);
            });
        }
        return experiment;

    }

    @Override
    public void changeStatus(String experimentId, String status) {
        Experiment dbData = getById(experimentId);
        switch (status) {
            case ExperimentStatus.COMPLETED:
                if (!StringUtils.equals(dbData.getStatus(), ExperimentStatus.PROGRESSING)) {
                    throw new IllegalArgumentException("试验状态不正确!");
                }
                break;
        }
        Experiment experiment = new Experiment();
        experiment.setId(experimentId);
        experiment.setStatus(status);
        updateById(experiment);
    }

    @Override
    public void saveWithDetail(Experiment experiment) {
        if (StringUtils.isBlank(experiment.getId())) {
            if (Objects.isNull(experiment.getIndexNo())) {
                Integer lastIndex = getLastIndex();
                experiment.setIndexNo(lastIndex + 1);
            }
        }
        saveOrUpdate(experiment);

        String experimentUser = experiment.getExperimentUser();
        if (StringUtils.isNotBlank(experimentUser)) {
            experimentUserService.removeByExperimentId(experiment.getId());
            for (String userId : experimentUser.split(",")) {
                ExperimentUser userDomain = new ExperimentUser();
                userDomain.setExperimentId(experiment.getId());
                userDomain.setUserId(userId);
                userDomain.setType("OPERATOR");
                experimentUserService.save(userDomain);
            }
        }
        List<ExperimentSampleInfo> sampleInfoList = experiment.getSampleInfoList();
        if (CollUtil.isNotEmpty(sampleInfoList)) {
            for (ExperimentSampleInfo sampleInfo : sampleInfoList) {
                sampleInfo.setExperimentId(experiment.getId());
                experimentSampleInfoService.saveOrUpdate(sampleInfo);
            }
        }
        List<ExperimentDeviationCondition> deviationConditionList = experiment.getDeviationConditionList();
        if (CollUtil.isNotEmpty(deviationConditionList)) {
            for (ExperimentDeviationCondition deviationCondition : deviationConditionList) {
                deviationCondition.setExperimentId(experiment.getId());
                experimentDeviationConditionService.saveOrUpdate(deviationCondition);
            }
        }
        List<ExperimentDeviationEquipment> deviationEquipmentList = experiment.getDeviationEquipmentList();
        if (CollUtil.isNotEmpty(deviationEquipmentList)) {
            for (ExperimentDeviationEquipment deviationEquipment : deviationEquipmentList) {
                deviationEquipment.setExperimentId(experiment.getId());
                experimentDeviationEquipmentService.saveOrUpdate(deviationEquipment);
            }
        }
        List<ExperimentIrradiationBoard> irradiationBoardList = experiment.getIrradiationBoardList();
        if (CollUtil.isNotEmpty(irradiationBoardList)) {
            for (ExperimentIrradiationBoard irradiationBoard : irradiationBoardList) {
                irradiationBoard.setExperimentId(experiment.getId());
                experimentIrradiationBoardService.saveOrUpdate(irradiationBoard);
            }
        }

        List<ExperimentFile> fileList = experiment.getFileList();
        if (CollUtil.isNotEmpty(fileList)) {
            for (ExperimentFile irradiationBoard : fileList) {
                irradiationBoard.setExperimentId(experiment.getId());
                experimentFileService.saveOrUpdate(irradiationBoard);
            }
        }

        //更新搜索数据
        componentSearchService.saveDataAfterSaveExperiment(experiment);


    }

    @Override
    public Integer getLastIndex() {
        LambdaQueryWrapper<Experiment> eq = new LambdaQueryWrapper<Experiment>().orderByDesc(Experiment::getIndexNo);
        Experiment one = getOne(eq, false);
        if (Objects.isNull(one)) {
            return 1;
        }

        return one.getIndexNo();
    }

    @Override
    public IPage<Experiment> join(Page<Experiment> page, Experiment experiment, SysUser loginUser) {
        if (StringUtils.contains(experiment.getStatus(), ",")) {
            experiment.setStatusList(List.of(experiment.getStatus().split(",")));
            experiment.setStatus(null);
        }
        return baseMapper.join(page, experiment, loginUser);
    }

    @Override
    public Long sumLhs() {
        return Optional.ofNullable(baseMapper.sumLhs()).orElse(0L);
    }

    @Override
    public Long sumXhy() {
        return Optional.ofNullable(baseMapper.sumXhy()).orElse(0L);
    }

    @Override
    public void fetchExperimentRateDetail(ExperimentRating experimentRating) {
        if (Objects.isNull(experimentRating)) {
            return;
        }
        Experiment experiment = this.getById(experimentRating.getExperimentId());
        if (Objects.isNull(experiment)) {
            return;
        }

        SysUser sysUser = userService.getById(experimentRating.getRateUserId());
        if (Objects.nonNull(sysUser)) {
            experimentRating.setRateUserName(sysUser.getRealname());
        }
        experimentRating.setExperimentName(experiment.getName());
        experimentRating.setExperimentNo(experiment.getExperimentNo());
    }

}
