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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.zanxiang.game.back.base.pojo.dto.TencentAppOrderBackQueryRpcDTO;
import com.zanxiang.game.back.base.pojo.dto.TencentOrderAppRpcDTO;
import com.zanxiang.game.back.base.pojo.dto.TencentRoleRegisterAppRpcDTO;
import com.zanxiang.game.back.base.pojo.dto.TencentUserAppRpcDTO;
import com.zanxiang.game.back.base.pojo.enums.OrderStatusEnum;
import com.zanxiang.game.back.base.pojo.vo.OrderBackQueryRpcVO;
import com.zanxiang.game.back.base.rpc.ITencentAppBackRpc;
import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrder;
import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppOrderSplitLog;
import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppRoleRegister;
import com.zanxiang.game.back.serve.pojo.entity.GameTencentAppUser;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.service.IGameTencentAppOrderService;
import com.zanxiang.game.back.serve.service.IGameTencentAppOrderSplitLogService;
import com.zanxiang.game.back.serve.service.IGameTencentAppRoleRegisterService;
import com.zanxiang.game.back.serve.service.IGameTencentAppUserService;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.pojo.ResultVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;

import java.time.LocalDateTime;
import java.util.Collections;
import java.util.List;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@DubboService
public class TencentAppBackRpcImpl implements ITencentAppBackRpc {

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private IGameTencentAppUserService gameTencentAppUserService;

    @Autowired
    private IGameTencentAppOrderService gameTencentAppOrderService;

    @Autowired
    private IGameTencentAppOrderSplitLogService gameTencentAppOrderSplitLogService;

    @Autowired
    private IGameTencentAppRoleRegisterService gameTencentAppRoleRegisterService;

    @Override
    public ResultVO<Boolean> backUser(TencentUserAppRpcDTO dto) {
        log.error("腾讯 APP用户回传收到：{}", JsonUtil.toString(dto));
        if (StringUtils.isBlank(dto.getMac())) {
            dto.setMac("");
        }
        if (StringUtils.isBlank(dto.getImei())) {
            dto.setImei("");
        }
        if (StringUtils.isBlank(dto.getOaid())) {
            dto.setOaid("");
        }
        if (StringUtils.isBlank(dto.getAndroidId())) {
            dto.setAndroidId("");
        }
        if (StringUtils.isBlank(dto.getIdfa())) {
            dto.setIdfa("");
        }
        if (StringUtils.isBlank(dto.getCaid())) {
            dto.setCaid("");
        }
        if (StringUtils.isBlank(dto.getUserId()) || (StringUtils.isBlank(dto.getImei())
                && StringUtils.isBlank(dto.getOaid())
                && StringUtils.isBlank(dto.getAndroidId())
                && StringUtils.isBlank(dto.getIdfa())
                && StringUtils.isBlank(dto.getCaid()))) {
            return ResultVO.fail("找不到用户唯一标识");
        }
        GameTencentAppUser userLog = GameTencentAppUser.builder()
                .userId(dto.getUserId())
                .mac(dto.getMac())
                .imei(dto.getImei())
                .oaid(dto.getOaid())
                .androidId(dto.getAndroidId())
                .idfa(dto.getIdfa())
                .caid(dto.getCaid())
                .gameId(dto.getGameId())
                .accountId(dto.getAccountId())
                .agentKey(dto.getAgentKey())
                .activeTime(dto.getActiveTime())
                .ip(dto.getRegIp())
                .backStatus(BackStatusEnum.NO.getBackStatus())
                .createTime(LocalDateTime.now())
                .userActionSetId(dto.getUserActionSetId())
                .build();
        gameTencentAppUserService.save(userLog);
        return ResultVO.ok(gameTencentAppUserService.userBack(userLog, Boolean.FALSE));
    }

