package com.zanxiang.game.back.serve.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
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.back.serve.dao.mapper.GameOceanengineAppUserLogMapper;
import com.zanxiang.game.back.serve.oceanengine.MiniGameCallback;
import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineAppUserLogDTO;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppBackLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppUserLog;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.pojo.vo.GameOceanengineAppUserLogVO;
import com.zanxiang.game.back.serve.service.IGameOceanengineAppBackLogService;
import com.zanxiang.game.back.serve.service.IGameOceanengineAppCallbackXgltService;
import com.zanxiang.game.back.serve.service.IGameOceanengineAppUserLogService;
import com.zanxiang.game.module.base.ServerInfo;
import com.zanxiang.game.module.base.pojo.vo.AgentRpcVO;
import com.zanxiang.game.module.base.rpc.IAgentRpc;
import com.zanxiang.module.util.bean.BeanUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@Slf4j
@Service
public class GameOceanengineAppUserLogServiceImpl extends ServiceImpl<GameOceanengineAppUserLogMapper, GameOceanengineAppUserLog>
        implements IGameOceanengineAppUserLogService {

    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
    private IAgentRpc agentRpc;

    @Autowired
    private IGameOceanengineAppBackLogService gameOceanengineAppBackLogService;

    @Autowired
    private IGameOceanengineAppCallbackXgltService gameOceanengineAppCallbackXgltService;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean callback(GameOceanengineAppUserLog userLog, boolean mustBack) {
        BackStatusEnum backStatus = doCallback(userLog, mustBack);

        //星广联投回传 -> 激活
        if (Objects.equals(backStatus, BackStatusEnum.SUCCESS)) {
            try {
                gameOceanengineAppCallbackXgltService.regBack(userLog);
            } catch (Exception ignored) {
            }
        }

        return update(new LambdaUpdateWrapper<GameOceanengineAppUserLog>()
                .set(GameOceanengineAppUserLog::getBackStatus, backStatus.getBackStatus())
                .eq(GameOceanengineAppUserLog::getId, userLog.getId())
        );
    }

    @Override
    public IPage<GameOceanengineAppUserLogVO> oceanengineAppUserLogList(GameOceanengineAppUserLogDTO dto) {
        IPage<GameOceanengineAppUserLog> page = page(dto.toPage(), new LambdaQueryWrapper<GameOceanengineAppUserLog>()
                .eq(StringUtils.isNotBlank(dto.getUserId()), GameOceanengineAppUserLog::getUserId, dto.getUserId())
                .eq(StringUtils.isNotBlank(dto.getMac()), GameOceanengineAppUserLog::getMac, dto.getMac())
                .eq(StringUtils.isNotBlank(dto.getImei()), GameOceanengineAppUserLog::getImei, dto.getImei())
                .eq(StringUtils.isNotBlank(dto.getOaid()), GameOceanengineAppUserLog::getOaid, dto.getOaid())
                .eq(StringUtils.isNotBlank(dto.getAndroidId()), GameOceanengineAppUserLog::getAndroidId, dto.getAndroidId())
                .eq(StringUtils.isNotBlank(dto.getIdfa()), GameOceanengineAppUserLog::getIdfa, dto.getIdfa())
                .eq(StringUtils.isNotBlank(dto.getCaid()), GameOceanengineAppUserLog::getCaid, dto.getCaid())
                .eq(StringUtils.isNotBlank(dto.getAgentKey()), GameOceanengineAppUserLog::getAgentKey, dto.getAgentKey())
                .ge(dto.getActiveTimeBegin() != null, GameOceanengineAppUserLog::getActiveTime, dto.getActiveTimeBegin() == null ? null : LocalDateTime.of(dto.getActiveTimeBegin(), LocalTime.MIDNIGHT))
                .le(dto.getActiveTimeEnd() != null, GameOceanengineAppUserLog::getActiveTime, dto.getActiveTimeEnd() == null ? null : LocalDateTime.of(dto.getActiveTimeEnd(), LocalTime.MAX))
                .eq(null != dto.getGameId(), GameOceanengineAppUserLog::getGameId, dto.getGameId())
                .eq(null != dto.getAccountId(), GameOceanengineAppUserLog::getAccountId, dto.getAccountId())
                .eq(null != dto.getBackStatus(), GameOceanengineAppUserLog::getBackStatus, dto.getBackStatus())
                .orderByDesc(GameOceanengineAppUserLog::getCreateTime)
        );
        IPage<GameOceanengineAppUserLogVO> result = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
        if (CollectionUtils.isEmpty(page.getRecords())) {
            return result;
        }
        result.setRecords(toVOBatch(page.getRecords()));
        return result;
    }

    private List<GameOceanengineAppUserLogVO> toVOBatch(List<GameOceanengineAppUserLog> logList) {
        if (CollectionUtils.isEmpty(logList)) {
            return Collections.emptyList();
        }
        Set<String> agentKeys = logList.stream().map(GameOceanengineAppUserLog::getAgentKey).filter(StringUtils::isNotBlank).collect(Collectors.toSet());
        Map<String, AgentRpcVO> agentMap = CollectionUtils.isEmpty(agentKeys) ? Collections.emptyMap() : agentRpc.getByAgentKeys(new ArrayList<>(agentKeys))
                .getData().stream().collect(Collectors.toMap(AgentRpcVO::getAgentKey, Function.identity()));
        return logList.stream().map(log -> {
            GameOceanengineAppUserLogVO vo = BeanUtil.copy(log, GameOceanengineAppUserLogVO.class);
            if (StringUtils.isNotBlank(log.getAgentKey())) {
                AgentRpcVO agent = agentMap.get(log.getAgentKey());
                if (agent != null) {
                    vo.setAgentName(agent.getAgentName());
                }
            }
            return vo;
        }).collect(Collectors.toList());

    }

    private BackStatusEnum doCallback(GameOceanengineAppUserLog userLog, boolean mustBack) {
        // 是否已经回传过
        if (!mustBack && gameOceanengineAppBackLogService.count(new LambdaQueryWrapper<GameOceanengineAppBackLog>()
                .eq(GameOceanengineAppBackLog::getGameId, userLog.getGameId())
                .eq(GameOceanengineAppBackLog::getUserId, userLog.getUserId())
                .eq(GameOceanengineAppBackLog::getAccountId, userLog.getAccountId())
                .eq(GameOceanengineAppBackLog::getEventType, MiniGameCallback.EventType.ACTIVE.getEventType())
                .eq(GameOceanengineAppBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
        ) > 0) {
            return BackStatusEnum.NO;
        }
        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
        gameOceanengineAppBackLogService.save(GameOceanengineAppBackLog.builder()
                .userId(userLog.getUserId())
                .mac(userLog.getMac())
                .imei(userLog.getImei())
                .oaid(userLog.getOaid())
                .androidId(userLog.getAndroidId())
                .idfa(userLog.getIdfa())
                .caid(userLog.getCaid())
                .gameId(userLog.getGameId())
                .accountId(userLog.getAccountId())
                .eventType(String.valueOf(MiniGameCallback.EventType.ACTIVE.getEventType()))
                .eventLogId(userLog.getId())
                .createTime(LocalDateTime.now())
                .backStatus(backStatus.getBackStatus())
                .errMsg(null)
                .build());
        return backStatus;
    }
}
