package com.qmth.teachcloud.common.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.teachcloud.common.bean.params.ApproveUserResult;
import com.qmth.teachcloud.common.bean.params.SysRoleGroupMemberMatch;
import com.qmth.teachcloud.common.bean.params.SysRoleGroupMemberMatchParams;
import com.qmth.teachcloud.common.bean.params.SysRoleGroupMemberParams;
import com.qmth.teachcloud.common.bean.result.SysRoleGroupMemberMatchResult;
import com.qmth.teachcloud.common.bean.result.SysRoleGroupMemberResult;
import com.qmth.teachcloud.common.contant.SystemConstant;
import com.qmth.teachcloud.common.entity.SysRoleGroupMember;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.entity.SysUserRole;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.enums.FieldUniqueEnum;
import com.qmth.teachcloud.common.mapper.SysRoleGroupMemberMapper;
import com.qmth.teachcloud.common.service.SysRoleGroupMemberService;
import com.qmth.teachcloud.common.service.SysUserRoleService;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.util.ResultUtil;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色组成员表 服务实现类
 * </p>
 *
 * @author wangliang
 * @since 2022-03-08
 */
@Service
public class SysRoleGroupMemberServiceImpl extends ServiceImpl<SysRoleGroupMemberMapper, SysRoleGroupMember> implements SysRoleGroupMemberService {

    @Resource
    SysUserService sysUserService;

    @Resource
    SysUserRoleService sysUserRoleService;

    /**
     * boolean
     *
     * @param roleGroupMemberParams
     * @return
     */
    @Override
    @Transactional
    public boolean saveOrUpdate(SysRoleGroupMemberParams roleGroupMemberParams) {
        try {
            //先查询数据库里的数据
            List<SysRoleGroupMember> sysRoleGroupMemberDbList = this.findByRoleIdAndUserId(roleGroupMemberParams.getRoleId(), roleGroupMemberParams.getUserId());
            List<SysRoleGroupMember> sysRoleGroupMemberList = null;
            List<Long> memberIdList = roleGroupMemberParams.getMemberIdList();
            if (Objects.nonNull(sysRoleGroupMemberDbList) && sysRoleGroupMemberDbList.size() > 0) {//编辑
                if (Objects.nonNull(memberIdList) && memberIdList.size() > 0) {
                    int count = (int) sysRoleGroupMemberDbList.stream().filter(s -> memberIdList.contains(s.getMemberId())).count();
                    if (count != sysRoleGroupMemberDbList.size() || memberIdList.size() != sysRoleGroupMemberDbList.size()) {
                        //全量删除
                        this.removeByIds(sysRoleGroupMemberDbList.stream().map(s -> s.getId()).collect(Collectors.toList()));
                        sysRoleGroupMemberList = new ArrayList<>();
                        for (Long l : memberIdList) {
                            sysRoleGroupMemberList.add(new SysRoleGroupMember(roleGroupMemberParams.getRoleId(), roleGroupMemberParams.getUserId(), l));
                        }
                    }
                } else {
                    this.removeByIds(sysRoleGroupMemberDbList.stream().map(s -> s.getId()).collect(Collectors.toList()));
                }
            } else {
                if (Objects.nonNull(memberIdList) && memberIdList.size() > 0) {
                    sysRoleGroupMemberList = new ArrayList<>();
                    for (Long l : memberIdList) {
                        sysRoleGroupMemberList.add(new SysRoleGroupMember(roleGroupMemberParams.getRoleId(), roleGroupMemberParams.getUserId(), l));
                    }
                }
            }
            if (Objects.nonNull(sysRoleGroupMemberList)) {
                this.saveBatch(sysRoleGroupMemberList);
            }
        } catch (Exception e) {
            log.error(SystemConstant.LOG_ERROR, e);
            if (e instanceof DuplicateKeyException) {
                String errorColumn = e.getCause().toString();
                String repeatColumn = errorColumn.substring(errorColumn.lastIndexOf("entry") + 6, errorColumn.length());
                repeatColumn = repeatColumn.substring(0, repeatColumn.lastIndexOf("for") - 2);
                String[] strs = repeatColumn.split("-");
                SysUser sysuser = null;
                if (Objects.nonNull(strs) && strs.length >= 2) {
                    sysuser = sysUserService.getById(SystemConstant.convertIdToLong(strs[1]));
                }
                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
                if (Objects.nonNull(sysuser)) {
                    throw ExceptionResultEnum.SQL_ERROR.exception("[" + sysuser.getRealName() + FieldUniqueEnum.convertToTitle(columnStr) + "]数据不允许重复插入");
                } else {
                    throw ExceptionResultEnum.SQL_ERROR.exception("[" + FieldUniqueEnum.convertToTitle(columnStr) + "]数据不允许重复插入");
                }
            } else if (e instanceof ApiException) {
                ResultUtil.error((ApiException) e, e.getMessage());
            } else {
                ResultUtil.error(e.getMessage());
            }
        }
        return true;
    }

