package com.qmth.distributed.print.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.qmth.boot.api.exception.ApiException;
import com.qmth.distributed.print.business.entity.TFFlowJoin;
import com.qmth.distributed.print.business.enums.FlowJoinTypeEnum;
import com.qmth.distributed.print.business.mapper.TFFlowJoinMapper;
import com.qmth.distributed.print.business.service.TFFlowJoinService;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.TFCustomTypeEnum;
import com.qmth.teachcloud.common.util.RedisUtil;
import com.qmth.teachcloud.common.util.ResultUtil;
import com.qmth.teachcloud.common.util.ServletUtil;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * <p>
 * 考试任务和流程关联表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2021-11-22
 */
@Service
public class TFFlowJoinServiceImpl extends ServiceImpl<TFFlowJoinMapper, TFFlowJoin> implements TFFlowJoinService {

    @Resource
    RedisUtil redisUtil;

    /**
     * 保存TExamTaskFlow
     *
     * @param map
     */
    @Override
    public boolean saveOrUpdate(Map<String, Object> map) {
        SysUser sysUser = (SysUser) ServletUtil.getRequestUser();
        Long objectId = (Long) map.get(SystemConstant.OBJECT_ID);
        Long flowId = SystemConstant.convertIdToLong((String) map.get(SystemConstant.FLOW_ID));
        Long flowEntityId = SystemConstant.convertIdToLong((String) map.get(SystemConstant.FLOW_ENTITY_ID));
        TFCustomTypeEnum flowType = (TFCustomTypeEnum) map.get(SystemConstant.FLOW_TYPE);
        Optional.ofNullable(flowType).orElseThrow(() -> ExceptionResultEnum.ERROR.exception("流程类型不能为空"));
        FlowJoinTypeEnum flowJoinTypeEnum = (FlowJoinTypeEnum) map.get(SystemConstant.FLOW_JOIN_TYPE);

        boolean lock = redisUtil.lock(SystemConstant.REDIS_LOCK_EXAM_TASK_FLOW_PREFIX + flowId, SystemConstant.REDIS_LOCK_EXAM_TASK_FLOW_TIME_OUT);
        if (!lock) {
            throw ExceptionResultEnum.ERROR.exception("该流程正在审批中，请稍候再试！");
        }
        try {
            QueryWrapper<TFFlowJoin> tfFlowJoinQueryWrapper = new QueryWrapper<>();
            tfFlowJoinQueryWrapper.lambda().eq(TFFlowJoin::getObjectId, objectId);
            List<TFFlowJoin> tfFlowJoinList = this.list(tfFlowJoinQueryWrapper);
            if (Objects.isNull(tfFlowJoinList) || tfFlowJoinList.size() == 0) {
                TFFlowJoin tfFlowJoin = new TFFlowJoin(flowEntityId, objectId, flowId, 1, flowJoinTypeEnum, sysUser.getId(), flowType.getTable());
                this.save(tfFlowJoin);
            } else if (Objects.nonNull(tfFlowJoinList) && tfFlowJoinList.size() == 1) {
                if (flowJoinTypeEnum == FlowJoinTypeEnum.NEW) {//子流程
                    TFFlowJoin tfFlowJoin = tfFlowJoinList.get(0);
                    Integer level = tfFlowJoin.getLevel();
                    TFFlowJoin tfFlowJoinSub = new TFFlowJoin(flowEntityId, objectId, flowId, ++level, flowJoinTypeEnum, sysUser.getId(), flowType.getTable());
                    this.save(tfFlowJoinSub);
                } else {//否则是重启流程
                    TFFlowJoin tfFlowJoin = new TFFlowJoin(flowEntityId, objectId, flowId, 1, flowJoinTypeEnum, sysUser.getId(), flowType.getTable());
                    this.save(tfFlowJoin);
                }
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        } finally {
            redisUtil.releaseLock(SystemConstant.REDIS_LOCK_EXAM_TASK_FLOW_PREFIX + flowId);
        }
        return true;
    }

    /**
     * 根据实体id查找
     *
     * @param objectId
     * @return
     */
    @Override
    public List<TFFlowJoin> findByObjectId(Long objectId) {
        return this.list(new QueryWrapper<TFFlowJoin>().lambda().eq(TFFlowJoin::getObjectId, objectId).orderByAsc(TFFlowJoin::getCreateTime));
    }

    /**
     * 根据流程id查找
     *
     * @param flowId
     * @return
     */
    @Override
    public TFFlowJoin findByFlowId(Long flowId) {
        return this.getOne(new QueryWrapper<TFFlowJoin>().lambda().eq(TFFlowJoin::getFlowId, flowId));
    }

    /**
     * 根据自定义流程实体id查询
     *
     * @param flowEntityId
     * @return
     */
    @Override
    public List<TFFlowJoin> findByFlowEntityId(Long flowEntityId) {
        return this.list(new QueryWrapper<TFFlowJoin>().lambda().eq(TFFlowJoin::getFlowEntityId, flowEntityId));
    }
}