    @Override
    public ResultVO<Boolean> backRoleRegister(TencentRoleRegisterAppRpcDTO dto) {
        log.error("腾讯 APP创角回传收到：{}", JsonUtil.toString(dto));
        if (StringUtils.isBlank(dto.getMac())) {
            dto.setMac("");
        }
        if (StringUtils.isBlank(dto.getImei())) {
            dto.setImei("");
        }
        if (StringUtils.isBlank(dto.getOaid())) {
            dto.setOaid("");
        }
        if (StringUtils.isBlank(dto.getAndroidId())) {
            dto.setAndroidId("");
        }
        if (StringUtils.isBlank(dto.getIdfa())) {
            dto.setIdfa("");
        }
        if (StringUtils.isBlank(dto.getCaid())) {
            dto.setCaid("");
        }
        if (StringUtils.isBlank(dto.getUserId()) || (StringUtils.isBlank(dto.getImei())
                && StringUtils.isBlank(dto.getOaid())
                && StringUtils.isBlank(dto.getAndroidId())
                && StringUtils.isBlank(dto.getIdfa())
                && StringUtils.isBlank(dto.getCaid()))) {
            return ResultVO.fail("找不到用户唯一标识");
        }
        GameTencentAppRoleRegister roleRegisterLog;
        GameTencentAppRoleRegister oldRole = gameTencentAppRoleRegisterService.getOne(new LambdaQueryWrapper<GameTencentAppRoleRegister>()
                .eq(GameTencentAppRoleRegister::getGameId, dto.getGameId())
                .eq(GameTencentAppRoleRegister::getUserId, dto.getUserId())
                .eq(GameTencentAppRoleRegister::getRoleId, dto.getRoleId())
                .last("limit 1")
        );
        if (oldRole != null) {
            roleRegisterLog = oldRole;
            if (dto.getRoleLevel() != null && (oldRole.getRoleLevel() == null || oldRole.getRoleLevel() < dto.getRoleLevel())) {
                gameTencentAppRoleRegisterService.update(new LambdaUpdateWrapper<GameTencentAppRoleRegister>()
                        .set(GameTencentAppRoleRegister::getRoleLevel, dto.getRoleLevel())
                        .set(GameTencentAppRoleRegister::getRoleName, dto.getRoleName())
                        .eq(GameTencentAppRoleRegister::getId, oldRole.getId())
                );
            }
            if (Objects.equals(oldRole.getBackStatus(), BackStatusEnum.SUCCESS.getBackStatus())) {
                // 创角已回传。不重复传了
                return ResultVO.ok(true);
            }
        } else {
            roleRegisterLog = GameTencentAppRoleRegister.builder()
                    .backPolicyId(dto.getBackPolicyId())
                    .userId(dto.getUserId())
                    .mac(dto.getMac())
                    .imei(dto.getImei())
                    .oaid(dto.getOaid())
                    .androidId(dto.getAndroidId())
                    .idfa(dto.getIdfa())
                    .caid(dto.getCaid())
                    .gameId(dto.getGameId())
                    .accountId(dto.getAccountId())
                    .agentKey(dto.getAgentKey())
                    .roleId(dto.getRoleId())
                    .roleName(dto.getRoleName())
                    .roleLevel(dto.getRoleLevel())
                    .registerTime(dto.getRegisterTime())
                    .backStatus(BackStatusEnum.NO.getBackStatus())
                    .createTime(LocalDateTime.now())
                    .userActionSetId(dto.getUserActionSetId())
                    .build();
            gameTencentAppRoleRegisterService.save(roleRegisterLog);
        }
        return ResultVO.ok(gameTencentAppRoleRegisterService.callback(roleRegisterLog));
    }

