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.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.pojo.params.GameGiftPackLinkLogListParam;
import com.zanxiang.game.module.manage.pojo.vo.GameGiftPackLinkLogVO;
import com.zanxiang.game.module.manage.service.*;
import com.zanxiang.game.module.mybatis.entity.*;
import com.zanxiang.game.module.mybatis.mapper.GameGiftPackLinkLogMapper;
import com.zanxiang.module.util.bean.BeanUtil;
import com.zanxiang.module.util.exception.BaseException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.logging.log4j.util.Strings;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import java.net.URLDecoder;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2022-06-22
 * @description : 游戏礼包码链接访问日志
 */
@Slf4j
@Service
public class GameGiftPackLinkLogServiceImpl extends ServiceImpl<GameGiftPackLinkLogMapper, GameGiftPackLinkLog> implements IGameGiftPackLinkLogService {

    @Autowired
    private IGameService gameService;

    @Autowired
    private ISmsService smsService;

    @Autowired
    private IGameServerService gameServerService;

    @Autowired
    private IRoleOperateService roleOperateService;

    @Autowired
    private IGameUserRoleService gameUserRoleService;

    @Autowired
    private IGameGiftPackLinkService gameGiftPackLinkService;

    @Override
    public IPage<GameGiftPackLinkLogVO> list(GameGiftPackLinkLogListParam param) {
        IPage<GameGiftPackLinkLog> linkLogIPage = page(param.toPage(), new QueryWrapper<GameGiftPackLinkLog>().lambda()
                .eq(GameGiftPackLinkLog::getLinkId, param.getLinkId())
                .ge(param.getCreateBeginTime() != null, GameGiftPackLinkLog::getCreateTime, param.getCreateBeginTime() == null ? null : LocalDateTime.of(param.getCreateBeginTime(), LocalTime.MIN))
                .le(param.getCreateEndTime() != null, GameGiftPackLinkLog::getCreateTime, param.getCreateEndTime() == null ? null : LocalDateTime.of(param.getCreateEndTime(), LocalTime.MAX))
                .orderByDesc(GameGiftPackLinkLog::getCreateTime));
        IPage<GameGiftPackLinkLogVO> result = new Page<>(linkLogIPage.getCurrent(), linkLogIPage.getSize(), linkLogIPage.getTotal());
        if (CollectionUtils.isNotEmpty(linkLogIPage.getRecords())) {
            List<GameGiftPackLinkLog> records = linkLogIPage.getRecords();
            Map<String, String> gameServerMap = this.getSourceGameServerByLinkId(param.getLinkId());
            result.setRecords(this.toVOBatch(records, gameServerMap));
        }
        return result;
    }

    private List<GameGiftPackLinkLogVO> toVOBatch(List<GameGiftPackLinkLog> linkLogList, Map<String, String> gameServerMap) {
        return linkLogList.stream().map(linkLog -> {
            GameGiftPackLinkLogVO gameGiftPackCodeLogVO = BeanUtil.copy(linkLog, GameGiftPackLinkLogVO.class);
            gameGiftPackCodeLogVO.setServerName(gameServerMap.get(linkLog.getServerId()));
            return gameGiftPackCodeLogVO;
        }).collect(Collectors.toList());
    }

    @Override
    public Map<String, String> getSourceGameServerByLinkId(Long linkId) {
        //查询访问日志
        GameGiftPackLink giftPackLink = gameGiftPackLinkService.getById(linkId);
        Assert.notNull(giftPackLink, "参数错误, 链接信息不存在");
        return this.getSourceGameServerByGameId(giftPackLink.getGameId());
    }

    @Override
    public Map<String, String> getSourceGameServerByLinkLogId(Long linkLogId) {
        //查询访问日志
        GameGiftPackLinkLog gameGiftPackLinkLog = super.getById(linkLogId);
        Assert.notNull(gameGiftPackLinkLog, "参数错误, 链接访问日志信息不存在");
        return this.getSourceGameServerByGameId(gameGiftPackLinkLog.getGameId());
    }

    private Map<String, String> getSourceGameServerByGameId(Long gameId) {
        //查询游戏信息
        GameDTO gameDTO = gameService.getById(gameId);
        Assert.notNull(gameDTO, "参数错误, 游戏信息不存在");
        //查询区服信息
        return gameServerService.list(new LambdaQueryWrapper<GameServer>()
                .eq(GameServer::getGameId, gameDTO.getSuperGameId())
                .eq(GameServer::getIsSourceServer, Boolean.TRUE)
        ).stream().collect(Collectors.toMap(GameServer::getServerId, GameServer::getServerName));
    }

    @Override
    public boolean randomCodeSend(Long linkLogId, String phoneNumber) {
        //参数校验
        GameGiftPackLinkLog gameGiftPackLinkLog = super.getById(linkLogId);
        Assert.notNull(gameGiftPackLinkLog, "参数错误, 链接访问日志信息不存在");
        //判断是否通过检测
        Assert.state(Strings.isNotBlank(gameGiftPackLinkLog.getRoleId()), "角色名未检测, 请先检测角色名");
        //非前端输入手机号
        if (phoneNumber.contains("****")) {
            //修正手机号, 且发送验证码
            String userPhone = gameGiftPackLinkLog.getUserPhone();
            Assert.state(Strings.isNotBlank(userPhone), "参数错误, 手机号信息缺失");
            return smsService.randomCodeSend(userPhone);
        }
        //判断输入的手机号是否被其他角色绑定
        Assert.state(roleOperateService.count(new LambdaQueryWrapper<RoleOperate>()
                .eq(RoleOperate::getGameId, gameGiftPackLinkLog.getGameId())
                .eq(RoleOperate::getUserPhone, phoneNumber)
        ) <= 0, "该手机号已被其它角色绑定, 请联系客服小姐姐处理");
        //发送验证码
        return smsService.randomCodeSend(phoneNumber);
    }

