package com.testor.module.safeCheck.service.impl;

import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.testor.biz.sys.org.model.domain.SysOrg;
import com.testor.common.util.DateUtil;
import com.testor.module.sys.service.TOrgService;
import com.testor.module.safeCheck.dao.TSafeHazardCheckPlanDao;
import com.testor.module.safeCheck.model.domain.TSafeHazardCheckObject;
import com.testor.module.safeCheck.model.domain.TSafeHazardCheckPeople;
import com.testor.module.safeCheck.model.domain.TSafeHazardCheckPlan;
import com.testor.module.safeCheck.model.dto.TSafeHazardCheckPlanDTO;
import com.testor.module.safeCheck.model.dto.TSafeHazardCheckPlanParam;
// import com.testor.module.safeCheck.model.vo.SafeHazardCheckObjectGroupVO;
import com.testor.module.safeCheck.model.vo.SafeHazardCheckObjectVO;
import com.testor.module.safeCheck.model.vo.SafeHazardCheckPeopleVO;
import com.testor.module.safeCheck.model.vo.SafeHazardCheckPlanDetailVO;
import com.testor.module.safeCheck.model.vo.TSafeHazardCheckPlanVO;
import com.testor.module.safeCheck.service.TSafeHazardCheckObjectService;
import com.testor.module.safeCheck.service.TSafeHazardCheckPeopleService;
import com.testor.module.safeCheck.service.TSafeHazardCheckPlanService;
import com.tongtech.tfw.backend.common.biz.constants.BizConstants;
import com.tongtech.tfw.backend.common.biz.models.BaseResponse;
import com.tongtech.tfw.backend.common.biz.models.BaseResponseList;
import com.tongtech.tfw.backend.common.constants.enumeration.BaseStatusEnum;
import com.tongtech.tfw.backend.common.context.ContextUtils;
import com.tongtech.tfw.backend.common.models.sys.UserInfo;
import com.tongtech.tfw.backend.core.helper.StringHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import org.springframework.stereotype.Service;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.time.LocalDateTime;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 巡检计划Service业务层处理
 *
 * @author testor-framework
 * @date 2022-08-04 11:07:52
 */
@Service
public class TSafeHazardCheckPlanServiceImpl extends SuperServiceImpl<TSafeHazardCheckPlanDao, TSafeHazardCheckPlan> implements TSafeHazardCheckPlanService {
    @Autowired(required = false)
    private TSafeHazardCheckPlanDao tSafeHazardCheckPlanDao;

    @Resource
    private TSafeHazardCheckObjectService checkObjectService;

    @Resource
    private TSafeHazardCheckPeopleService checkPeopleService;

    @Autowired
    private TOrgService tOrgService;

    @Transactional
    public BaseResponse editCheckPlan(TSafeHazardCheckPlanDTO checkPlanDTO) {
        BaseResponse baseResponse = new BaseResponse<>();

        UserInfo curUser = ContextUtils.getLoginUser();
        if (StrUtil.isBlank(curUser.getOrgId())) {
            baseResponse.setCode(BaseStatusEnum.UN_DATA.code());
            baseResponse.setMsg("用户信息错误");
            return baseResponse;
        }

        String userId = curUser.getUserId();

        List<TSafeHazardCheckObject> checkObjectList = checkPlanDTO.getCheckObjectList();
        List<TSafeHazardCheckPeople> checkPeopleList = checkPlanDTO.getCheckPeopleList();
        if (checkObjectList == null || checkObjectList.size() == 0 ||
                checkPeopleList == null || checkPeopleList.size() == 0) {
            baseResponse.setCode(BaseStatusEnum.UN_DATA.code());
            baseResponse.setMsg("参数缺失");
            return baseResponse;
        }

        TSafeHazardCheckPlan checkPlan = BeanHelper.beanToBean(checkPlanDTO, TSafeHazardCheckPlan.class);
        String dataId = checkPlan.getId();
        Integer doResult;
        if (StrUtil.isBlank(dataId)) { // 新增
            checkPlan.setCreateBy(userId);
            doResult = tSafeHazardCheckPlanDao.insert(checkPlan);
        } else {

            Integer planStatus = calPlanStatus(DateUtil.dateToLocalDateTime(checkPlan.getStartDate()), DateUtil.dateToLocalDateTime(checkPlan.getEndDate()), checkPlan.getAdvanceHour());
            if (planStatus == null || planStatus != 0) {
                baseResponse.setCode(BaseStatusEnum.UNKNOWN.code());
                baseResponse.setMsg("该排查计划不允许进行编辑");
                return baseResponse;
            }
            checkPlan.setUpdateBy(userId);
            doResult = tSafeHazardCheckPlanDao.updateById(checkPlan);
        }

        if (doResult == null || doResult != 1) {
            baseResponse.setCode(BaseStatusEnum.UNKNOWN.code());
            baseResponse.setMsg("排查计划编辑失败");
            return baseResponse;
        }

        // 更新 排查对象 、 排查人员
        boolean objResult = checkObjectService.editBatchByPlan(checkPlan.getId(), checkObjectList);
        boolean peopleResult = checkPeopleService.editBatchByPlan(checkPlan.getId(), checkPlan.getAdvanceHour(), DateUtil.dateToLocalDateTime(checkPlan.getEndDate()), checkPeopleList);
        if (!objResult || !peopleResult) {
            throw new RuntimeException("排查对象/排查人员 更新失败");
        }

        baseResponse.setData(checkPlan);
        return baseResponse;
    }

