package com.zanxiang.game.module.manage.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.erp.base.ErpServer;
import com.zanxiang.erp.base.pojo.vo.SysGameUserGroupRpcVO;
import com.zanxiang.erp.base.rpc.ISysGameUserGroupRpc;
import com.zanxiang.erp.base.rpc.ISysUserRpc;
import com.zanxiang.erp.security.util.SecurityUtil;
import com.zanxiang.game.module.base.pojo.enums.DeleteEnum;
import com.zanxiang.game.module.base.pojo.enums.GameAuthEnum;
import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.pojo.params.GameAuthAddParam;
import com.zanxiang.game.module.manage.pojo.params.GameAuthListParam;
import com.zanxiang.game.module.manage.pojo.params.GameAuthUpdateParam;
import com.zanxiang.game.module.manage.pojo.vo.GameAuthVO;
import com.zanxiang.game.module.manage.service.IGameAuthRoleService;
import com.zanxiang.game.module.manage.service.IGameAuthService;
import com.zanxiang.game.module.manage.service.IGameService;
import com.zanxiang.game.module.mybatis.entity.GameAuth;
import com.zanxiang.game.module.mybatis.entity.GameAuthRole;
import com.zanxiang.game.module.mybatis.mapper.GameAuthMapper;
import com.zanxiang.module.util.bean.BeanUtil;
import com.zanxiang.module.util.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import reactor.util.function.Tuple2;
import reactor.util.function.Tuples;

import java.time.LocalDateTime;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2023-08-16
 * @description : 游戏授权
 */
@Slf4j
@Service
public class GameAuthServiceImpl extends ServiceImpl<GameAuthMapper, GameAuth> implements IGameAuthService {

    @Autowired
    private IGameService gameService;

    @Autowired
    private IGameAuthRoleService gameAuthRoleService;

    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
    private ISysUserRpc sysUserRpc;

    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
    private ISysGameUserGroupRpc sysGameUserGroupRpc;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean gameAuthAdd(GameAuthAddParam param) {
        List<Long> userIdList = param.getUserIdList();
        List<GameAuthAddParam.GameAuthBean> gameAuthList = param.getGameAuthList();
        List<GameAuth> addList = new ArrayList<>();
        userIdList.forEach(userId -> {
            //判断角色是否正确
            if (gameAuthRoleService.count(new LambdaQueryWrapper<GameAuthRole>()
                    .eq(GameAuthRole::getUserId, userId)
                    .eq(GameAuthRole::getAuthType, param.getGameAuthEnum().getValue())
            ) <= 0) {
                throw new BaseException("参数错误, 提交得用户存在权限不匹配");
            }
            //循环添加
            gameAuthList.forEach(gameAuthBean -> {
                //判断提交的参数数据是否已经存在
                if (super.count(new LambdaQueryWrapper<GameAuth>()
                        .eq(GameAuth::getGameId, gameAuthBean.getGameId())
                        .eq(GameAuth::getUserId, userId)
                ) > 0) {
                    return;
                }
                addList.add(this.transform(gameAuthBean, userId));
            });
        });
        if (addList.isEmpty()) {
            return Boolean.FALSE;
        }
        return super.saveBatch(addList);
    }

