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

import com.zanxiang.erp.base.ErpServer;
import com.zanxiang.erp.base.rpc.IDingTalkMsgRpc;
import com.zanxiang.game.data.serve.pojo.entity.AdsMonitorAlarm;
import com.zanxiang.game.data.serve.pojo.vo.GameMonitorAlarmVO;
import com.zanxiang.game.data.serve.service.IGameMonitorAlarmService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.nutz.dao.Chain;
import org.nutz.dao.Cnd;
import org.nutz.dao.Dao;
import org.nutz.dao.Sqls;
import org.nutz.dao.sql.Criteria;
import org.nutz.dao.sql.Sql;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author tianhua
 * @version 1.0
 * @description: TODO
 * @date 2023/12/13 16:24
 */
@Service
@Slf4j
public class GameMonitorAlarmServiceImpl implements IGameMonitorAlarmService {

    @Autowired
    private Dao dao;

    @DubboReference(providedBy = ErpServer.SERVER_DUBBO_NAME)
    private IDingTalkMsgRpc dingTalkMsgRpc;

    @Transactional(rollbackFor = Exception.class)
    public boolean sendMsgToUser() {
        //数据库查表
        log.info("查询告警信息");
        Sql sql = Sqls.create(getMonitorAlarmInfoSql());
        sql.setCallback(Sqls.callback.entities());
        sql.setEntity(dao.getEntity(GameMonitorAlarmVO.class));
        dao.execute(sql);
        //结果
        log.info("查询告警信息结束");
        try {
            List<GameMonitorAlarmVO> list1 = sql.getList(GameMonitorAlarmVO.class);
            log.info("告警信息：{}", list1);
            if (CollectionUtils.isEmpty(list1)) {
                log.info("没有告警信息");
                return true;
            }
            //用type==4进行分组
            Map<Boolean, List<GameMonitorAlarmVO>> partitionedMap = list1.stream()
                    .collect(Collectors.partitioningBy(vo -> vo.getConfigType() == 4));
            List<GameMonitorAlarmVO> listWithType4 = partitionedMap.get(true);

            //如果有type==4的，则每个投手的消息整合为1条告警
            if (CollectionUtils.isNotEmpty(listWithType4)) {
                Map<String, List<GameMonitorAlarmVO>> map = new HashMap<>();
                for (GameMonitorAlarmVO vo : listWithType4) {
                    String[] pitcherIds = vo.getPitcherId().split("-");
                    for (String pitcherId : pitcherIds) {
                        if (map.get(pitcherId) != null) {
                            map.get(pitcherId).add(vo);
                        }else {
                            ArrayList<GameMonitorAlarmVO> newList = new ArrayList<>();
                            newList.add(vo);
                            map.put(pitcherId,newList);
                        }
                    }
                }
                for (String pitcherId : map.keySet()) {
                    List<GameMonitorAlarmVO> gameMonitorAlarmVOS = map.get(pitcherId);
                    StringBuilder msgStr = new StringBuilder(0);
                    //把消息拼成一条
                    for (int i = 0; i < gameMonitorAlarmVOS.size(); i++) {
                        String s = alarmStr(gameMonitorAlarmVOS.get(i),i);
                        msgStr.append(s);
                    }

                    log.info("type类型为4的告警信息,投手id:{}",pitcherId);
                    dingTalkMsgRpc.sendByUserId(Long.valueOf(pitcherId), new String(msgStr));
                    log.info("type类型为4的告警信息发送成功,投手id:{}",pitcherId);
                }
                for (GameMonitorAlarmVO vo : listWithType4) {
                    Criteria cri = getCriteria(vo);
                    dao.update(AdsMonitorAlarm.class, Chain.make("warn_status", 1), cri);
                }
            }

            //如果没有type==4的，则每个投手的消息单独发送
            List<GameMonitorAlarmVO> listWithoutType4 = partitionedMap.get(false);
            log.info("准备发送告警信息");
            for (GameMonitorAlarmVO vo : listWithoutType4) {
                String[] pitcherIds = vo.getPitcherId().split("-");
                for (String pitcherId : pitcherIds) {
                    //发送给多个投手
                    log.info("发送告警信息给投手：{}", pitcherId);
                    dingTalkMsgRpc.sendByUserId(Long.valueOf(pitcherId), alarmStr(vo,null));
                    log.info("发送告警信息给投手：{}成功", pitcherId);
                }
                Criteria cri = getCriteria(vo);
                dao.update(AdsMonitorAlarm.class, Chain.make("warn_status", 1), cri);
            }

        } catch (Exception e) {
            log.error("游戏监控告警出错，原因：{}", e.getMessage(), e);
        }
        return true;
    }

