package com.ruoyi.project.business.service.flow.impl;

import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Lists;
import com.ruoyi.common.utils.SecurityUtils;
import com.ruoyi.project.business.domain.flow.Flow;
import com.ruoyi.project.business.domain.flow.FlowUserPerm;
import com.ruoyi.project.business.enums.AuditFlowEnum;
import com.ruoyi.project.business.enums.AuditStatusEnum;
import com.ruoyi.project.business.mapper.flow.FlowUserPermMapper;
import com.ruoyi.project.business.service.flow.IFlowService;
import com.ruoyi.project.business.service.flow.IFlowUserPermService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import javax.validation.constraints.NotNull;
import java.util.List;
import java.util.Map;
import java.util.Objects;

import static com.google.common.collect.Lists.newArrayList;
import static com.ruoyi.common.utils.SecurityUtils.getUserId;
import static java.util.stream.Collectors.*;
import static org.apache.commons.collections4.CollectionUtils.isEmpty;
import static org.apache.commons.collections4.CollectionUtils.isNotEmpty;

/**
 * <p>
 * 流程数据权限表(用于列表数据筛选，处理审批过程中的用户权限关系，审批通过后删除) 服务实现类
 * </p>
 *
 * @author CAC
 * @since 2023-10-18
 */
@Service
public class FlowUserPermServiceImpl extends ServiceImpl<FlowUserPermMapper, FlowUserPerm> implements IFlowUserPermService {

    @Resource
    private IFlowService flowService;

    @Override
    public void addPerm(AuditFlowEnum auditFlowEnum, Integer businessId) {
        addPerm(Lists.newArrayList(SecurityUtils.getUserId()), auditFlowEnum, businessId);
    }

    @Override
    public void addPermBatch(AuditFlowEnum auditFlowEnum, List<Integer> businessIds) {
        addPermBatch(Lists.newArrayList(SecurityUtils.getUserId()), auditFlowEnum, businessIds);
    }

    @Override
    public void addPerm(List<Long> userIds, AuditFlowEnum auditFlowEnum, Integer businessId) {
        addPermBatch(userIds, auditFlowEnum, newArrayList(businessId));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void addPermBatch(List<Long> userIds, AuditFlowEnum auditFlowEnum, List<Integer> businessIds) {
        // 1. 获取已存的数据权限
        Map<Integer, List<Long>> existDataPerm = list(Wrappers.<FlowUserPerm>lambdaQuery()
                .eq(FlowUserPerm::getAuditFlow, auditFlowEnum.getValue()))
                .stream().collect(groupingBy(FlowUserPerm::getBusinessId, mapping(FlowUserPerm::getPermUserId, toList())));

        // 2. 添加当前操作人和审批人的权限
        List<FlowUserPerm> data = newArrayList();
        List<Long> addPermUsers = userIds.stream().distinct().collect(toList());
        businessIds.forEach(businessId -> {
            List<Long> permUsers = existDataPerm.get(businessId);
            // 添加还未获得权限的人到权限表
            data.addAll(addPermUsers.stream()
                    .filter(userId -> isEmpty(permUsers) || !permUsers.contains(userId))
                    .map(userId -> {
                        FlowUserPerm flowUserPerm = new FlowUserPerm();
                        flowUserPerm.setAuditFlow(auditFlowEnum.getValue());
                        flowUserPerm.setBusinessId(businessId);
                        flowUserPerm.setPermUserId(userId);
                        return flowUserPerm;
                    }).collect(toList()));
        });
        saveBatch(data);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void removePerm(AuditFlowEnum auditFlow, @NotNull Long businessId) {
        remove(Wrappers.<FlowUserPerm>lambdaQuery()
                .eq(FlowUserPerm::getAuditFlow, auditFlow.getValue())
                .eq(FlowUserPerm::getBusinessId, businessId));
    }

    @Override
    public boolean hasPerm(AuditFlowEnum auditFlow, @NotNull Long businessId) {
        Flow flow = flowService.getFlowMap(Lists.newArrayList(businessId), auditFlow).get(businessId);
        if (Objects.nonNull(flow) && AuditStatusEnum.PASS.getValue().equals(flow.getStatus())) {
            return true;
        }
        return isNotEmpty(
                list(Wrappers.<FlowUserPerm>lambdaQuery()
                        .eq(FlowUserPerm::getAuditFlow, auditFlow.getValue())
                        .eq(FlowUserPerm::getBusinessId, businessId)
                        .eq(FlowUserPerm::getPermUserId, getUserId()))
        );
    }
}