    private GameAuth transform(GameAuthAddParam.GameAuthBean gameAuthBean, Long userId) {
        return GameAuth.builder()
                .gameId(gameAuthBean.getGameId())
                .userId(userId)
                .isDelete(DeleteEnum.NO.getCode())
                .createBy(SecurityUtil.getUserId())
                .createTime(LocalDateTime.now())
                .updateBy(SecurityUtil.getUserId())
                .updateTime(LocalDateTime.now())
                .defaultAgent(gameAuthBean.getDefaultAgent())
                .build();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean gameAuthUpdate(GameAuthUpdateParam param) {
        //判断提交的参数数据是否已经存在
        if (super.count(new LambdaQueryWrapper<GameAuth>()
                .eq(GameAuth::getGameId, param.getGameId())
                .eq(GameAuth::getUserId, param.getUserId())
        ) > 0) {
            throw new BaseException("参数错误, 要修改的数据已经存在相同数据");
        }
        //修改
        return super.update(new LambdaUpdateWrapper<GameAuth>()
                .set(GameAuth::getGameId, param.getGameId())
                .set(GameAuth::getDefaultAgent, param.getDefaultAgent())
                .set(GameAuth::getUpdateBy, SecurityUtil.getUserId())
                .set(GameAuth::getUpdateTime, LocalDateTime.now())
                .eq(GameAuth::getId, param.getId()));
    }

    @Override
    public IPage<GameAuthVO> listOfPage(GameAuthListParam param) {
        return page(param.toPage(), new QueryWrapper<GameAuth>().lambda()
                .eq(param.getGameId() != null, GameAuth::getGameId, param.getGameId())
                .eq(param.getUserId() != null, GameAuth::getUserId, param.getUserId())
                .orderByDesc(GameAuth::getUpdateTime)
        ).convert(this::toVo);
    }

    private GameAuthVO toVo(GameAuth gameAuth) {
        if (Objects.isNull(gameAuth)) {
            return null;
        }
        GameAuthVO gameAuthVO = BeanUtil.copy(gameAuth, GameAuthVO.class);
        GameDTO gameDTO = gameService.getById(gameAuthVO.getGameId());
        gameAuthVO.setGameName(gameDTO == null ? null : gameDTO.getName());
        Map<Long, String> userMap = sysUserRpc.getUserNameByIds(Collections.singletonList(gameAuthVO.getUserId())).getData();
        gameAuthVO.setUserName(userMap.get(gameAuthVO.getUserId()));
        GameAuthRole gameAuthRole = gameAuthRoleService.getOne(new LambdaQueryWrapper<GameAuthRole>()
                .eq(GameAuthRole::getUserId, gameAuthVO.getUserId()));
        if (gameAuthRole != null) {
            gameAuthVO.setAuthType(GameAuthEnum.getByValue(gameAuthRole.getAuthType()));
        }
        return gameAuthVO;
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean deleteById(Long id) {
        return super.removeById(id);
    }

    @Override
    public Tuple2<String, List<Long>> getUserGameList(String userId) {
        //查询用户权限角色
        GameAuthRole gameAuthRole = gameAuthRoleService.getOne(new LambdaQueryWrapper<GameAuthRole>()
                .eq(GameAuthRole::getUserId, SecurityUtil.getUserId()));
        if (!SecurityUtil.isAdmin() && gameAuthRole == null) {
            throw new BaseException("参数错误, 无法查询到用户的权限角色信息");
        }
        //超管权限
        if (SecurityUtil.isAdmin() || Objects.equals(gameAuthRole.getAuthType(), GameAuthEnum.MANAGE.getValue())) {
            List<Long> gameIdList = super.list(new LambdaQueryWrapper<GameAuth>()
                    .eq(Strings.isNotBlank(userId), GameAuth::getUserId, Strings.isBlank(userId) ? null : Long.valueOf(userId))
            ).stream().map(GameAuth::getGameId).collect(Collectors.toList());
            if (SecurityUtil.isAdmin()) {
                return Tuples.of(GameAuthEnum.ADMIN.getValue(), gameIdList);
            }
            return Tuples.of(gameAuthRole.getAuthType(), gameIdList);
        }
        //非超管权限查询
        List<Long> gameIdList = super.list(new LambdaQueryWrapper<GameAuth>()
                .eq(Strings.isBlank(userId), GameAuth::getUserId, SecurityUtil.getUserId())
                .eq(Strings.isNotBlank(userId), GameAuth::getUserId, Strings.isBlank(userId) ? null : Long.valueOf(userId))
        ).stream().map(GameAuth::getGameId).collect(Collectors.toList());
        //返回角色权限以及游戏
        return Tuples.of(gameAuthRole.getAuthType(), gameIdList);
    }

    @Override
    public Map<Long, String> agentUserChoiceList() {
        //判断是否是组长
        SysGameUserGroupRpcVO sysGameUserGroupRpcVO = sysGameUserGroupRpc.getByGroupUser(SecurityUtil.getCompanyId(),
                SecurityUtil.getUserId()).getData();
        //判断运营
        GameAuthRole gameAuthRole = gameAuthRoleService.getOne(new LambdaQueryWrapper<GameAuthRole>()
                .eq(GameAuthRole::getUserId, SecurityUtil.getUserId()));
        //所有投手
        List<Long> pitcherIdList = gameAuthRoleService.list(new LambdaQueryWrapper<GameAuthRole>()
                .eq(GameAuthRole::getAuthType, GameAuthEnum.PITCHER.getValue())
        ).stream().map(GameAuthRole::getUserId).collect(Collectors.toList());
        //游戏权限
        Tuple2<String, List<Long>> userGameTuple2 = this.getUserGameList(null);
        if (CollectionUtils.isEmpty(userGameTuple2.getT2())) {
            throw new BaseException("未查询到用户游戏列表");
        }
        List<GameAuth> gameAuthList;
        //超管或者管理员
        if (SecurityUtil.isAdmin() || Objects.equals(gameAuthRole.getAuthType(), GameAuthEnum.MANAGE.getValue())) {
            gameAuthList = super.list(new LambdaQueryWrapper<GameAuth>()
                    .in(GameAuth::getUserId, pitcherIdList));
        } else if (Objects.equals(gameAuthRole.getAuthType(), GameAuthEnum.OPERATE.getValue())) {
            //运营权限
            gameAuthList = super.list(new LambdaQueryWrapper<GameAuth>()
                    .in(GameAuth::getGameId, userGameTuple2.getT2())
                    .in(GameAuth::getUserId, pitcherIdList));
        } else if (sysGameUserGroupRpcVO != null) {
            //组长权限, 获取组员id, 查询组内所有人
            Collection<Long> memberUserIdList = sysGameUserGroupRpc.memberUserIds(SecurityUtil.getCompanyId(),
                    SecurityUtil.getUserId()).getData();
            List<Long> userIdList = memberUserIdList.stream().filter(pitcherIdList::contains).collect(Collectors.toList());
            gameAuthList = super.list(new LambdaQueryWrapper<GameAuth>()
                    .in(GameAuth::getGameId, userGameTuple2.getT2())
                    .in(GameAuth::getUserId, userIdList));
        } else {
            gameAuthList = super.list(new LambdaQueryWrapper<GameAuth>()
                    .in(GameAuth::getGameId, userGameTuple2.getT2())
                    .eq(GameAuth::getUserId, SecurityUtil.getUserId()));
        }
        return sysUserRpc.getUserNameByIds(gameAuthList.stream().map(GameAuth::getUserId)
                .distinct().collect(Collectors.toList())
        ).getData();
    }
}
