package com.zd.chemical.service.impl;

import java.math.BigDecimal;
import java.util.*;
import java.util.concurrent.atomic.LongAdder;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.function.Predicate;
import java.util.stream.Collectors;

import com.alibaba.nacos.shaded.org.checkerframework.checker.nullness.Opt;
import com.zd.chemical.domain.ActApplytaskNode;
import com.zd.chemical.domain.ActHxpapply;
import com.zd.chemical.domain.ActHxpapplyDetail;
import com.zd.chemical.domain.vo.ActApplytaskVo;
import com.zd.chemical.domain.vo.ActHxpapplyInfoVo;
import com.zd.chemical.mapper.ActApplytaskNodeMapper;
import com.zd.chemical.mapper.ActHxpapplyDetailMapper;
import com.zd.chemical.mapper.ActHxpapplyMapper;
import com.zd.common.core.exception.ServiceException;
import com.zd.common.core.utils.DateUtils;
import com.zd.common.core.utils.SecurityUtils;
import com.zd.common.core.utils.StringUtils;
import com.zd.common.security.utils.SaveUtil;

import com.zd.system.api.laboratory.RemoteLaboratoryService;
import com.zd.system.api.laboratory.domain.LabMessageContent;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.zd.chemical.mapper.ActApplytaskMapper;
import com.zd.chemical.domain.ActApplytask;
import com.zd.chemical.service.IActApplytaskService;

/**
 * 化学品申购任务Service业务层处理
 *
 * @author zd
 * @date 2022-08-17
 */
@Service
public class ActApplytaskServiceImpl implements IActApplytaskService
{
    @Autowired
    private ActApplytaskMapper actApplytaskMapper;

    @Autowired
    private ActApplytaskNodeMapper actApplytaskNodeMapper;

    @Autowired
    private ActHxpapplyMapper actHxpapplyMapper;

    @Autowired
    private ActHxpapplyDetailMapper actHxpapplyDetailMapper;

    @Autowired
    private RemoteLaboratoryService remoteLaboratoryService;

    /**
     * 查询化学品申购任务
     *
     * @param id 化学品申购任务主键
     * @return 化学品申购任务
     */
    @Override
    public ActApplytask selectActApplytaskById(Long id)
    {
        return actApplytaskMapper.selectActApplytaskById(id);
    }

    /**
     * 查询化学品申购任务列表
     *
     * @param actApplytask 化学品申购任务
     * @return 化学品申购任务
     */
    @Override
    public List<ActApplytask> selectActApplytaskList(ActApplytask actApplytask)
    {
        return actApplytaskMapper.selectActApplytaskList(actApplytask);
    }

    @Override
    public List<ActApplytask> getListByIds(List<Long> ids){
        if (ids.isEmpty()){
            new ArrayList <>();
        }
        return actApplytaskMapper.getListByIds(ids);
    }

