package com.zanxiang.game.module.manage.service.impl;

import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.zanxiang.game.module.manage.enums.CpSendRoleResultEnum;
import com.zanxiang.game.module.manage.pojo.dto.CpSendMsgResultDTO;
import com.zanxiang.game.module.manage.pojo.dto.GameDTO;
import com.zanxiang.game.module.manage.service.*;
import com.zanxiang.game.module.mybatis.entity.GameSupper;
import com.zanxiang.game.module.mybatis.entity.GameUserRole;
import com.zanxiang.game.module.mybatis.entity.PushMsgSendLog;
import com.zanxiang.game.module.mybatis.entity.PushMsgSendResult;
import com.zanxiang.game.module.mybatis.mapper.PushMsgSendLogMapper;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.support.TransactionTemplate;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

/**
 * @author : lingfeng
 * @time : 2024-05-27
 * @description : 消息推送日志
 */
@Slf4j
@Service
public class PushMsgSendLogServiceImpl extends ServiceImpl<PushMsgSendLogMapper, PushMsgSendLog> implements IPushMsgSendLogService {

    @Autowired
    private IGameService gameService;

    @Autowired
    private IGameSupperService gameSupperService;

    @Autowired
    private TransactionTemplate transactionTemplate;

    @Autowired
    private ICpSendMsgLogService cpSendMsgLogService;

    @Autowired
    private IPushMsgSendResultService pushMsgSendResultService;

    @Override
    public void pushMsg(Long gameId, Long strategyId, String text, List<GameUserRole> gameUserRoleList) {
        //查询游戏
        GameDTO gameDTO = gameService.getById(gameId);
        GameSupper gameSupper = gameSupperService.getById(gameDTO.getSuperGameId());
        //消息id
        String msgId = UUID.randomUUID().toString().replace("-", "");
        //保存发送记录
        PushMsgSendLog pushMsgSendLog = this.transform(msgId, gameId, strategyId, text, gameUserRoleList.size());
        super.save(pushMsgSendLog);
        //角色信息按区服分组
        Map<String, List<GameUserRole>> serverIdRoleMap = gameUserRoleList.stream()
                .collect(Collectors.groupingBy(GameUserRole::getServerId));
        serverIdRoleMap.forEach((serverId, roleList) -> {
            List<String> serverRoleIdList = roleList.stream().map(GameUserRole::getRoleId).collect(Collectors.toList());
            try {
                CpSendMsgResultDTO result = cpSendMsgLogService.cpSendMsgApi(gameSupper, msgId, serverId, text, serverRoleIdList);
                this.resultHandle(pushMsgSendLog, result, serverId, serverRoleIdList);
            } catch (Exception e) {
                log.error("消息推送, CP消息发送API调用异常, gameId : {}, strategyId : {}, serverId : {}, roleList : {}, e : {}",
                        gameId, strategyId, serverId, roleList, e.getMessage(), e);
            }
        });
    }

    private PushMsgSendLog transform(String msgId, Long gameId, Long strategyId, String text, Integer roleCount) {
        return PushMsgSendLog.builder()
                .msgId(msgId)
                .gameId(gameId)
                .strategyId(strategyId)
                .text(text)
                .roleCount(roleCount)
                .successCount(0L)
                .failCount(0L)
                .createTime(LocalDateTime.now())
                .updateTime(LocalDateTime.now())
                .build();
    }

    private void resultHandle(PushMsgSendLog pushMsgSendLog, CpSendMsgResultDTO result, String serverId, List<String> roleList) {
        //结果列表
        List<PushMsgSendResult> resultList = new ArrayList<>();
        roleList.forEach(roleId -> {
            //状态判断
            CpSendRoleResultEnum resultEnum = result.getFailList().contains(roleId) ?
                    CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_FAIL : CpSendRoleResultEnum.CP_SEND_ROLE_RESULT_SUCCESS;
            resultList.add(this.transform(pushMsgSendLog, resultEnum.getValue(), serverId, roleId));
        });
        //在同一个事物中进行表更新
        transactionTemplate.execute(status -> {
            pushMsgSendResultService.saveBatch(resultList);
            super.update(new LambdaUpdateWrapper<PushMsgSendLog>()
                    .setSql("success_count=success_count+" + result.getSucessCount())
                    .setSql("fail_count=fail_count+" + result.getFailList().size())
                    .set(PushMsgSendLog::getUpdateTime, LocalDateTime.now())
                    .eq(PushMsgSendLog::getMsgId, pushMsgSendLog.getMsgId())
            );
            return Boolean.TRUE;
        });
    }

    private PushMsgSendResult transform(PushMsgSendLog pushMsgSendLog, String sendStatus, String serverId, String roleId) {
        return PushMsgSendResult.builder()
                .msgId(pushMsgSendLog.getMsgId())
                .gameId(pushMsgSendLog.getGameId())
                .strategyId(pushMsgSendLog.getStrategyId())
                .serverId(serverId)
                .roleId(roleId)
                .sendStatus(sendStatus)
                .createTime(LocalDateTime.now())
                .build();
    }
}
