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.GameOceanengineRoleRegisterLogMapper;
import com.zanxiang.game.back.serve.oceanengine.MiniGameCallback;
import com.zanxiang.game.back.serve.oceanengine.OceanengineCallbackException;
import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineRoleRegisterLogDTO;
import com.zanxiang.game.back.serve.pojo.entity.GameBackPolicy;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineBackLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineRoleRegisterLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineUserLog;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.pojo.vo.GameOceanengineRoleRegisterLogVO;
import com.zanxiang.game.back.serve.service.IGameBackPolicyService;
import com.zanxiang.game.back.serve.service.IGameOceanengineBackLogService;
import com.zanxiang.game.back.serve.service.IGameOceanengineRoleRegisterLogService;
import com.zanxiang.game.back.serve.service.IGameOceanengineUserLogService;
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 GameOceanengineRoleRegisterLogServiceImpl extends ServiceImpl<GameOceanengineRoleRegisterLogMapper, GameOceanengineRoleRegisterLog>
        implements IGameOceanengineRoleRegisterLogService {

    @Autowired
    private MiniGameCallback miniGameCallback;
    @Autowired
    private IGameOceanengineUserLogService gameOceanengineUserLogService;
    @Autowired
    private IGameBackPolicyService gameBackPolicyService;
    @Autowired
    private IGameOceanengineBackLogService gameOceanengineBackLogService;
    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
    private IAgentRpc agentRpc;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean callback(GameOceanengineRoleRegisterLog roleRegisterLog) {
        BackStatusEnum backStatus = doCallback(roleRegisterLog);
        return update(new LambdaUpdateWrapper<GameOceanengineRoleRegisterLog>()
                .set(GameOceanengineRoleRegisterLog::getBackStatus, backStatus.getBackStatus())
                .eq(GameOceanengineRoleRegisterLog::getId, roleRegisterLog.getId())
        );
    }

    @Override
    public IPage<GameOceanengineRoleRegisterLogVO> oceanengineUserLogList(GameOceanengineRoleRegisterLogDTO dto) {
        IPage<GameOceanengineRoleRegisterLog> page = page(dto.toPage(), new LambdaQueryWrapper<GameOceanengineRoleRegisterLog>()
                .eq(StringUtils.isNotBlank(dto.getAgentKey()), GameOceanengineRoleRegisterLog::getAgentKey, dto.getAgentKey())
                .ge(dto.getRegisterTimeBegin() != null, GameOceanengineRoleRegisterLog::getRegisterTime, dto.getRegisterTimeBegin() == null ? null : LocalDateTime.of(dto.getRegisterTimeBegin(), LocalTime.MIDNIGHT))
                .le(dto.getRegisterTimeEnd() != null, GameOceanengineRoleRegisterLog::getRegisterTime, dto.getRegisterTimeEnd() == null ? null : LocalDateTime.of(dto.getRegisterTimeEnd(), LocalTime.MAX))
                .eq(null != dto.getGameId(), GameOceanengineRoleRegisterLog::getGameId, dto.getGameId())
                .eq(null != dto.getAccountId(), GameOceanengineRoleRegisterLog::getAccountId, dto.getAccountId())
                .eq(StringUtils.isNotBlank(dto.getAppId()), GameOceanengineRoleRegisterLog::getAppId, dto.getAppId())
                .eq(StringUtils.isNotBlank(dto.getOpenId()), GameOceanengineRoleRegisterLog::getOpenId, dto.getOpenId())
                .eq(null != dto.getBackStatus(), GameOceanengineRoleRegisterLog::getBackStatus, dto.getBackStatus())
                .eq(StringUtils.isNotBlank(dto.getRoleName()), GameOceanengineRoleRegisterLog::getRoleName, dto.getRoleName())
                .orderByDesc(GameOceanengineRoleRegisterLog::getCreateTime)
        );
        IPage<GameOceanengineRoleRegisterLogVO> 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<GameOceanengineRoleRegisterLogVO> toVOBatch(List<GameOceanengineRoleRegisterLog> logList) {
        if (CollectionUtils.isEmpty(logList)) {
            return Collections.emptyList();
        }
        Set<String> agentKeys = logList.stream().map(GameOceanengineRoleRegisterLog::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 -> {
            GameOceanengineRoleRegisterLogVO vo = BeanUtil.copy(log, GameOceanengineRoleRegisterLogVO.class);
            if (StringUtils.isNotBlank(log.getAgentKey())) {
                AgentRpcVO agent = agentMap.get(log.getAgentKey());
                if (agent != null) {
                    vo.setAgentName(agent.getAgentName());
                }
            }
            return vo;
        }).collect(Collectors.toList());
    }

    @Override
    public boolean oceanengineUserReport(List<Long> ids) {
        listByIds(ids).forEach(this::callback);
        return true;
    }

    private BackStatusEnum doCallback(GameOceanengineRoleRegisterLog roleRegisterLog) {
        GameOceanengineUserLog userLog = gameOceanengineUserLogService.getOne(new LambdaQueryWrapper<GameOceanengineUserLog>()
                .eq(GameOceanengineUserLog::getGameId, roleRegisterLog.getGameId())
                .eq(GameOceanengineUserLog::getAppId, roleRegisterLog.getAppId())
                .eq(GameOceanengineUserLog::getOpenId, roleRegisterLog.getOpenId())
                .eq(GameOceanengineUserLog::getAccountId, roleRegisterLog.getAccountId())
                .orderByDesc(GameOceanengineUserLog::getCreateTime)
                .last("limit 1")
        );
        if (userLog == null) {
            gameOceanengineBackLogService.save(GameOceanengineBackLog.builder()
                    .appId(roleRegisterLog.getAppId())
                    .openId(roleRegisterLog.getOpenId())
                    .unionId(roleRegisterLog.getUnionId())
                    .gameId(roleRegisterLog.getGameId())
                    .accountId(roleRegisterLog.getAccountId())
                    .clueToken("")
                    .eventType(String.valueOf(MiniGameCallback.EventType.ACTIVE_REGISTER.getEventType()))
                    .eventLogId(roleRegisterLog.getId())
                    .createTime(LocalDateTime.now())
                    .backStatus(BackStatusEnum.FAILED.getBackStatus())
                    .errMsg("找不到用户注册信息")
                    .build());
            return BackStatusEnum.FAILED;
        }

        //判断创角是否已回传
        if (gameOceanengineBackLogService.count(new LambdaQueryWrapper<GameOceanengineBackLog>()
                .eq(GameOceanengineBackLog::getGameId, userLog.getGameId())
                .eq(GameOceanengineBackLog::getAppId, userLog.getAppId())
                .eq(GameOceanengineBackLog::getOpenId, userLog.getOpenId())
                .eq(GameOceanengineBackLog::getAccountId, userLog.getAccountId())
                .eq(GameOceanengineBackLog::getEventType, MiniGameCallback.EventType.ACTIVE_REGISTER.getEventType())
                .eq(GameOceanengineBackLog::getBackStatus, BackStatusEnum.SUCCESS.getBackStatus())
        ) > 0) {
            //创角已回传
            return BackStatusEnum.NO;
        }

        //回传策略等级判断
        if (roleRegisterLog.getBackPolicyId() != null) {
            GameBackPolicy gameBackPolicy = gameBackPolicyService.getById(roleRegisterLog.getBackPolicyId());
            if (gameBackPolicy.getRoleLevelMin() != null && roleRegisterLog.getRoleLevel() != null
                    && roleRegisterLog.getRoleLevel() < gameBackPolicy.getRoleLevelMin()) {
                return BackStatusEnum.NO;
            }
        }

        // 回传用户激活
        if (Objects.equals(BackStatusEnum.NO.getBackStatus(), userLog.getBackStatus())) {
            gameOceanengineUserLogService.callback(userLog, true);
        }

        //创角回传
        MiniGameCallback.MiniGameCallbackRequest request = MiniGameCallback.MiniGameCallbackRequest.builder()
                .clue_token(userLog.getClueToken())
                .open_id(roleRegisterLog.getOpenId())
                .union_id(roleRegisterLog.getUnionId())
                .event_type(String.valueOf(MiniGameCallback.EventType.ACTIVE_REGISTER.getEventType()))
                .build();
        BackStatusEnum backStatus = BackStatusEnum.SUCCESS;
        String errMsg = null;
        try {
            miniGameCallback.doCallback(userLog.getAccountReportUrl(), userLog.getAccountReportToken(), request);
        } catch (OceanengineCallbackException e) {
            log.error(e.getMessage(), e);
            backStatus = BackStatusEnum.FAILED;
            errMsg = e.getMsg();
        } catch (Exception e) {
            log.error(e.getMessage(), e);
            backStatus = BackStatusEnum.FAILED;
            errMsg = "系统异常：" + e.getMessage();
        }
        gameOceanengineBackLogService.save(GameOceanengineBackLog.builder()
                .appId(roleRegisterLog.getAppId())
                .openId(roleRegisterLog.getOpenId())
                .unionId(roleRegisterLog.getUnionId())
                .gameId(roleRegisterLog.getGameId())
                .accountId(roleRegisterLog.getAccountId())
                .clueToken(userLog.getClueToken())
                .eventType(request.getEvent_type())
                .eventLogId(roleRegisterLog.getId())
                .createTime(LocalDateTime.now())
                .backStatus(backStatus.getBackStatus())
                .errMsg(errMsg)
                .build());
        return backStatus;
    }
}