    /**
     * 根据roleId查找数据
     *
     * @param roleId
     * @param name
     * @return
     */
    @Override
    public List<SysRoleGroupMemberResult> findByRoleIdAndName(Long roleId, String name) {
        List<SysRoleGroupMemberResult> sysRoleGroupMemberResultList = null;
        if (Objects.nonNull(roleId) && Objects.nonNull(name)) {
            List<ApproveUserResult> approveUserResultList = sysUserService.findByRoldIdAndMemberName(roleId, name);
            if (Objects.nonNull(approveUserResultList) && approveUserResultList.size() > 0) {
                Map<String, List<ApproveUserResult>> map = new LinkedHashMap<>();
                List<ApproveUserResult> list = null;
                for (ApproveUserResult a : approveUserResultList) {
                    if (!map.containsKey(a.getRoleId() + "_" + a.getUserId())) {
                        list = new ArrayList<>();
                    } else {
                        list = map.get(a.getRoleId() + "_" + a.getUserId());
                    }
                    list.add(a);
                    map.put(a.getRoleId() + "_" + a.getUserId(), list);
                }
                sysRoleGroupMemberResultList = new ArrayList<>();
                for (Map.Entry<String, List<ApproveUserResult>> entry : map.entrySet()) {
                    String[] strs = entry.getKey().split("_");
                    List<ApproveUserResult> approveUserResult = sysUserService.findById(SystemConstant.convertIdToLong(strs[1]));
                    sysRoleGroupMemberResultList.add(new SysRoleGroupMemberResult(approveUserResult.get(0), entry.getValue()));
                }
            }
        } else {
            List<SysUserRole> sysUserRoles = sysUserRoleService.listByRoleId(roleId);
            if (Objects.nonNull(sysUserRoles) && sysUserRoles.size() > 0) {
                sysRoleGroupMemberResultList = new ArrayList<>();
                for (SysUserRole s : sysUserRoles) {
                    List<ApproveUserResult> approveUserResult = sysUserService.findById(s.getUserId());
                    if (Objects.nonNull(approveUserResult) && approveUserResult.size() == 1) {
                        List<SysRoleGroupMember> sysRoleGroupMemberList = this.findByRoleIdAndUserId(s.getRoleId(), s.getUserId());
                        if (Objects.nonNull(sysRoleGroupMemberList) && sysRoleGroupMemberList.size() > 0) {
                            List<ApproveUserResult> approveUserResultList = sysUserService.findByIdsForResult(sysRoleGroupMemberList.stream().map(x -> x.getMemberId()).collect(Collectors.toList()));
                            sysRoleGroupMemberResultList.add(new SysRoleGroupMemberResult(approveUserResult.get(0), approveUserResultList));
                        } else {
                            sysRoleGroupMemberResultList.add(new SysRoleGroupMemberResult(approveUserResult.get(0)));
                        }
                    }
                }
            }
        }
        return sysRoleGroupMemberResultList;
    }

    /**
     * 根据ids count数据
     *
     * @param ids
     * @return
     */
    @Override
    public int findByIdsCount(List<Long> ids) {
        return this.count(new QueryWrapper<SysRoleGroupMember>().lambda().in(SysRoleGroupMember::getId, ids).eq(SysRoleGroupMember::getEnable, true));
    }