    @Override
    public ResultVO<Boolean> backOrder(TencentOrderAppRpcDTO dto) {
        if (Objects.equals(OrderStatusEnum.SUCCESS_PAY.getValue(), dto.getOrderStatus())) {
            log.error("腾讯 APP订单回传收到：{}。", JsonUtil.toString(dto));
        } else {
            log.error("腾讯H5订单回传收到：{}。订单未支付，直接过滤", JsonUtil.toString(dto));
            return ResultVO.ok(true);
        }
        if (StringUtils.isBlank(dto.getMac())) {
            dto.setMac("");
        }
        if (StringUtils.isBlank(dto.getImei())) {
            dto.setImei("");
        }
        if (StringUtils.isBlank(dto.getOaid())) {
            dto.setOaid("");
        }
        if (StringUtils.isBlank(dto.getAndroidId())) {
            dto.setAndroidId("");
        }
        if (StringUtils.isBlank(dto.getIdfa())) {
            dto.setIdfa("");
        }
        if (StringUtils.isBlank(dto.getCaid())) {
            dto.setCaid("");
        }
        if (StringUtils.isBlank(dto.getUserId()) || (StringUtils.isBlank(dto.getImei())
                && StringUtils.isBlank(dto.getOaid())
                && StringUtils.isBlank(dto.getAndroidId())
                && StringUtils.isBlank(dto.getIdfa())
                && StringUtils.isBlank(dto.getCaid()))) {
            return ResultVO.fail("找不到用户唯一标识");
        }
        // 此处加锁防止 cp 方调用过快，导致查询回传结果时判断逻辑没走完
        String lockKey = com.zanxiang.game.back.base.ServerInfo.SERVER_NAME + ":TencentAppOrderBack:" + dto.getGameId() + ":" + dto.getOrderId();
        redisTemplate.opsForValue().set(lockKey, dto.getOrderId(), 2L, TimeUnit.MINUTES);
        try {
            GameTencentAppOrder orderLog = GameTencentAppOrder.builder()
                    .userId(dto.getUserId())
                    .mac(dto.getMac())
                    .imei(dto.getImei())
                    .oaid(dto.getOaid())
                    .androidId(dto.getAndroidId())
                    .idfa(dto.getIdfa())
                    .caid(dto.getCaid())
                    .gameId(dto.getGameId())
                    .backPolicyId(dto.getBackPolicyId())
                    .accountId(dto.getAccountId())
                    .agentKey(dto.getAgentKey())
                    .regTime(dto.getRegTime())
                    .orderNo(dto.getOrderId())
                    .amount(dto.getRechargeMoney())
                    .orderStatus(dto.getOrderStatus())
                    .createTime(dto.getCreateTime())
                    .payTime(dto.getPayTime())
                    .backStatus(BackStatusEnum.NO.getBackStatus())
                    .roleId(dto.getRoleId())
                    .roleName(dto.getRoleName())
                    .userActionSetId(dto.getUserActionSetId())
                    .build();
            boolean isFirstOrder = gameTencentAppOrderService.getOne(new LambdaQueryWrapper<GameTencentAppOrder>()
                    .eq(GameTencentAppOrder::getGameId, orderLog.getGameId())
                    .eq(GameTencentAppOrder::getUserId, orderLog.getUserId())
                    .eq(GameTencentAppOrder::getAccountId, orderLog.getAccountId())
                    .eq(GameTencentAppOrder::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
                    .last("limit 1")
            ) == null;
            orderLog.setIsFirstOrder(isFirstOrder);
            gameTencentAppOrderService.save(orderLog);
            return ResultVO.ok(gameTencentAppOrderService.callback(orderLog));
        } finally {
            redisTemplate.delete(lockKey);
        }
    }

    @Override
    public ResultVO<OrderBackQueryRpcVO> orderBackQuery(TencentAppOrderBackQueryRpcDTO dto) {
        log.error("腾讯APP订单回传结果查询：{}", JsonUtil.toString(dto));
        GameTencentAppOrder orderLog = queryOrder(dto);
        if (orderLog == null) {
            try {
                Thread.sleep(15 * 1000L);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
            orderLog = queryOrder(dto);
        }
        if (orderLog == null) {
            return ResultVO.ok(OrderBackQueryRpcVO.builder()
                    .doBack(Boolean.FALSE)
                    .backMsg("回传异常，找不到订单：" + dto.getOrderId())
                    .build());
        }
        List<Long> splitMoney = gameTencentAppOrderSplitLogService.list(new LambdaQueryWrapper<GameTencentAppOrderSplitLog>()
                .eq(GameTencentAppOrderSplitLog::getOrderNo, orderLog.getOrderNo())
                .orderByAsc(GameTencentAppOrderSplitLog::getBackIndex)
        ).stream().map(GameTencentAppOrderSplitLog::getSplitMoney).collect(Collectors.toList());
        OrderBackQueryRpcVO orderBackQueryRpcVO = OrderBackQueryRpcVO.builder()
                .doBack(BackStatusEnum.getByValue(orderLog.getBackStatus()) == BackStatusEnum.SUCCESS)
                .backMoney(CollectionUtils.isEmpty(splitMoney) ? Collections.singletonList(orderLog.getBackMoney()) : splitMoney)
                .backMsg(orderLog.getBackMsg())
                .build();
        return ResultVO.ok(orderBackQueryRpcVO);
    }

    private GameTencentAppOrder queryOrder(TencentAppOrderBackQueryRpcDTO dto) {
        String lockKey = com.zanxiang.game.back.base.ServerInfo.SERVER_NAME + ":TencentAppOrderBack:" + dto.getGameId() + ":" + dto.getOrderId();
        int maxCount = 0;
        while (true) {
            if (redisTemplate.opsForValue().get(lockKey) == null) {
                break;
            }
            if (maxCount++ >= 120 / 10) {
                break;
            }
            try {
                Thread.sleep(10 * 1000L);
            } catch (Exception e) {
                log.error(e.getMessage(), e);
            }
        }
        return gameTencentAppOrderService.getOne(new LambdaQueryWrapper<GameTencentAppOrder>()
                .eq(GameTencentAppOrder::getOrderNo, dto.getOrderId())
                .eq(GameTencentAppOrder::getGameId, dto.getGameId())
                .eq(GameTencentAppOrder::getAgentKey, dto.getAgentKey())
                .eq(GameTencentAppOrder::getUserId, dto.getUserId())
        );
    }
}
