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.TtAppOrderBackQueryRpcDTO;
import com.zanxiang.game.back.base.pojo.dto.TtOrderAppRpcDTO;
import com.zanxiang.game.back.base.pojo.dto.TtRoleRegisterAppRpcDTO;
import com.zanxiang.game.back.base.pojo.dto.TtUserActiveAppRpcDTO;
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.ITtAppBackRpc;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppOrderLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppOrderSplitLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppRoleRegisterLog;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppUserLog;
import com.zanxiang.game.back.serve.pojo.enums.BackStatusEnum;
import com.zanxiang.game.back.serve.service.*;
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 TtAppBackRpcImpl implements ITtAppBackRpc {

    @Autowired
    private IGameOceanengineAppUserLogService gameOceanengineAppUserLogService;

    @Autowired
    private IGameOceanengineAppRoleRegisterLogService gameOceanengineAppRoleRegisterLogService;

    @Autowired
    private IGameOceanengineAppOrderLogService gameOceanengineAppOrderLogService;

    @Autowired
    private IGameOceanengineAppOrderSplitLogService gameOceanengineAppOrderSplitLogService;

    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    @Autowired
    private IGameOceanengineAppCallbackXgltService gameOceanengineAppCallbackXgltService;

    @Override
    public ResultVO<Boolean> userActiveReport(TtUserActiveAppRpcDTO 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("找不到用户唯一标识");
        }

        GameOceanengineAppUserLog userLog = GameOceanengineAppUserLog.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.getAccountReport().getAccountId())
                .agentKey(dto.getAgentKey())
                .activeTime(dto.getActiveTime())
                .ip(dto.getRegIp())
                .backStatus(BackStatusEnum.NO.getBackStatus())
                .createTime(LocalDateTime.now())
                .build();

        //设置星广联投回传参数
        String xgltCallback = gameOceanengineAppCallbackXgltService.getCallBackParamByUser(userLog);
        if (StringUtils.isNotBlank(xgltCallback)) {
            userLog.setXgltCallback(xgltCallback);
        }

        gameOceanengineAppUserLogService.save(userLog);
        return ResultVO.ok(gameOceanengineAppUserLogService.callback(userLog, Boolean.FALSE));
    }

    @Override
    public ResultVO<Boolean> orderReport(TtOrderAppRpcDTO dto) {
        if (Objects.equals(OrderStatusEnum.SUCCESS_PAY.getValue(), dto.getOrderStatus())) {
            log.error("头条 APP订单回传收到：{}。", JsonUtil.toString(dto));
        } else {
            log.error("头条 APP订单回传收到：{}。订单未支付，直接过滤", 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 + ":TtAppOrderBack:" + dto.getGameId() + ":" + dto.getOrderId();
        redisTemplate.opsForValue().set(lockKey, dto.getOrderId(), 2L, TimeUnit.MINUTES);
        try {
            GameOceanengineAppOrderLog orderLog = GameOceanengineAppOrderLog.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.getAccountReport().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())
                    .build();
            boolean isFirstOrder = gameOceanengineAppOrderLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
                    .eq(GameOceanengineAppOrderLog::getGameId, orderLog.getGameId())
                    .eq(GameOceanengineAppOrderLog::getUserId, orderLog.getUserId())
                    .eq(GameOceanengineAppOrderLog::getAccountId, orderLog.getAccountId())
                    .eq(GameOceanengineAppOrderLog::getOrderStatus, OrderStatusEnum.SUCCESS_PAY.getValue())
                    .last("limit 1")
            ) == null;
            orderLog.setIsFirstOrder(isFirstOrder);
            gameOceanengineAppOrderLogService.save(orderLog);
            return ResultVO.ok(gameOceanengineAppOrderLogService.callback(orderLog));
        } finally {
            redisTemplate.delete(lockKey);
        }
    }

    @Override
    public ResultVO<Boolean> roleRegisterReport(TtRoleRegisterAppRpcDTO 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("找不到用户唯一标识");
        }
        GameOceanengineAppRoleRegisterLog roleRegisterLog;
        GameOceanengineAppRoleRegisterLog oldRole = gameOceanengineAppRoleRegisterLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppRoleRegisterLog>()
                .eq(GameOceanengineAppRoleRegisterLog::getGameId, dto.getGameId())
                .eq(GameOceanengineAppRoleRegisterLog::getUserId, dto.getUserId())
                .eq(GameOceanengineAppRoleRegisterLog::getRoleId, dto.getRoleId())
                .last("limit 1")
        );
        if (oldRole != null) {
            roleRegisterLog = oldRole;
            if (dto.getRoleLevel() != null && (oldRole.getRoleLevel() == null || oldRole.getRoleLevel() < dto.getRoleLevel())) {
                gameOceanengineAppRoleRegisterLogService.update(new LambdaUpdateWrapper<GameOceanengineAppRoleRegisterLog>()
                        .set(GameOceanengineAppRoleRegisterLog::getRoleLevel, dto.getRoleLevel())
                        .set(GameOceanengineAppRoleRegisterLog::getRoleName, dto.getRoleName())
                        .eq(GameOceanengineAppRoleRegisterLog::getId, oldRole.getId())
                );
            }
            if (Objects.equals(oldRole.getBackStatus(), BackStatusEnum.SUCCESS.getBackStatus())) {
                // 创角已回传。不重复传了
                return ResultVO.ok(true);
            }
        } else {
            roleRegisterLog = GameOceanengineAppRoleRegisterLog.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.getAccountReport().getAccountId())
                    .agentKey(dto.getAgentKey())
                    .roleId(dto.getRoleId())
                    .roleName(dto.getRoleName())
                    .roleLevel(dto.getRoleLevel())
                    .registerTime(dto.getRegisterTime())
                    .backStatus(BackStatusEnum.NO.getBackStatus())
                    .createTime(LocalDateTime.now())
                    .build();
            gameOceanengineAppRoleRegisterLogService.save(roleRegisterLog);
        }
        return ResultVO.ok(gameOceanengineAppRoleRegisterLogService.callback(roleRegisterLog));
    }

    @Override
    public ResultVO<OrderBackQueryRpcVO> orderBackQuery(TtAppOrderBackQueryRpcDTO dto) {
        log.error("头条APP订单回传结果查询：{}", JsonUtil.toString(dto));

        GameOceanengineAppOrderLog 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 = gameOceanengineAppOrderSplitLogService.list(new LambdaQueryWrapper<GameOceanengineAppOrderSplitLog>()
                .eq(GameOceanengineAppOrderSplitLog::getOrderNo, orderLog.getOrderNo())
                .orderByAsc(GameOceanengineAppOrderSplitLog::getBackIndex)
        ).stream().map(GameOceanengineAppOrderSplitLog::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();

        //星广联投回传 -> 付费
        try {
            if (Objects.equals(orderBackQueryRpcVO.getDoBack(), Boolean.TRUE)) {
                gameOceanengineAppCallbackXgltService.orderPayBack(orderLog, orderBackQueryRpcVO);
            }
        } catch (Exception ignored) {
        }

        return ResultVO.ok(orderBackQueryRpcVO);
    }

    private GameOceanengineAppOrderLog queryOrder(TtAppOrderBackQueryRpcDTO dto) {
        String lockKey = com.zanxiang.game.back.base.ServerInfo.SERVER_NAME + ":TtAppOrderBack:" + 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 gameOceanengineAppOrderLogService.getOne(new LambdaQueryWrapper<GameOceanengineAppOrderLog>()
                .eq(GameOceanengineAppOrderLog::getOrderNo, dto.getOrderId())
                .eq(GameOceanengineAppOrderLog::getGameId, dto.getGameId())
                .eq(GameOceanengineAppOrderLog::getAgentKey, dto.getAgentKey())
                .eq(GameOceanengineAppOrderLog::getUserId, dto.getUserId())
        );
    }
}
