package com.qmth.themis.exam.listener.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.google.gson.Gson;
import com.qmth.themis.business.cache.ExamRecordCacheUtil;
import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.dto.WebsocketDto;
import com.qmth.themis.business.entity.TEExamStudentLog;
import com.qmth.themis.business.entity.TIeExamInvigilateNotice;
import com.qmth.themis.business.entity.TMRocketMessage;
import com.qmth.themis.business.enums.FinishTypeEnum;
import com.qmth.themis.business.enums.MessageTypeEnum;
import com.qmth.themis.business.enums.MqTagEnum;
import com.qmth.themis.business.enums.WebsocketTypeEnum;
import com.qmth.themis.business.service.TEExamStudentLogService;
import com.qmth.themis.business.service.TEExamStudentService;
import com.qmth.themis.business.service.TIeExamInvigilateNoticeService;
import com.qmth.themis.business.service.TMRocketMessageService;
import com.qmth.themis.business.util.JacksonUtil;
import com.qmth.themis.business.util.RedisUtil;
import com.qmth.themis.exam.config.ExamConstant;
import com.qmth.themis.exam.listener.service.MqOeLogicService;
import com.qmth.themis.exam.websocket.WebSocketMobileServer;
import com.qmth.themis.exam.websocket.WebSocketOeServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.Map;
import java.util.Objects;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;

/**
 * @Description: mq 考生端执行逻辑 impl
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/7/31
 */
@Service
public class MqOeLogicServiceImpl implements MqOeLogicService {
    private final static Logger log = LoggerFactory.getLogger(MqOeLogicServiceImpl.class);

    @Resource
    RedisUtil redisUtil;

    @Resource
    TMRocketMessageService tmRocketMessageService;

    @Resource
    TEExamStudentLogService teExamStudentLogService;

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TIeExamInvigilateNoticeService tIeExamInvigilateNoticeService;

    /**
     * mq最大重试次数逻辑
     *
     * @param mqDto
     * @param key
     */
    @Override
    @Transactional
    public void execMqMaxReconsumeTime(MqDto mqDto, String key) {
        //超过最大重试次数，保存到数据库，后续可以发短信通知系统管理人员
        Gson gson = new Gson();
        mqDto.setAck(SystemConstant.POSION_ACK_TYPE);
        TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
        tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
        tmRocketMessageService.saveOrUpdate(tmRocketMessage);
        redisUtil.delete(key, mqDto.getId());
    }

