package com.rongwei.sfcommon.sys.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.rongwe.scentity.domian.*;
import com.rongwei.commonservice.serial.service.SysSerialNumberService;
import com.rongwei.rwadmincommon.system.vo.SysUserVo;
import com.rongwei.rwcommon.base.BaseDo;
import com.rongwei.rwcommon.base.R;
import com.rongwei.rwcommon.base.exception.CustomException;
import com.rongwei.rwcommon.utils.SecurityUtil;
import com.rongwei.rwcommon.utils.StringUtils;
import com.rongwei.safecommon.utils.JSCommonUtils;
import com.rongwei.sfcommon.sys.service.HazardInvestigationService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

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

/**
 * HazardInvestigationServiceImpl class
 *
 * @author XH
 * @date 2024/08/09
 */
@Service
public class HazardInvestigationServiceImpl implements HazardInvestigationService {

    private final Logger log = LoggerFactory.getLogger(this.getClass().getName());
    @Autowired
    private ApsHazardInvestigationTemplateServiceImpl apsHazardInvestigationTemplateService;
    @Autowired
    private ApsHazardInvestigationTemplateZibiaoServiceImpl apsHazardInvestigationTemplateZibiaoService;
    @Autowired
    private SysSerialNumberService autoSysSerialNumberService;
    @Autowired
    private AspRiskUnitServiceImpl aspRiskUnitService;
    @Autowired
    private ApsDetailsHazardInvestigationTasksServiceImpl apsDetailsHazardInvestigationTasksServiceImpl;
    @Autowired
    private ApsDetailsHazardInvestigationTasksJcxzibiaoServiceImpl apsDetailsHazardInvestigationTasksJcxzibiaoService;
    @Autowired
    private AspMajorHazardSourcesServiceImpl aspMajorHazardSourcesService;

    public static final Map<String, List<Function<AspMajorHazardSourcesDo, String>>>getCheckUserInfoFunctionMap=new HashMap<String, List<Function<AspMajorHazardSourcesDo, String>>>(){{
        put("1",new ArrayList<Function<AspMajorHazardSourcesDo, String>>(){{
            add(AspMajorHazardSourcesDo::getMainresponsible);
            add(AspMajorHazardSourcesDo::getMainresponsibleid);
        }});
        put("2",new ArrayList<Function<AspMajorHazardSourcesDo, String>>(){{
            add(AspMajorHazardSourcesDo::getTechnicalresponsible);
            add(AspMajorHazardSourcesDo::getTechnicalresponsibleid);
        }});
        put("3",new ArrayList<Function<AspMajorHazardSourcesDo, String>>(){{
            add(AspMajorHazardSourcesDo::getOperationresponsible);
            add(AspMajorHazardSourcesDo::getOperationresponsibleid);
        }});
    }};

    @Override
    public R createTask(String id) {
        log.info("开始根据模板：{}创建隐患排查任务", id);
        ApsHazardInvestigationTemplateDo tempData = apsHazardInvestigationTemplateService.getById(id);
        if (tempData == null) {
            log.error("无法获取隐患模板信息");
            throw new CustomException("该模板已删除");
        }
        // 模板检查项
        List<ApsHazardInvestigationTemplateZibiaoDo> templateZibiaoDos = apsHazardInvestigationTemplateZibiaoService.list(new LambdaQueryWrapper<ApsHazardInvestigationTemplateZibiaoDo>()
                .eq(ApsHazardInvestigationTemplateZibiaoDo::getMubanid, id)
                .eq(BaseDo::getDeleted, "0"));
        if (templateZibiaoDos.isEmpty()) {
            log.debug("模板检查项为空");
            return R.ok("模板检查项为空");
        }
        // 生成隐患排查任务
        assembleTask(tempData, templateZibiaoDos);

        return R.ok();
    }

