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

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.game.back.serve.dao.mapper.GameOceanengineAppCallbackMapper;
import com.zanxiang.game.back.serve.pojo.dto.GameOceanengineAppCallbackDTO;
import com.zanxiang.game.back.serve.pojo.entity.GameOceanengineAppCallback;
import com.zanxiang.game.back.serve.service.IGameOceanengineAppCallbackService;
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.DateUtil;
import com.zanxiang.module.util.JsonUtil;
import com.zanxiang.module.util.bean.BeanUtil;
import com.zanxiang.module.util.encryption.Md5Util;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.kafka.clients.producer.KafkaProducer;
import org.apache.kafka.clients.producer.ProducerRecord;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;

@Slf4j
@Service
public class GameOceanengineAppCallbackServiceImpl extends ServiceImpl<GameOceanengineAppCallbackMapper, GameOceanengineAppCallback>
implements IGameOceanengineAppCallbackService {

    @Value("${spring.kafka.oceanengineAppCallbackTopic}")
    private String oceanengineAppCallbackTopic;
    @Autowired
    private KafkaProducer<String, String> kafkaProducer;
    @DubboReference(providedBy = ServerInfo.SERVER_DUBBO_NAME)
    private IAgentRpc agentRpc;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public boolean callback(GameOceanengineAppCallbackDTO dto) {
        AgentRpcVO agent = agentRpc.getByByteAccountId(dto.getAdvertiserId()).getData();
        if (agent == null) {
            log.error("头条检测链接数据找不到渠道：{}", JsonUtil.toString(dto));
        }
        GameOceanengineAppCallback appCallback = BeanUtil.copy(dto, GameOceanengineAppCallback.class);
        if (agent != null) {
            appCallback.setAgentKey(agent.getAgentKey());
            appCallback.setGameId(agent.getGameId());
        } else {
            appCallback.setAgentKey("-");
            appCallback.setGameId(-1L);
        }
        appCallback.setDay(dto.getTs() == null || dto.getTs() < 1000 ? LocalDate.now() : DateUtil.milliToLocalDateTime(dto.getTs()).toLocalDate());
        save(appCallback);
        try {
            kafkaProducer.send(new ProducerRecord<>(oceanengineAppCallbackTopic, dto.getAdvertiserId().toString(), JsonUtil.toString(appCallback)));
        } catch (Exception e) {
            log.error(e.getMessage(), e);
        }
        return true;
    }

    @Override
    public GameOceanengineAppCallback getUserCallback(Long gameId, String oaid, String mac, String idfa, String caid, String ip, LocalDateTime regTime) {
        LambdaQueryWrapper<GameOceanengineAppCallback> qw = new LambdaQueryWrapper<GameOceanengineAppCallback>()
                .lt(GameOceanengineAppCallback::getTs, DateUtil.localDateTimeToMilli(regTime))
                .eq(GameOceanengineAppCallback::getGameId, gameId)
                .orderByDesc(GameOceanengineAppCallback::getTs)
                .last("limit 1");

        qw.and(and -> {
            if(StringUtils.isNoneBlank(oaid)) {
                and.or().eq(GameOceanengineAppCallback::getOaid, oaid)
                        .or().eq(GameOceanengineAppCallback::getOaidMd5, Md5Util.encrypt32(oaid).toLowerCase());
            }
            if (StringUtils.isNoneBlank(idfa)) {
                and.or().eq(GameOceanengineAppCallback::getIdfaMd5, Md5Util.encrypt32(idfa).toLowerCase())
                        .or().eq(GameOceanengineAppCallback::getIdfa, idfa);
            }
            and.or().eq(StringUtils.isNoneBlank(mac), GameOceanengineAppCallback::getMac, StringUtils.isBlank(oaid) ? null : Md5Util.encrypt32(mac.replaceAll(":","").toUpperCase()).toLowerCase())
                    .or().and(StringUtils.isNoneBlank(ip), tmp -> {
                        tmp.ge(GameOceanengineAppCallback::getTs, DateUtil.localDateTimeToMilli(regTime.plusDays(2)))
                                .eq(GameOceanengineAppCallback::getIp, ip);
                    });
        });
        return getOne(qw);
    }
}