    /**
     * oe逻辑
     *
     * @param mqDto
     * @param key
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    @Override
    @Transactional
    public void execMqOeLogic(MqDto mqDto, String key) throws ClassNotFoundException, IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Gson gson = new Gson();
        ConcurrentHashMap<Long, WebSocketOeServer> webSocketMap = WebSocketOeServer.getWebSocketMap();
        String tag = mqDto.getTag();
        if (Objects.equals(MqTagEnum.OE_MONITOR_FINISH.name(), tag)) {//强制离线交卷
            Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
            examRecordId.forEach(s -> {
                Long recordId = Long.parseLong(String.valueOf(s));
                if (Objects.nonNull(webSocketMap.get(recordId))) {
                    Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
                    WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
                    Map map = new HashMap<>();
                    map.put("form", mqDto.getObjName());
                    map.put(SystemConstant.RECORD_ID, recordId);
                    map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_STOP_EXAM.name(), map);
                    webSocketOeServer.sendMessage(websocketDto);
                    TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), mqDto.getType().getCode(), mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId);
                    teExamStudentLogService.save(teExamStudentLog);
                }
            });
        }
//        else if (Objects.equals(MqTagEnum.OE_HARD_FINISH.name(), tag)) {//手动交卷
//            Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
//            examRecordId.forEach(s -> {
//                Long recordId = Long.parseLong(String.valueOf(s));
//                if (Objects.nonNull(webSocketMap.get(recordId))) {
//                    Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
//                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
//                    WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
//                    Map map = new HashMap<>();
//                    map.put(SystemConstant.RECORD_ID, recordId);
//                    map.put(SystemConstant.MESSAGE, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
//                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.HAND_STOP_EXAM.name(), map);
//                    webSocketOeServer.sendMessage(websocketDto);
//                    TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), mqDto.getType().getCode(), mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId);
//                    teExamStudentLogService.save(teExamStudentLog);
//                }
//            });
//        }
        else if (Objects.equals(MqTagEnum.OE_WARNING_FINISH.name(), tag)) {//预警交卷
            Set examRecordId = JacksonUtil.readJson(String.valueOf(mqDto.getBody()), Set.class);
            examRecordId.forEach(s -> {
                Long recordId = Long.parseLong(String.valueOf(s));
                if (Objects.nonNull(webSocketMap.get(recordId))) {
                    Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
                    ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
                    WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
                    Map map = new HashMap<>();
                    map.put(SystemConstant.RECORD_ID, recordId);
                    map.put(SystemConstant.BREACH_STATUS, FinishTypeEnum.valueOf(String.valueOf(mqDto.getProperties().get("type"))).getCode());
                    WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.BREACH_STOP_EXAM.name(), map);
                    webSocketOeServer.sendMessage(websocketDto);
                    TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), mqDto.getType().getCode(), mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId);
                    teExamStudentLogService.save(teExamStudentLog);
                }
            });
        } else if (Objects.equals(MqTagEnum.OE_IM_CLUSTERING.name(), tag)) {//点对点消息
            Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
            if (Objects.nonNull(webSocketMap.get(recordId))) {
                Long examId = ExamRecordCacheUtil.getExamId(recordId);
                Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
                Long examActivityId = ExamRecordCacheUtil.getExamActivityId(recordId);
                WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
                Map<String, Object> prop = mqDto.getProperties();
                Map map = new HashMap<>();
                map.put(SystemConstant.RECORD_ID, recordId);
                map.put("from", mqDto.getObjName());
                map.put("type", prop.get("type"));
                map.put("content", prop.get("content"));
                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_NOTICE.name(), map);
                webSocketOeServer.sendMessage(websocketDto);
                TIeExamInvigilateNotice tIeExamInvigilateNotice = new TIeExamInvigilateNotice(examId, examActivityId, recordId, Long.parseLong(mqDto.getObjId()), examStudentId, MessageTypeEnum.valueOf(String.valueOf(prop.get("type"))), String.valueOf(prop.get("content")));
                tIeExamInvigilateNoticeService.saveOrUpdate(tIeExamInvigilateNotice);
            }
        } else if (Objects.equals(MqTagEnum.OE_IM_BROADCASTING.name(), tag)) {//广播消息
            JSONArray jsonArray = JSONArray.parseArray(String.valueOf(mqDto.getBody()));
            Set<String> examStudentIdentitySet = jsonArray.toJavaObject(Set.class);
            log.info("examStudentIdentitySet:{}", JacksonUtil.parseJson(examStudentIdentitySet));
        } else if (Objects.equals(MqTagEnum.OE_LIVENESS_VERIFY.name(), tag)) {//监考强制活体验证
            Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
            if (Objects.nonNull(webSocketMap.get(recordId))) {
                Long examStudentId = ExamRecordCacheUtil.getExamStudentId(recordId);
                ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(examStudentId);
                WebSocketOeServer webSocketOeServer = webSocketMap.get(recordId);
                Map map = new HashMap<>();
                map.put(SystemConstant.RECORD_ID, recordId);
                WebsocketDto websocketDto = new WebsocketDto(WebsocketTypeEnum.INVIGILATE_LIVENESS_VERIFY.name(), map);
                webSocketOeServer.sendMessage(websocketDto);
                TEExamStudentLog teExamStudentLog = new TEExamStudentLog(mqDto.getType().name(), mqDto.getType().getCode(), mqDto.getType().getCode(), examStudentCacheBean.getStudentId(), examStudentId, recordId);
                teExamStudentLogService.save(teExamStudentLog);
            }
        }
        mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
        TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
        tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
        tmRocketMessageService.saveOrUpdate(tmRocketMessage);
        redisUtil.delete(key, mqDto.getId());
    }

    /**
     * oe mobile逻辑
     *
     * @param mqDto
     * @param key
     * @throws ClassNotFoundException
     * @throws IllegalAccessException
     * @throws InstantiationException
     * @throws NoSuchMethodException
     * @throws InvocationTargetException
     */
    @Override
    public void execMqOeMobileLogic(MqDto mqDto, String key) {
        Gson gson = new Gson();
        ConcurrentHashMap<String, WebSocketMobileServer> webSocketMap = WebSocketMobileServer.getWebSocketMap();
        String tag = mqDto.getTag();
        if (Objects.equals(MqTagEnum.EXAM_STOP.name(), tag)) {//考试退出
            Long recordId = Long.parseLong(String.valueOf(mqDto.getBody()));
            ExamConstant.sendExamStopMsg(recordId, true);
        }
        mqDto.setAck(SystemConstant.STANDARD_ACK_TYPE);
        TMRocketMessage tmRocketMessage = gson.fromJson(gson.toJson(mqDto), TMRocketMessage.class);
        tmRocketMessage.setBody(JacksonUtil.parseJson(tmRocketMessage.getBody()));
        tmRocketMessageService.saveOrUpdate(tmRocketMessage);
        redisUtil.delete(key, mqDto.getId());
    }
}