    /**
     * 生成隐患任务信息
     *
     * @param tempData
     */
    public void assembleTask(ApsHazardInvestigationTemplateDo tempData,
                             List<ApsHazardInvestigationTemplateZibiaoDo> templateZibiaoDos) {

        SysUserVo currentUser = JSCommonUtils.getCurrentUser();

        if (StringUtils.isBlank(tempData.getHiddendangerid())) {
            log.error("风险分析单元为空");
            throw new RuntimeException("模板对应需检查的风险分析单元为空");
        }

        if (templateZibiaoDos.isEmpty()) {
            log.error("当前模板:{}不存在检查项", tempData.getTemplatename());
            throw new CustomException("当前模板不存在检查项");
        }
        // 风险分析单元
        List<String> riskPointIds = Arrays.asList(tempData.getHiddendangerid().split(","));
        List<AspRiskUnitDo> aspRiskUnitDos = (List<AspRiskUnitDo>) aspRiskUnitService.listByIds(riskPointIds);
        if (aspRiskUnitDos.isEmpty()) {
            log.error("无法根据id:{}找到对应的风险点", riskPointIds);
            throw new CustomException("无法获取对应的风险点");
        }
        // 重大危险源ID
        List<String> collect = aspRiskUnitDos.stream().map(AspRiskUnitDo::getMajorhazardid).collect(Collectors.toList());
        List<AspMajorHazardSourcesDo> aspMajorHazardSourcesDos = aspMajorHazardSourcesService.getBaseMapper().selectBatchIds(collect);

        List<ApsDetailsHazardInvestigationTasksDo> taskSaveList = new ArrayList<>();
        List<ApsDetailsHazardInvestigationTasksJcxzibiaoDo> taskDetailSaveList = new ArrayList<>();
        // 按照风险点 分开生成隐患排查任务
        ApsDetailsHazardInvestigationTasksDo apsDetailsHazardInvestigationTasksDo;
        // 获取当前时间的0点0分0秒
        Calendar startOfDay = Calendar.getInstance();
        startOfDay.setTime(new Date());
        startOfDay.set(Calendar.HOUR_OF_DAY, 0);
        startOfDay.set(Calendar.MINUTE, 0);
        startOfDay.set(Calendar.SECOND, 1);
        Date startTime = startOfDay.getTime();
        // 获取当前时间的23点59分59秒
        startOfDay.set(Calendar.HOUR_OF_DAY, 23);
        startOfDay.set(Calendar.MINUTE, 59);
        startOfDay.set(Calendar.SECOND, 59);
        startOfDay.set(Calendar.MILLISECOND, 999);
        Date endTime = startOfDay.getTime();
        for (AspRiskUnitDo s : aspRiskUnitDos) {
            apsDetailsHazardInvestigationTasksDo = new ApsDetailsHazardInvestigationTasksDo();
            JSCommonUtils.setBaseDetail(apsDetailsHazardInvestigationTasksDo, currentUser);
            apsDetailsHazardInvestigationTasksDo.setId(SecurityUtil.getUUID());
            apsDetailsHazardInvestigationTasksDo.setRiskunit(tempData.getHiddendangerid());
            apsDetailsHazardInvestigationTasksDo.setRiskanalysisobjectcode(tempData.getHiddendanger());
            apsDetailsHazardInvestigationTasksDo.setTempcode(tempData.getTemplatenumber());
            apsDetailsHazardInvestigationTasksDo.setTempname(tempData.getTemplatename());
            apsDetailsHazardInvestigationTasksDo.setState("0");
            apsDetailsHazardInvestigationTasksDo.setNumber(
                    JSCommonUtils.streamCodeGeneration("aps_details_hazard_investigation_tasks_NUMBER",
                            "YH@{date:yyyyMMdd}@{serialNumber:#000000}", "date:yyyyMM",
                            ""));
            String checkUserInfo = getCheckUserInfo(s, aspMajorHazardSourcesDos, tempData);
            apsDetailsHazardInvestigationTasksDo.setIdentifyperple(checkUserInfo.split("-;-")[0]);
            apsDetailsHazardInvestigationTasksDo.setIdentifyperpleid(checkUserInfo.split("-;-")[1]);
            apsDetailsHazardInvestigationTasksDo.setPlannedstarttime(startTime);
            apsDetailsHazardInvestigationTasksDo.setTasktype(tempData.getChecktype());
            apsDetailsHazardInvestigationTasksDo.setPlannedendtime(endTime);
            apsDetailsHazardInvestigationTasksDo.setTenantid(tempData.getTenantid());
            taskSaveList.add(apsDetailsHazardInvestigationTasksDo);
            taskDetailSaveList.addAll(assembleTaskDetails(currentUser, apsDetailsHazardInvestigationTasksDo,
                    templateZibiaoDos));
        }
        apsDetailsHazardInvestigationTasksServiceImpl.saveBatch(taskSaveList);
        apsDetailsHazardInvestigationTasksJcxzibiaoService.saveBatch(taskDetailSaveList);
    }