    /**
     * @return 0-未开始且未派发任务；1-未开始 已派发任务； 2-进行中； 3-已完成;
     */
    public Integer calPlanStatus(LocalDateTime startDate, LocalDateTime endDate, long advanceHour) {

        LocalDateTime nowDate = LocalDateTime.now();
        LocalDateTime offsetTime = LocalDateTimeUtil.offset(nowDate, advanceHour, ChronoUnit.HOURS);
        long offsetDiffVal = LocalDateTimeUtil.between(offsetTime, startDate, ChronoUnit.SECONDS);
        if (offsetDiffVal > 0) {
            return 0;
        }

        long startDiffVal = LocalDateTimeUtil.between(nowDate, startDate, ChronoUnit.SECONDS);
        if (startDiffVal >= 0 && offsetDiffVal < 0) {
            return 1;
        }

        long endDiffVal = LocalDateTimeUtil.between(nowDate, endDate, ChronoUnit.SECONDS);
        if (startDiffVal <= 0 && endDiffVal >= 0) {
            return 2;
        }

        if (endDiffVal < 0) {
            return 3;
        }

        return null;
    }

    @Override
    public BaseResponseList<TSafeHazardCheckPlanVO> listByPage(TSafeHazardCheckPlanParam param) {

//        if (StrUtil.isBlank(param.getOrgId())) {
//            UserInfo curUser = ContextUtils.getLoginUser();
//            String curUserOrgId = curUser.getOrgId();
//            param.setOrgId(curUserOrgId);
//        }

        BaseResponseList<TSafeHazardCheckPlanVO> baseResponseList = new BaseResponseList<>();

        Long page =
                StringHelper.isEmpty(param.getPage()) ? BizConstants.PAGE : Long.valueOf(param.getPage());
        Long limit =
                StringHelper.isEmpty(param.getLimit()) ? BizConstants.LIMIT : Long.valueOf(param.getLimit());
        Page<TSafeHazardCheckPlanVO> resultPage = new Page<>(page, limit);
        IPage<TSafeHazardCheckPlanVO> iPage = tSafeHazardCheckPlanDao.listPage(resultPage, param);

        List<TSafeHazardCheckPlanVO> riskSourceVOList = iPage.getRecords();
        riskSourceVOList.forEach(item -> {
            SysOrg regionalCompany = tOrgService.getRegionalCompany(item.getOrgId());
            if (regionalCompany != null) {
                item.setBusinessOrgName(regionalCompany.getOrgName());
            }
        });
        if (riskSourceVOList == null || riskSourceVOList.size() == 0) {
            baseResponseList.setData(iPage.getRecords());
            baseResponseList.setTotal(iPage.getTotal());
            return baseResponseList;
        }

        List<TSafeHazardCheckPlanVO> finalCheckPlanVOList = riskSourceVOList.stream().map(vo -> {
            String objectNames = checkObjectService.findObjectNamesByPlan(vo.getId());
            vo.setCheckObjectNames(objectNames);
            Integer planStatus = calPlanStatus(vo.getStartDate(), vo.getEndDate(), vo.getAdvanceHour());
            //0-未开始且未派发任务；1-未开始 已派发任务； 2-进行中； 3-已完成
            vo.setPlanStatus(planStatus);
            return vo;

        }).collect(Collectors.toList());
        baseResponseList.setData(finalCheckPlanVOList);
        baseResponseList.setTotal(iPage.getTotal());
        return baseResponseList;
    }

    /**
     * 根据id获取巡检计划
     *
     * @return
     */
    @Override
    public SafeHazardCheckPlanDetailVO findById(String planId) {
        if (StrUtil.isBlank(planId)) {
            return null;
        }
        SafeHazardCheckPlanDetailVO detailVO = tSafeHazardCheckPlanDao.findById(planId);
        List<SafeHazardCheckObjectVO> objectVOList = checkObjectService.listVOByPlan(planId);
        List<SafeHazardCheckPeopleVO> peopleVOList = checkPeopleService.listVOByPlan(planId);
        detailVO.setCheckObjectList(objectVOList);
        detailVO.setCheckPeopleList(peopleVOList);
        return detailVO;
    }

    @Override
    public BaseResponse deletePlan(String planId) {
        BaseResponse baseResponse = new BaseResponse<>();
        if (StrUtil.isBlank(planId)) {
            baseResponse.setCode(BaseStatusEnum.UN_DATA.code());
            baseResponse.setMsg("参数缺失");
            return baseResponse;
        }
        TSafeHazardCheckPlan checkPlan = getById(planId);
        Integer planStatus = calPlanStatus(DateUtil.dateToLocalDateTime(checkPlan.getStartDate()), DateUtil.dateToLocalDateTime(checkPlan.getEndDate()), checkPlan.getAdvanceHour());
        if (planStatus != 0) {
            baseResponse.setCode(BaseStatusEnum.UN_DATA.code());
            baseResponse.setMsg("当前计划状态不允许删除！");
            return baseResponse;
        }

        checkPlan.setStatus(BizConstants.STATUS_DELETE);
        updateById(checkPlan);
        baseResponse.setCode(BaseStatusEnum.SUCCESS.code());
        return baseResponse;
    }

    /**
     * 根据检测对象 查询 未结束的巡检计划
     *
     * @param object : 巡检标准、对象类型-设备、对象类型-空间
     * @return
     */
    @Override
    public List<TSafeHazardCheckPlan> findByObjectInfo(TSafeHazardCheckObject object) {
        List<TSafeHazardCheckPlan> checkPlanList = null;
        checkPlanList = tSafeHazardCheckPlanDao.findByObjectInfo(object);
        return checkPlanList;
    }

}