    /**
     * 新增化学品申购任务
     *
     * @param actApplytask 化学品申购任务
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int insertActApplytask(ActApplytask actApplytask)
    {
        //设置其他公共字段
        SaveUtil.setCommonAttr(actApplytask);
        return actApplytaskMapper.insertActApplytask(actApplytask);
    }

    /**
     * 修改化学品申购任务
     *
     * @param actApplytask 化学品申购任务
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int updateActApplytask(ActApplytask actApplytask)
    {
        return actApplytaskMapper.updateActApplytask(actApplytask);
    }

    /**
     * 批量删除化学品申购任务
     *
     * @param ids 需要删除的化学品申购任务主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteActApplytaskByIds(Long[] ids)
    {
        return actApplytaskMapper.deleteActApplytaskByIds(ids);
    }

    /**
     * 删除化学品申购任务信息
     *
     * @param id 化学品申购任务主键
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int deleteActApplytaskById(Long id)
    {
        return actApplytaskMapper.deleteActApplytaskById(id);
    }


    /**
     * 工作流节点审批
     *
     * @param actApplytaskVo 化学品申购任务
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int approvalTask(ActApplytaskVo actApplytaskVo)
    {
        //根据申请单的id，查询对应的工作流
        ActApplytask actApplytask = new ActApplytask();
        actApplytask.setTaskId(actApplytaskVo.getTaskId());
        List <ActApplytask> actApplytasks = actApplytaskMapper.selectActApplytaskList(actApplytask);
        if(actApplytasks.size()>1){
            throw new ServiceException("申请单对应的工作流task是多个，请联系管理员！！");
        }
        if(actApplytasks.size()==0){
            throw new ServiceException("申请单无工作流task，请提交申请单！！");
        }
        ActApplytask applytask = actApplytasks.get(0);
        ActApplytaskNode actApplytaskNode = new ActApplytaskNode();
        actApplytaskNode.setApplytaskId(applytask.getId());
        actApplytaskNode.setNodeStatus(0);
        List<ActApplytaskNode> taskNodeList = actApplytaskNodeMapper.selectActApplytaskNodeList(actApplytaskNode);
        //查询申请表的信息
        ActHxpapplyInfoVo actHxpapplyInfoVo = actHxpapplyMapper.selectActHxpapplyById(actApplytaskVo.getTaskId());
        Map<String,Long> jumpApply = new HashMap<>();
        jumpApply.put("jumpApply",1L);
        Predicate<ActApplytaskNode> pre = x->Arrays.asList(x.getApplyUserIds().split(",")).stream().filter(y->Long.parseLong(y)==actHxpapplyInfoVo.getUserId()).count()>0;
        //这里把下一步的步数给当前步数
        applytask.setNowStep(-1L);
        applytask.setNextStep(-1L);
        LongAdder longAdder = new LongAdder();
        Optional.ofNullable(taskNodeList).orElseGet(Collections::emptyList)
                .stream()
                .forEach(a->{
                    longAdder.add(1);
                    if(longAdder.sum()==1){
                        a.setNodeStatus(1);
                        a.setApplyUserid(SecurityUtils.getUserId());
                        actApplytaskNodeMapper.updateActApplytaskNode(a);
                    }else{
                        // 这里需要验证审批人是不是申请人，如果是，需要跳过
                        if(pre.test(a)&&jumpApply.get("jumpApply")==1){
                            jumpApply.put("jumpApply",1L);
                            a.setNodeStatus(1);
                            a.setApplyUserid(actHxpapplyInfoVo.getUserId());
                            actApplytaskNodeMapper.updateActApplytaskNode(a);
                        }else{
                            jumpApply.put("jumpApply",2L);
                        }
                    }
                });
        // 调用回填步数的方法
        int flag = proStep(applytask,actHxpapplyInfoVo.getUserId());
        selectionChemical(actApplytaskVo);
        return flag;
    }

    // 这里做了执行task回填步数
    private int proStep(ActApplytask actApplytask,Long userId){
        ActApplytaskNode actApplytaskNode = new ActApplytaskNode();
        actApplytaskNode.setNodeStatus(0);
        actApplytaskNode.setApplytaskId(actApplytask.getId());
        List <ActApplytaskNode> actApplytaskNodes = actApplytaskNodeMapper.selectActApplytaskNodeList(actApplytaskNode);
        for(int i=0;i<actApplytaskNodes.size();i++){
            if(i==0){
                actApplytask.setNowStep(actApplytaskNodes.get(i).getId());
            }
            if(i==1){
                actApplytask.setNextStep(actApplytaskNodes.get(i).getId());
            }
        }
        if(actApplytaskNodes.size()==0){
            actApplytask.setOverTime(new Date());
            actApplytask.setApprovalStatus(1);
            //发送审批通过的消息
            sendMess(userId+"","你的采购申请审批已通过，请尽快存放入库。");
        }
        return actApplytaskMapper.updateActApplytask(actApplytask);
    }

    private void selectionChemical(ActApplytaskVo actApplytaskVo){
        ActHxpapplyDetail actHxpapplyDetail = new ActHxpapplyDetail();
        actHxpapplyDetail.setHxpapplyId(actApplytaskVo.getTaskId());
        List <ActHxpapplyDetail> actHxpapplyDetails = actHxpapplyDetailMapper.selectActHxpapplyDetailList(actHxpapplyDetail);

//        Map<String, String> collect = new HashMap <>();
        Map<Long, BigDecimal> collect = actApplytaskVo.getActHxpapplyDetailList().stream()
                .collect(Collectors.toMap(ActHxpapplyDetail::getId,ActHxpapplyDetail::getRemainingStorage));
//                .forEach(a->{
//                    collect.put(a.getChemicalId()+"@"+a.getCabinetId(),a.getChemicalId()+"@"+a.getCabinetId());
//                });
        Consumer <List <ActHxpapplyDetail>> comparator = x->x.stream().forEach(p->{
            Predicate<Map <Long, BigDecimal>> pre = pt -> StringUtils.isNotNull(pt.get(p.getId()));
            if(pre.test(collect)){
                p.setTickStatus(1);
                p.setRemainingStorage(collect.get(p.getId()));
                actHxpapplyDetailMapper.updateActHxpapplyDetail(p);
            }else{
                p.setTickStatus(2);
                actHxpapplyDetailMapper.updateActHxpapplyDetail(p);
            }
        });
        comparator.accept(actHxpapplyDetails);
    }

    @Override
    public int approvalRefuse(ActApplytask actApplytask) {
        //根据申请单的id，查询对应的工作流
        List <ActApplytask> actApplytasks = actApplytaskMapper.selectActApplytaskList(actApplytask);
        if(actApplytasks.size()>1){
            throw new ServiceException("申请单对应的工作流task是多个，请联系管理员！！");
        }
        if(actApplytasks.size()==0){
            throw new ServiceException("申请单无工作流task，请提交申请单！！");
        }
        ActApplytask applytask = actApplytasks.get(0);
        ActApplytaskNode actApplytaskNode = new ActApplytaskNode();
        actApplytaskNode.setApplytaskId(applytask.getId());
        actApplytaskNode.setNodeStatus(0);
        List<ActApplytaskNode> taskNodeList = actApplytaskNodeMapper.selectActApplytaskNodeList(actApplytaskNode);
        //这里把下一步变成-1，审批拒绝后，没有下一步
        applytask.setNextStep(-1L);
        LongAdder longAdder = new LongAdder();
        Optional.ofNullable(taskNodeList).orElseGet(Collections::emptyList)
                .stream()
                .forEach(a->{
                    longAdder.add(1);
                    if(longAdder.sum()==1){
                        a.setNodeStatus(2);
                        a.setApplyUserid(SecurityUtils.getUserId());
                        a.setNodeContent(actApplytask.getRefuseContent());
                        actApplytaskNodeMapper.updateActApplytaskNode(a);
                    }
                });
        // 这里修改主流程的审批状态变为拒绝
        applytask.setApprovalStatus(2);
        applytask.setOverTime(new Date());
        //查询审批单的创建人
        ActHxpapplyInfoVo actHxpapplyInfoVo = actHxpapplyMapper.selectActHxpapplyById(actApplytask.getTaskId());
        //发送审批拒绝的消息
        sendMess(actHxpapplyInfoVo.getUserId()+"","你的采购申请审批未通过，可登录系统查看详情。");
        int flag = actApplytaskMapper.updateActApplytask(applytask);
        return flag;
    }


    private void sendMess(String userId,String messContent){
        LabMessageContent labMessageContent = new LabMessageContent();
        labMessageContent.setSendRange(3);
        labMessageContent.setMessClass(1);
        labMessageContent.setContent(messContent);
        labMessageContent.setUserIds(userId);
        labMessageContent.setUserId(-2L);
        labMessageContent.setCreateTime(new Date());
        labMessageContent.setCreateBy("系统");
        remoteLaboratoryService.publishMess(labMessageContent);
    }


    @Override
    public int approvalRevoke(ActApplytask actApplytask) {
        //根据申请单的id，查询对应的工作流
        List <ActApplytask> actApplytasks = actApplytaskMapper.selectActApplytaskList(actApplytask);
        if(actApplytasks.size()>1){
            throw new ServiceException("申请单对应的工作流task是多个，请联系管理员！！");
        }
        if(actApplytasks.size()==0){
            throw new ServiceException("申请单无工作流task，请提交申请单！！");
        }
        //这里把申请订单变为以撤销
        ActHxpapply actHxpapply = new ActHxpapply();
        actHxpapply.setId(actApplytask.getTaskId());
        actHxpapply.setApplyStatus(3);
        actHxpapplyMapper.updateActHxpapply(actHxpapply);
        ActApplytask applytask = actApplytasks.get(0);
        //撤销这里需要把当前步数和下一步全部置成-1
        applytask.setNowStep(-1L);
        applytask.setNextStep(-1L);

        // 这里修改主流程的审批状态变为撤销
        applytask.setApprovalStatus(3);
        applytask.setOverTime(new Date());
        int flag = actApplytaskMapper.updateActApplytask(applytask);
        return flag;
    }
}