    @Override
    public Map<String, Object> gameUserRoleCheck(Long linkLogId, String serverId, String roleName) {
        //查询访问日志
        GameGiftPackLinkLog gameGiftPackLinkLog = super.getById(linkLogId);
        Assert.notNull(gameGiftPackLinkLog, "参数错误, 链接访问日志信息不存在");
        //构造返回结果
        Map<String, Object> resultMap = new HashMap<>();
        //查询角色
        List<GameUserRole> gameUserRoleList = gameUserRoleService.list(new LambdaQueryWrapper<GameUserRole>()
                .eq(GameUserRole::getGameId, gameGiftPackLinkLog.getGameId())
                .eq(GameUserRole::getServerId, serverId)
                .eq(GameUserRole::getRoleName, roleName));
        //角色查询结果不存在, 或者为多个
        if (gameUserRoleList.size() != 1) {
            resultMap.put("result", Boolean.FALSE);
            resultMap.put("msg", "角色名称检测不通过");
            return resultMap;
        }
        //角色信息
        GameUserRole gameUserRole = gameUserRoleList.get(0);
        //查询是否已经绑定手机号
        RoleOperate roleOperate = roleOperateService.getOne(new LambdaQueryWrapper<RoleOperate>()
                .eq(RoleOperate::getGameId, gameUserRole.getGameId())
                .eq(RoleOperate::getServerId, gameUserRole.getServerId())
                .eq(RoleOperate::getRoleId, gameUserRole.getRoleId()));
        String userPhone = roleOperate == null || Strings.isBlank(roleOperate.getUserPhone()) ? null : roleOperate.getUserPhone();
        //更新链接访问记录
        gameGiftPackLinkLog.setUserPhone(userPhone);
        gameGiftPackLinkLog.setUserId(gameUserRole.getUserId());
        gameGiftPackLinkLog.setServerId(gameUserRole.getServerId());
        gameGiftPackLinkLog.setRoleId(gameUserRole.getRoleId());
        gameGiftPackLinkLog.setRoleName(gameUserRole.getRoleName());
        gameGiftPackLinkLog.setUpdateTime(LocalDateTime.now());
        super.updateById(gameGiftPackLinkLog);
        //返回结果
        resultMap.put("result", Boolean.TRUE);
        resultMap.put("msg", "角色名称检测成功");
        resultMap.put("roleId", gameUserRole.getRoleId());
        if (Strings.isNotBlank(userPhone)) {
            resultMap.put("userPhone", userPhone.substring(0, 3) + " **** " + userPhone.substring(userPhone.length() - 4));
        }
        return resultMap;
    }

    @Override
    public Long linkVisitLogPush(String url) {
        Map<String, String> urlParameter = this.getUrlParameter(url);
        String linkUrl = urlParameter.get("linkUrl");
        String gameId = urlParameter.get("gameId");
        String codeType = urlParameter.get("codeType");
        String corpId = urlParameter.get("corpId");
        String corpUserId = urlParameter.get("corpUserId");
        String externalUserId = urlParameter.get("externalUserId");
        //参数判断
        if (StringUtils.isAnyEmpty(linkUrl, gameId, codeType)) {
            throw new BaseException("非法链接请求, 链接参数解析异常");
        }
        //查询链接信息
        GameGiftPackLink gameGiftPackLink = gameGiftPackLinkService.getOne(new LambdaQueryWrapper<GameGiftPackLink>()
                .eq(GameGiftPackLink::getGameId, Long.valueOf(gameId))
                .eq(GameGiftPackLink::getCodeType, codeType));
        Assert.notNull(gameGiftPackLink, "非法链接请求, 礼包链接信息不存在");
        //构造
        GameGiftPackLinkLog gameGiftPackLinkLog = this.transform(gameGiftPackLink, linkUrl, corpId, corpUserId, externalUserId);
        super.save(gameGiftPackLinkLog);
        return gameGiftPackLinkLog.getId();
    }

    private GameGiftPackLinkLog transform(GameGiftPackLink gameGiftPackLink, String linkUrl, String corpId,
                                          String corpUserId, String externalUserId) {
        return GameGiftPackLinkLog.builder()
                .linkId(gameGiftPackLink.getId())
                .linkUrl(linkUrl)
                .gameId(gameGiftPackLink.getGameId())
                .corpId(corpId)
                .corpUserId(corpUserId)
                .externalUserId(externalUserId)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
    }

    private Map<String, String> getUrlParameter(String url) {
        //参数判断
        if (Strings.isBlank(url)) {
            return Collections.emptyMap();
        }
        //没有拼接参数
        if (url.indexOf('?') == -1) {
            return Collections.singletonMap("url", url);
        }
        //参数map
        Map<String, String> map = new HashMap<>(6);
        map.put("linkUrl", url);
        try {
            final String charset = "utf-8";
            url = URLDecoder.decode(url, charset);
            //解析参数
            final String contents = url.substring(url.indexOf('?') + 1);
            String[] keyValues = contents.split("&");
            for (String keyValue : keyValues) {
                String key = keyValue.substring(0, keyValue.indexOf("="));
                String value = keyValue.substring(keyValue.indexOf("=") + 1);
                map.put(key, value);
            }
        } catch (Exception e) {
            log.error("url : {}, 链接参数解析异常", url);
            throw new BaseException("链接参数解析异常");
        }
        return map;
    }
}




