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

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.game.module.base.pojo.enums.GameCategoryEnum;
import com.zanxiang.game.module.base.util.DateUtils;
import com.zanxiang.game.module.manage.pojo.dto.AgentDTO;
import com.zanxiang.game.module.manage.pojo.dto.CpDTO;
import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.pojo.dto.UserDTO;
import com.zanxiang.game.module.manage.pojo.params.GameUserListParam;
import com.zanxiang.game.module.manage.pojo.vo.GameUserListVO;
import com.zanxiang.game.module.manage.pojo.vo.GameUserVO;
import com.zanxiang.game.module.manage.service.*;
import com.zanxiang.game.module.mybatis.entity.Agent;
import com.zanxiang.game.module.mybatis.entity.GameUser;
import com.zanxiang.game.module.mybatis.entity.GameUserRole;
import com.zanxiang.game.module.mybatis.mapper.GameUserMapper;
import com.zanxiang.module.util.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import reactor.util.function.Tuple2;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2022-07-04
 * @description : 玩家游戏
 */
@Slf4j
@Service
public class GameUserServiceImpl extends ServiceImpl<GameUserMapper, GameUser> implements IGameUserService {

    @Autowired
    private IUserService userService;

    @Autowired
    private IGameService gameService;

    @Autowired
    private ICpService cpService;

    @Autowired
    private IAgentService agentService;

    @Autowired
    private IGameUserRoleService gameUserRoleService;

    @Autowired
    private IGameAuthService gameAuthService;

    @Override
    public IPage<GameUserListVO> gameUserList(GameUserListParam param) {
        //游戏获取
        Tuple2<String, List<Long>> gameTuple = gameAuthService.getUserGameList(param.getPitcherId());
        if (CollectionUtils.isEmpty(gameTuple.getT2())) {
            return new Page<>();
        }
        //游戏条件处理
        Map<Long, GameDTO> gameMap = gameService.gameCondition(gameTuple.getT2(), param.getCpId(), param.getGameId(), param.getGameCategoryId());
        //根据条件, 匹配不到游戏
        if (CollectionUtils.isEmpty(gameMap)) {
            return new Page<>();
        }
        //渠道获取
        Tuple2<List<Long>, List<AgentDTO>> tuple2 = agentService.getUserAgent(param.getAccountId(), param.getPitcherId(), param.getChannelId());
        List<Long> agentIdList = tuple2.getT1();
        List<AgentDTO> agentDTOList = tuple2.getT2();
        if (CollectionUtils.isEmpty(agentIdList)) {
            return new Page<>();
        }
        //玩家条件处理
        Map<Long, UserDTO> userMap = userService.userCondition(param.getUserId(), agentIdList, param.getUserName(),
                param.getNickname(), null, null, null);
        //根据条件, 匹配不到玩家
        if (userMap != null && userMap.isEmpty()) {
            return new Page<>();
        }
        //相关用户id
        Map<Long, CpDTO> cpMap = cpService.cpMap();
        Set<Long> userIdSet = userMap == null ? null : userMap.keySet();
        Map<Long, AgentDTO> agentMap = agentDTOList.stream().collect(Collectors.toMap(AgentDTO::getId, Function.identity()));
        //执行查询
        return page(param.toPage(), new QueryWrapper<GameUser>().lambda()
                .in(GameUser::getGameId, gameMap.keySet())
                .in(CollectionUtils.isNotEmpty(userIdSet), GameUser::getUserId, userIdSet)
                .ge(param.getBeginDate() != null, GameUser::getCreateTime, param.getBeginDate() == null ? null : LocalDateTime.of(param.getBeginDate(), LocalTime.MIN))
                .le(param.getEndDate() != null, GameUser::getCreateTime, param.getEndDate() == null ? null : LocalDateTime.of(param.getEndDate(), LocalTime.MAX))
                .ge(param.getRechargeBeginDate() != null, GameUser::getLastRechargeTime, param.getRechargeBeginDate() == null ? null : LocalDateTime.of(param.getRechargeBeginDate(), LocalTime.MIN))
                .le(param.getRechargeEndDate() != null, GameUser::getLastRechargeTime, param.getRechargeEndDate() == null ? null : LocalDateTime.of(param.getRechargeEndDate(), LocalTime.MAX))
                .gt(Objects.equals(param.getIsRecharge(), Boolean.TRUE), GameUser::getRechargeCount, 0)
                .eq(Objects.equals(param.getIsRecharge(), Boolean.FALSE), GameUser::getRechargeCount, 0)
                .apply(param.getRegPayIntervalTimeMin() != null, "if(last_recharge_time is not null, TIMESTAMPDIFF(minute, reg_time, last_recharge_time), null) >= {0}", param.getRegPayIntervalTimeMin())
                .apply(param.getRegPayIntervalTimeMax() != null, "if(last_recharge_time is not null, TIMESTAMPDIFF(minute, reg_time, last_recharge_time), null) <= {0}", param.getRegPayIntervalTimeMax())
                .orderByDesc(GameUser::getCreateTime)
        ).convert(u -> this.toVo(u, userMap, gameMap, agentMap, cpMap));
    }

