package com.yeejoin.amos.boot.module.cylinder.biz.job;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.yeejoin.amos.boot.module.cylinder.api.entity.CylinderQuestionInfo;
import com.yeejoin.amos.boot.module.cylinder.api.enums.QuestionTypeEnum;
import com.yeejoin.amos.boot.module.cylinder.biz.service.impl.CylinderQuestionInfoServiceImpl;
import com.yeejoin.amos.boot.module.cylinder.flc.api.dto.CylinderInfoDto;
import com.yeejoin.amos.boot.module.cylinder.flc.api.entity.CylinderInspection;
import com.yeejoin.amos.boot.module.cylinder.flc.api.mapper.CylinderInfoMapper;
import com.yeejoin.amos.boot.module.cylinder.flc.biz.service.impl.CylinderInspectionServiceImpl;
import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.scheduling.annotation.EnableScheduling;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;
import org.typroject.tyboot.core.rdbms.orm.entity.BaseEntity;

import javax.validation.constraints.NotNull;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author Administrator
 */
@Component
@EnableScheduling
public class InspectionQuestionJob {


    private CylinderInfoMapper cylinderInfoMapper;

    private CylinderInspectionServiceImpl cylinderInspectionService;

    private CylinderQuestionInfoServiceImpl questionInfoService;

    public InspectionQuestionJob(CylinderInfoMapper cylinderInfoMapper,
                                 CylinderInspectionServiceImpl cylinderInspectionService,
                                 CylinderQuestionInfoServiceImpl questionInfoService) {
        this.cylinderInfoMapper = cylinderInfoMapper;
        this.questionInfoService = questionInfoService;
        this.cylinderInspectionService = cylinderInspectionService;
    }


    /**
     * 检验超期
     */
    @SchedulerLock(name = "genOverdueQuestionJobCylinder2", lockAtMostFor = "PT1H")
    @Scheduled(cron = "${inspection.overdue.job.cron:0 0 1 * * ?}")
    @Transactional(rollbackFor = Exception.class)
    public void genOverdueQuestion() {
        List<CylinderInfoDto> cylinderList = cylinderInfoMapper.queryCylinderOfInspectionOverdue();
        List<CylinderQuestionInfo> cylinderQuestionInfos = cylinderList.stream().map(cylinderInfoDto -> {
            CylinderQuestionInfo cylinderQuestionInfo = new CylinderQuestionInfo();
            cylinderQuestionInfo.setQuestionType(QuestionTypeEnum.JYCQ.getCode());
            cylinderQuestionInfo.setQuestionTypeName(QuestionTypeEnum.JYCQ.getName());
            return fillCommonField(cylinderInfoDto, cylinderQuestionInfo);
        }).collect(Collectors.toList());
        // 已经生成的数据不再重复生成
        List<CylinderQuestionInfo> needToDbQuestionInfos = this.removeRepeatData(cylinderQuestionInfos);
        if (needToDbQuestionInfos.size() > 0) {
            questionInfoService.saveBatch(needToDbQuestionInfos);
        }
    }

    private List<CylinderQuestionInfo> removeRepeatData(List<CylinderQuestionInfo> cylinderQuestionInfos) {
        if (cylinderQuestionInfos.size() > 0) {
            Set<String> questionObjectIds = cylinderQuestionInfos.stream().map(CylinderQuestionInfo::getQuestionObjectId).collect(Collectors.toSet());
            Set<String> appIds = cylinderQuestionInfos.stream().map(CylinderQuestionInfo::getQuestionAttributionId).collect(Collectors.toSet());
            // 已经生成问题的气瓶
            List<CylinderQuestionInfo> questionInfos = questionInfoService.list(new LambdaQueryWrapper<CylinderQuestionInfo>()
                    .in(CylinderQuestionInfo::getQuestionObjectId, questionObjectIds)
                    .in(CylinderQuestionInfo::getQuestionAttributionId, appIds).eq(CylinderQuestionInfo::getQuestionType, QuestionTypeEnum.JYCQ.getCode()));
            // 去掉已经生成的气瓶问题，不在重复生成问题
            return cylinderQuestionInfos.stream().filter(c -> questionInfos.stream().noneMatch(d -> d.getQuestionObjectId().equals(c.getQuestionObjectId()) &&
                    d.getQuestionAttributionId().equals(c.getQuestionAttributionId()))).collect(Collectors.toList());
        }
        return new ArrayList<>();
    }


    /**
     * 检验不合格任务
     */
    @SchedulerLock(name = "genInspectionUnqualifiedQuestionJobCylinder2", lockAtMostFor = "PT20M")
    @Scheduled(cron = "${inspection.unqualified.job.cron:0 0/10 * * * ?}")
    @Transactional(rollbackFor = Exception.class)
    public void genInspectionUnqualifiedQuestion() {
        List<CylinderInfoDto> cylinderList = cylinderInfoMapper.queryCylinderOfUnqualifiedQuestion();
        List<CylinderQuestionInfo> cylinderQuestionInfos = cylinderList.stream().map(cylinderInfoDto -> {
            CylinderQuestionInfo cylinderQuestionInfo = new CylinderQuestionInfo();
            cylinderQuestionInfo.setQuestionType(QuestionTypeEnum.JYBHG.getCode());
            cylinderQuestionInfo.setQuestionTypeName(QuestionTypeEnum.JYBHG.getName());
            return fillCommonField(cylinderInfoDto, cylinderQuestionInfo);
        }).collect(Collectors.toList());
        if (cylinderQuestionInfos.size() > 0) {
            questionInfoService.saveBatch(cylinderQuestionInfos);
            updateDealStatusAfterJobDeal(cylinderList);
        }
    }

    private void updateDealStatusAfterJobDeal(List<CylinderInfoDto> cylinderList) {
        LambdaUpdateWrapper<CylinderInspection> updateWrapper = new LambdaUpdateWrapper<>();
        cylinderList.forEach(cylinder -> {
            updateWrapper.eq(BaseEntity::getSequenceNbr, cylinder.getSequenceNbr());
            updateWrapper.set(CylinderInspection::getIsDealQuestion, true);
            cylinderInspectionService.update(updateWrapper);
        });
    }

    @NotNull
    private CylinderQuestionInfo fillCommonField(CylinderInfoDto cylinderInfoDto, CylinderQuestionInfo cylinderQuestionInfo) {
        cylinderQuestionInfo.setHappenDate(new Date());
        cylinderQuestionInfo.setRecDate(new Date());
        cylinderQuestionInfo.setRegionCode(cylinderInfoDto.getRegionCode());
        cylinderQuestionInfo.setQuestionObjectId(cylinderInfoDto.getSequenceCode());
        cylinderQuestionInfo.setQuestionObjectName(cylinderInfoDto.getFactoryNum());
        cylinderQuestionInfo.setQuestionAttributionId(cylinderInfoDto.getAppId());
        cylinderQuestionInfo.setQuestionAttributionName(cylinderInfoDto.getUnitName());
        return cylinderQuestionInfo;
    }
}