    @Override
    public boolean sendMsgToUserTest() {
        Sql sql = Sqls.create(getMonitorAlarmInfoSql());
        sql.setCallback(Sqls.callback.entities());
        sql.setEntity(dao.getEntity(GameMonitorAlarmVO.class));
        dao.execute(sql);
        List<GameMonitorAlarmVO> list1 = sql.getList(GameMonitorAlarmVO.class);
        //用type==4进行分组
        Map<Boolean, List<GameMonitorAlarmVO>> partitionedMap = list1.stream()
                .collect(Collectors.partitioningBy(vo -> vo.getConfigType() == 4));
        List<GameMonitorAlarmVO> listWithType4 = partitionedMap.get(true);
        //如果有type==4的，则每个投手的消息整合为1条告警
        if (CollectionUtils.isNotEmpty(listWithType4)) {
            Map<String, List<GameMonitorAlarmVO>> map = new HashMap<>();
            for (GameMonitorAlarmVO vo : listWithType4) {
                String[] pitcherIds = vo.getPitcherId().split("-");
                for (String pitcherId : pitcherIds) {
                    if (map.get(pitcherId) != null) {
                        map.get(pitcherId).add(vo);
                    }else {
                        ArrayList<GameMonitorAlarmVO> newList = new ArrayList<>();
                        newList.add(vo);
                        map.put(pitcherId,newList);
                    }
                }
            }
            for (String pitcherId : map.keySet()) {
                List<GameMonitorAlarmVO> gameMonitorAlarmVOS = map.get(pitcherId);
                StringBuilder msgStr = new StringBuilder(0);
                //把消息拼成一条
                for (int i = 0; i < gameMonitorAlarmVOS.size(); i++) {
                    String s = alarmStr(gameMonitorAlarmVOS.get(i),i);
                    msgStr.append(s);
                }

                log.info("type类型为4的告警信息,投手id:{}",pitcherId);
                log.info("type类型为4的告警信息：{}",msgStr);
                log.info("type类型为4的告警信息发送成功,投手id:{}",pitcherId);
            }
        }
        return true;
    }

    private  Criteria getCriteria(GameMonitorAlarmVO vo) {
        //更新的条件
        Criteria cri = Cnd.cri();
        if (vo.getId() != null) {
            cri.where().andEquals("id", vo.getId());
        }
        if (vo.getDt() != null) {
            cri.where().andEquals("dt", vo.getDt());
        }
        if (vo.getGameId() != null) {
            cri.where().andEquals("gameId", vo.getGameId());
        }
        if (vo.getUserId() != null) {
            cri.where().andEquals("userId", vo.getUserId());
        }
        log.info("更新告警信息状态");
        return cri;
    }

    /**
     * 生成告警信息字符串
     */
    private String alarmStr(GameMonitorAlarmVO vo,Integer index) {
        StringBuilder msgStr = new StringBuilder(0);
        if(index!=null){
            msgStr.append("【"+(index+1)+"】 \n");
        }
        msgStr.append("游戏策略响应时间：")
                .append(vo.getDt())
                .append(" ;")
                .append("\n")
                .append("游戏名称：")
                .append(vo.getGameName())
                .append(" ;区服名称：")
                .append(vo.getServerName())
                .append(" ;")
                .append("\n")
                .append("用户ID：")
                .append(vo.getUserId())
                .append(" ;角色名称：")
                .append(vo.getRoleName())
                .append(" ;")
                .append("\n")
                .append("响应策略内容：")
                .append(vo.getMessage())
                .append(" ;")
                .append("\n")
                .append("该用户响应的策略属于：")
                .append(vo.getConfigExplain())
                .append(";")
                .append("\n");

        return msgStr.toString();
    }

    /**
     * 游戏监控告警sql
     *
     * @return String
     */
    private String getMonitorAlarmInfoSql() {
        return """
                SELECT
                	a.dt ,
                	a.id ,
                	a.source_system ,
                	a.user_id ,
                	b.username ,
                	b.nickname ,
                	a.server_id ,
                	e.server_name ,
                	a.game_id ,
                	d.game_name ,
                	a.role_id ,
                	c.role_name ,
                	a.pitcher_id ,
                	a.message ,
                	a.config_explain ,
                	a.config_type,
                	a.warn_status
                FROM game_ads.ads_monitor_alarm a
                LEFT JOIN dm_game_order.t_game_user b on a.source_system = b.source_system AND a.user_id = b.id
                LEFT JOIN (
                	SELECT
                		source_system ,
                		role_id ,
                		role_name ,
                		ROW_NUMBER()over(partition by role_id , source_system order by update_time desc, user_id desc) as num
                	FROM dm_game_order.t_game_user_role
                ) c on a.source_system = c.source_system AND a.role_id = c.role_id AND c.num = 1
                LEFT JOIN dm_game_order.t_game d on a.source_system = d.source_system AND a.game_id = d.id
                LEFT JOIN dm_game_order.t_game_server e on a.source_system = e.source_system AND a.game_id = e.game_id AND a.server_id = e.server_id
                WHERE a.warn_status = 0
                """;
    }


}