    private GameUserListVO toVo(GameUser gameUser, Map<Long, UserDTO> userMap, Map<Long, GameDTO> gameMap,
                                Map<Long, AgentDTO> agentMap, Map<Long, CpDTO> cpMap) {
        GameUserListVO gameUserListVO = BeanUtil.copy(gameUser, GameUserListVO.class);
        if (Objects.isNull(gameUserListVO)) {
            return null;
        }
        UserDTO userDTO = CollectionUtils.isEmpty(userMap) ? null : userMap.get(gameUserListVO.getUserId());
        if (userDTO == null) {
            userDTO = userService.getById(gameUserListVO.getUserId());
        }
        if (userDTO != null) {
            gameUserListVO.setNickname(userDTO.getNickname());
            gameUserListVO.setUsername(userDTO.getUsername());
            //用户渠道
            AgentDTO agentDTO = agentMap.get(userDTO.getAgentId());
            if (agentDTO != null) {
                gameUserListVO.setAgentName(agentDTO.getAgentName());
                gameUserListVO.setPitcherId(agentDTO.getCreateBy());
                gameUserListVO.setPitcherName(agentDTO.getCreateByName());
                gameUserListVO.setAccountId(agentDTO.getAccountId());
            }
            if (Objects.equals(Agent.DEFAULT_AGENT, userDTO.getAgentId())) {
                gameUserListVO.setAgentName(Agent.DEFAULT_AGENT_NAME);
            }
        }
        GameDTO gameDTO;
        if (CollectionUtils.isNotEmpty(gameMap) && gameMap.containsKey(gameUserListVO.getGameId())) {
            gameDTO = gameMap.get(gameUserListVO.getGameId());
        } else {
            gameDTO = gameService.getById(gameUserListVO.getGameId());
        }
        if (gameDTO != null) {
            gameUserListVO.setCpId(gameDTO.getCpId());
            gameUserListVO.setGameName(gameDTO.getName());
            gameUserListVO.setGameCategoryId(gameDTO.getCategory());
            gameUserListVO.setCpName(cpMap.get(gameDTO.getCpId()) == null ? null : cpMap.get(gameDTO.getCpId()).getCpName());
            gameUserListVO.setGameCategoryName(GameCategoryEnum.getNameByCategory(gameDTO.getCategory()));
        }
        //最近角色
        GameUserRole gameUserRole = gameUserRoleService.getLastGameUserRoleName(gameUser.getUserId(), gameUser.getGameId());
        gameUserListVO.setLastGameRoleName(gameUserRole == null ? null : gameUserRole.getRoleName());
        //注册充值时间差
        gameUserListVO.setRegPayTimeDiff(DateUtils.getRegPayTimeDiff(gameUserListVO.getRegTime(), gameUserListVO.getLastRechargeTime()));
        //返回
        return gameUserListVO;
    }

    @Override
    public GameUserVO getById(Long id) {
        return BeanUtil.copy(super.getById(id), GameUserVO.class);
    }
}