    /**
     * 生成隐患任务详情
     *
     * @return
     */
    public List<ApsDetailsHazardInvestigationTasksJcxzibiaoDo> assembleTaskDetails(SysUserVo currentUser,
                                                                                   ApsDetailsHazardInvestigationTasksDo apsDetailsHazardInvestigationTasksDo,
                                                                                   List<ApsHazardInvestigationTemplateZibiaoDo> checkItemList) {
        ApsDetailsHazardInvestigationTasksJcxzibiaoDo apsHazardInvestigationTemplateZibiaoDo;
        List<ApsDetailsHazardInvestigationTasksJcxzibiaoDo> subSaveList = new ArrayList<>();
        for (ApsHazardInvestigationTemplateZibiaoDo s : checkItemList) {
            apsHazardInvestigationTemplateZibiaoDo = new ApsDetailsHazardInvestigationTasksJcxzibiaoDo();
            apsHazardInvestigationTemplateZibiaoDo.setId(SecurityUtil.getUUID());
            apsHazardInvestigationTemplateZibiaoDo.setTaskid(apsDetailsHazardInvestigationTasksDo.getId());
            JSCommonUtils.setBaseDetail(apsHazardInvestigationTemplateZibiaoDo, currentUser);
            apsHazardInvestigationTemplateZibiaoDo.setControlmeasurenumber(s.getControlmeasurenumber());
            apsHazardInvestigationTemplateZibiaoDo.setInspectioncycle(s.getInspectioncycle());
            apsHazardInvestigationTemplateZibiaoDo.setInspectioncycleunit(s.getInspectioncycleunit());
            apsHazardInvestigationTemplateZibiaoDo.setTasktype(s.getTasktype());
            apsHazardInvestigationTemplateZibiaoDo.setWorkingdaytype(s.getWorkingdaytype());
            apsHazardInvestigationTemplateZibiaoDo.setCorrespondingitemsforwarrantytasks(s.getCorrespondingitemsforwarrantytasks());
            apsHazardInvestigationTemplateZibiaoDo.setHiddendangerinvestigationcontent(s.getHiddendangerinvestigationcontent());
            apsHazardInvestigationTemplateZibiaoDo.setRiskevent(s.getRiskevent());
            apsHazardInvestigationTemplateZibiaoDo.setRiskunit(s.getRiskunit());
            apsHazardInvestigationTemplateZibiaoDo.setControlmethod(s.getControlmethod());
            apsHazardInvestigationTemplateZibiaoDo.setClassificationofcontrolmeasures1(s.getClassificationofcontrolmeasures1());
            apsHazardInvestigationTemplateZibiaoDo.setClassificationofcontrolmeasures2(s.getClassificationofcontrolmeasures2());
            apsHazardInvestigationTemplateZibiaoDo.setDescriptionofcontrolmeasures(s.getDescriptionofcontrolmeasures());
            apsHazardInvestigationTemplateZibiaoDo.setClassificationofcontrolmeasures3(s.getClassificationofcontrolmeasures3());
            apsHazardInvestigationTemplateZibiaoDo.setTenantid(apsDetailsHazardInvestigationTasksDo.getTenantid());
            subSaveList.add(apsHazardInvestigationTemplateZibiaoDo);
        }
        return subSaveList;
    }

    /**
     * 获取隐患排查任务的排查人
     *
     * @param aspRiskUnitDo
     * @param aspMajorHazardSourcesDos
     * @param tempData
     * @return
     */
    public String getCheckUserInfo(AspRiskUnitDo aspRiskUnitDo,
                                   List<AspMajorHazardSourcesDo> aspMajorHazardSourcesDos,
                                   ApsHazardInvestigationTemplateDo tempData) {
        // 不是重大危险源直接返回责任人
        if (!"1".equals(aspRiskUnitDo.getMajorhazard()) || "0".equals(tempData.getChecktype())) {
            return aspRiskUnitDo.getDutyofficername() + "-;-" + aspRiskUnitDo.getDutyofficerid();
        }
        AspMajorHazardSourcesDo hazardSources = aspMajorHazardSourcesDos.stream().filter(data -> data.getId().equals(aspRiskUnitDo.getMajorhazardid())).findFirst()
                .orElse(null);
        JSCommonUtils.parameterCheck(()->hazardSources==null,"无法获取到重大危险源","无法获取到重大危险源");
        List<Function<AspMajorHazardSourcesDo, String>> functions = getCheckUserInfoFunctionMap.get(tempData.getChecktype());
        return functions.get(0).apply(hazardSources) + "-;-" + functions.get(1).apply(hazardSources);
    }

    /**
     * 校验模板中的检查项是否需要生成任务信息
     */
    public int verifyBeforeGeneratingTasks(ApsHazardInvestigationTemplateZibiaoDo investigationTemplateZibiaoDo) {
        // 检查项的创建时间
        Date createdate = investigationTemplateZibiaoDo.getCreatedate();
        // 巡检周期
        Integer inspectioncycle = investigationTemplateZibiaoDo.getInspectioncycle();
        // 周期单位
        String inspectioncycleunit = investigationTemplateZibiaoDo.getInspectioncycleunit();
        int generationFrequency = 0;
        if (inspectioncycle == null || inspectioncycle == 0) {
            log.error("巡检周期为空");
            throw new CustomException("巡检周期为空");
        }
        Calendar instance = Calendar.getInstance();
        switch (inspectioncycleunit) {
            case "0": // 小时  每几小时巡检一次
                generationFrequency = 24 / inspectioncycle;
                break;
            case "1": //天  每几天巡检一次
                generationFrequency = inspectioncycle;

                break;
            case "2": // 月
                generationFrequency = inspectioncycle;

                break;
            case "3": // 年


                break;
            default:
                log.debug("当前检测周期异常");
                throw new CustomException("检查周期为空");
        }
        return generationFrequency;
    }

}