    /**
     * 根据roleId和userId查找数据
     *
     * @param roleId
     * @param userId
     * @return
     */
    @Override
    public List<SysRoleGroupMember> findByRoleIdAndUserId(Long roleId, Long userId) {
        return this.list(new QueryWrapper<SysRoleGroupMember>().lambda().eq(SysRoleGroupMember::getRoleId, roleId).eq(SysRoleGroupMember::getUserId, userId).eq(SysRoleGroupMember::getEnable, true));
    }

    /**
     * 根据roleIds和memberId查找数据
     *
     * @param roleIds
     * @param memberId
     * @return
     */
    @Override
    public List<SysRoleGroupMember> findByRoleIdsAndMemberId(List<Long> roleIds, Long memberId) {
        return this.list(new QueryWrapper<SysRoleGroupMember>().lambda().in(SysRoleGroupMember::getRoleId, roleIds).eq(SysRoleGroupMember::getMemberId, memberId).eq(SysRoleGroupMember::getEnable, true));
    }

    /**
     * 根据roleIds和memberIds查找数据
     *
     * @param roleIds
     * @param memberIds
     * @return
     */
    @Override
    public List<SysRoleGroupMember> findByRoleIdsAndMemberIds(List<Long> roleIds, List<Long> memberIds) {
        return this.list(new QueryWrapper<SysRoleGroupMember>().lambda().in(SysRoleGroupMember::getRoleId, roleIds).in(SysRoleGroupMember::getMemberId, memberIds).eq(SysRoleGroupMember::getEnable, true));
    }

    /**
     * 流程数据组匹配查询
     *
     * @param roleGroupMemberMatchParams
     * @return
     */
    @Override
    public Map<String, SysRoleGroupMemberMatchResult> matchList(SysRoleGroupMemberMatchParams roleGroupMemberMatchParams) {
        Map<String, SysRoleGroupMemberMatchResult> approveUserResultMap = new LinkedHashMap<>();
        Map<String, SysRoleGroupMemberMatch> map = roleGroupMemberMatchParams.getFlowRoleGroupMemberMatchMap();
        List<Long> nextApproveUserList = null;
        for (Map.Entry<String, SysRoleGroupMemberMatch> entry : map.entrySet()) {
            List<SysRoleGroupMember> sysRoleGroupMemberList = null;
            List<Long> sysRoleGroupMemberIdList = new ArrayList<>();
            if (Objects.nonNull(entry.getValue().getUserId())) {
                sysRoleGroupMemberList = this.findByRoleIdsAndMemberId(entry.getValue().getRoleIdList(), entry.getValue().getUserId());
            } else if (Objects.nonNull(nextApproveUserList) && nextApproveUserList.size() > 0) {
                sysRoleGroupMemberList = this.findByRoleIdsAndMemberIds(entry.getValue().getRoleIdList(), nextApproveUserList);
            }

            if (Objects.nonNull(sysRoleGroupMemberList) && sysRoleGroupMemberList.size() > 0) {
                boolean manual = false;
                if (sysRoleGroupMemberList.size() == 1) {//直接返回
                    manual = false;
                } else if (sysRoleGroupMemberList.size() > 1) {//前端选择
                    manual = true;
                }

                if (Objects.isNull(nextApproveUserList)) {
                    nextApproveUserList = new ArrayList<>();
                } else {
                    nextApproveUserList.clear();
                }
                for (SysRoleGroupMember s : sysRoleGroupMemberList) {
                    sysRoleGroupMemberIdList.add(s.getId());
                    nextApproveUserList.add(s.getUserId());
                }
                List<ApproveUserResult> approveUserResultList = sysUserService.findByIdsForResult(nextApproveUserList);
                approveUserResultMap.put(entry.getKey(), new SysRoleGroupMemberMatchResult(manual, approveUserResultList, sysRoleGroupMemberIdList));
            } else {
                approveUserResultMap.put(entry.getKey(), null);
            }
        }
        return approveUserResultMap;
    }
}
