package com.qmth.themis.exam.api;

import com.qmth.themis.business.annotation.ApiJsonObject;
import com.qmth.themis.business.annotation.ApiJsonProperty;
import com.qmth.themis.business.cache.ExamRecordCacheUtil;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dto.MqDto;
import com.qmth.themis.business.entity.SysConfig;
import com.qmth.themis.business.entity.TIeExamInvigilateCallLog;
import com.qmth.themis.business.entity.TOeExamRecord;
import com.qmth.themis.business.enums.*;
import com.qmth.themis.business.service.MqDtoService;
import com.qmth.themis.business.service.TOeExamRecordService;
import com.qmth.themis.business.service.ThemisCacheService;
import com.qmth.themis.business.util.MqUtil;
import com.qmth.themis.common.contanst.Constants;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.Result;
import com.qmth.themis.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RestController;

import javax.annotation.Resource;
import java.util.Collections;
import java.util.Map;
import java.util.Objects;
import java.util.Optional;

/**
 * @Description: mobile监考监控通话信息 前端控制器
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Api(tags = "mobile监考监控通话信息Controller")
@RestController
@RequestMapping(SystemConstant.PREFIX_URL_MOBILE + "/monitor")
public class TIeInvigilateCallMobileController {
    private final static Logger log = LoggerFactory.getLogger(TIeInvigilateCallMobileController.class);

    @Resource
    MqDtoService mqDtoService;

    @Resource
    MqUtil mqUtil;

    @Resource
    TOeExamRecordService tOeExamRecordService;

    @Resource
    ThemisCacheService themisCacheService;

//    @Deprecated
//    @ApiOperation(value = "监控观看地址更新接口")
//    @RequestMapping(value = "/live_url", method = RequestMethod.POST)
//    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
//    @Transactional
//    public Result liveUrl(@ApiJsonObject(name = "liveUrlMobile", value = {
//            @ApiJsonProperty(key = "recordId", type = "long", example = "1", description = "考试记录id", required = true),
//            @ApiJsonProperty(key = "source", description = "监考视频源", required = true),
//            @ApiJsonProperty(key = "liveUrl", description = "观看地址", required = true)
//    }) @ApiParam(value = "监控信息", required = true) @RequestBody Map<String, Object> mapParameter) {
//        if (Objects.isNull(mapParameter.get("recordId")) || Objects.equals(mapParameter.get("recordId"), "")) {
//            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
//        }
//        Long recordId = null;
//        try {
//            recordId = Long.parseLong(String.valueOf(mapParameter.get("recordId")));
//            if (Objects.isNull(mapParameter.get("source")) || Objects.equals(mapParameter.get("source"), "")) {
//                throw new BusinessException("监考视频源不能为空");
//            }
//            MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf(String.valueOf(mapParameter.get("source")).toUpperCase());
//            if (Objects.isNull(mapParameter.get("liveUrl")) || Objects.equals(mapParameter.get("liveUrl"), "")) {
//                throw new BusinessException("观看地址不能为空");
//            }
//            ConcurrentHashMap<String, WebSocketMobileServer> webSocketMap = WebSocketMobileServer.getWebSocketMap();
//            String clientWebsocketId = ExamRecordCacheUtil.getClientWebsocketId(recordId);
//            if (Objects.isNull(webSocketMap.get(clientWebsocketId + "-" + source.name()))) {
//                throw new BusinessException("网络连接失败");
//            }
//            String liveUrl = String.valueOf(mapParameter.get("liveUrl"));
//            String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
//            TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, MonitorStatusSourceEnum.INIT, monitorKey, null);
//            //获取考试记录缓存
//            ExamRecordCacheUtil.setMonitorLiveUrl(recordId, source, liveUrl, true);
//
//            //监考监控通话信息 发送mq start
//            MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
//            mqDtoService.assembleSendOneWayMsg(mqDto);
//            //监考监控通话信息 发送mq end
//        } catch (Exception e) {
//            log.error(SystemConstant.LOG_ERROR, e);
//            if (e instanceof DuplicateKeyException) {
//                String errorColumn = e.getCause().toString();
//                String columnStr = errorColumn.substring(errorColumn.lastIndexOf("key") + 3, errorColumn.length()).replaceAll("'", "");
//                throw new BusinessException("考试记录id[" + recordId + "]下的" + FieldUniqueEnum.convertToCode(columnStr) + "数据不允许重复插入");
//            } else if (e instanceof BusinessException) {
//                throw new BusinessException(e.getMessage());
//            } else {
//                throw new RuntimeException(e);
//            }
//        }
//        return ResultUtil.ok(Collections.singletonMap(SystemConstant.UPDATE_TIME, System.currentTimeMillis()));
//    }

    @ApiOperation(value = "发送通话申请接口")
    @RequestMapping(value = "/call/apply", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result callApply(@ApiJsonObject(name = "callApplyMobile", value = {
            @ApiJsonProperty(key = "recordId", type = "long", example = "1", description = "考试记录id", required = true),
            @ApiJsonProperty(key = "source", description = "监考视频源", required = true)
    }) @ApiParam(value = "监控信息", required = true) @RequestBody Map<String, Object> mapParameter) {
        if (Objects.isNull(mapParameter.get(SystemConstant.RECORD_ID)) || Objects.equals(mapParameter.get(SystemConstant.RECORD_ID), "")) {
            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
        }
        Long recordId = Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.RECORD_ID)));
        if (Objects.isNull(mapParameter.get(Constants.HEADER_SOURCE)) || Objects.equals(mapParameter.get(Constants.HEADER_SOURCE), "")) {
            throw new BusinessException("来源不能为空!");
        }
        MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf(String.valueOf(mapParameter.get(Constants.HEADER_SOURCE)));
        //获取考试记录缓存
        if (Objects.isNull(source) || Objects.isNull(ExamRecordCacheUtil.getMonitorStatus(recordId, source))) {
            throw new BusinessException("推流状态为空");
        }
        MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source);
        if (!Objects.equals(status, MonitorStatusSourceEnum.START)) {
            throw new BusinessException("推流状态不正常");
        }
        //2022/04/21加入校验
        String monitorRecord = ExamRecordCacheUtil.getMonitorVideoSource(recordId);
        if (Objects.isNull(monitorRecord)) {
            TOeExamRecord tOeExamRecord = SystemConstant.getExamRecord(recordId);
            monitorRecord = tOeExamRecord.getMonitorVideoSource();
        }
        Map<String, String> monitorRecordMap = SystemConstant.getMonitorRecordMap(monitorRecord);
        if (Objects.isNull(monitorRecordMap)) {
            return ResultUtil.ok();
        } else {
            String monitorRecordStr = monitorRecordMap.get(source.name());
            if (Objects.isNull(monitorRecordStr)) {
                return ResultUtil.ok();
            }
        }

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.MONITOR_CONFIG_PREFIX);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置监控前缀"));

        String liveUrl = SystemConstant.setStreamId(sysConfig.getConfigValue(), recordId, source);
        Long timestamp = System.currentTimeMillis();
        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.START, timestamp);
        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
        String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
        TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.START, ExamRecordCacheUtil.getExamStudentId(recordId), null);
        //监考监控通话信息 发送mq start
        MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
        mqDtoService.assembleSendAsyncMsg(mqDto);
        //监考监控通话信息 发送mq end
        return ResultUtil.ok(Collections.singletonMap(SystemConstant.UPDATE_TIME, System.currentTimeMillis()));
    }

    @ApiOperation(value = "监控状态更新接口")
    @RequestMapping(value = "/status", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result status(@ApiJsonObject(name = "statusMobile", value = {
            @ApiJsonProperty(key = "recordId", type = "long", example = "1", description = "考试记录id", required = true),
            @ApiJsonProperty(key = "source", description = "监考视频源", required = true),
            @ApiJsonProperty(key = "status", description = "当前状态", required = true),
            @ApiJsonProperty(key = "type", description = "异常类型，status=stop时需要传递")
    }) @ApiParam(value = "监控信息", required = true) @RequestBody Map<String, Object> mapParameter) {
//        if (Objects.isNull(mapParameter.get(SystemConstant.RECORD_ID)) || Objects.equals(mapParameter.get(SystemConstant.RECORD_ID), "")) {
//            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
//        }
//        Long recordId = Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.RECORD_ID)));
//        if (Objects.isNull(mapParameter.get(Constants.HEADER_SOURCE)) || Objects.equals(mapParameter.get(Constants.HEADER_SOURCE), "")) {
//            throw new BusinessException("监考视频源不能为空");
//        }
//        MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf(String.valueOf(mapParameter.get(Constants.HEADER_SOURCE)).toUpperCase());
//        if (Objects.isNull(mapParameter.get(SystemConstant.STATUS)) || Objects.equals(mapParameter.get(SystemConstant.STATUS), "")) {
//            throw new BusinessException("监考视频状态不能为空");
//        }
//        MonitorStatusSourceEnum status = MonitorStatusSourceEnum.valueOf(String.valueOf(mapParameter.get(SystemConstant.STATUS)).toUpperCase());
//        if (Objects.equals(status, MonitorStatusSourceEnum.STOP.name()) && (Objects.isNull(mapParameter.get(SystemConstant.TYPE)) || Objects.equals(mapParameter.get(SystemConstant.TYPE), ""))) {
//            throw new BusinessException("异常类型不能为空");
//        }
//        //2022/04/21加入校验
//        String monitorRecord = ExamRecordCacheUtil.getMonitorVideoSource(recordId);
//        if (Objects.isNull(monitorRecord)) {
//            TOeExamRecord tOeExamRecord = SystemConstant.getExamRecord(recordId);
//            monitorRecord = tOeExamRecord.getMonitorVideoSource();
//        }
//        Map<String, String> monitorRecordMap = SystemConstant.getMonitorRecordMap(monitorRecord);
//        if (Objects.isNull(monitorRecordMap)) {
//            return ResultUtil.ok();
//        } else {
//            String monitorRecordStr = monitorRecordMap.get(source.name());
//            if (Objects.isNull(monitorRecordStr)) {
//                return ResultUtil.ok();
//            }
//        }
//        //获取考试记录缓存
//        String liveUrl = SystemConstant.setStreamId(dictionaryConfig.monitorDomain().getPrefix(), recordId, source);
//        MonitorCallStatusSourceEnum callStcallStatusatus = Objects.nonNull(ExamRecordCacheUtil.getMonitorCallStatus(recordId, source)) ? ExamRecordCacheUtil.getMonitorCallStatus(recordId, source) : null;
//        Long timestamp = System.currentTimeMillis();
//        ExamRecordCacheUtil.setMonitorStatus(recordId, source, status, timestamp);
//        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, callStatus, timestamp);
//        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
//        String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
//        TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, MonitorStatusSourceEnum.START, monitorKey, callStatus);
//        if (Objects.nonNull(mapParameter.get(SystemConstant.TYPE)) && !Objects.equals(mapParameter.get(SystemConstant.TYPE), "")) {
//            tIeExamInvigilateCallLog.setType(ExceptionEnum.valueOf(String.valueOf(mapParameter.get(SystemConstant.TYPE))));
//        }
//
//        //监考监控通话信息 发送mq start
//        MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
//        mqDtoService.assembleSendOneWayMsg(mqDto);
//        //监考监控通话信息 发送mq end

//        Map mqMap = new HashMap<>();
//        mqMap.put(SystemConstant.RECORD_ID, recordId);
//        mqMap.put(Constants.HEADER_SOURCE, source.name());
//        if (Objects.equals(status.name(), MonitorStatusSourceEnum.START.name())) {
//            //监控开始
//            MqDto mqDtoStart = new MqDto(mqUtil.getTopic(), MqTagEnum.MONITOR_START.name(), recordId, MqTagEnum.MONITOR_START, String.valueOf(recordId), mqMap, String.valueOf(recordId));
//            mqDtoService.assembleSendOneOrderMsg(mqDtoStart);
//        } else if (Objects.equals(status.name(), MonitorStatusSourceEnum.STOP.name())) {
//            //监控结束
//            MqDto mqDtoStop = new MqDto(mqUtil.getTopic(), MqTagEnum.MONITOR_STOP.name(), recordId, MqTagEnum.MONITOR_STOP, String.valueOf(recordId), mqMap, String.valueOf(recordId));
//            mqDtoService.assembleSendOneOrderMsg(mqDtoStop);
//        }
//        Map map = new HashMap();
//        map.put(SystemConstant.STATUS, status.name());
//        map.put(SystemConstant.UPDATE_TIME, System.currentTimeMillis());
//        return ResultUtil.ok(map);
        return ResultUtil.ok(true);
    }

    @ApiOperation(value = "撤销通话申请接口")
    @RequestMapping(value = "/call/cancel", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "{\"success\":true}", response = Result.class)})
    @Transactional
    public Result callCancel(@ApiJsonObject(name = "callCancelExamMobile", value = {
            @ApiJsonProperty(key = "recordId", type = "long", example = "1", description = "考试记录id", required = true),
            @ApiJsonProperty(key = "source", description = "监考视频源", required = true)
    }) @ApiParam(value = "监控信息", required = true) @RequestBody Map<String, Object> mapParameter) {
        if (Objects.isNull(mapParameter.get(SystemConstant.RECORD_ID)) || Objects.equals(mapParameter.get(SystemConstant.RECORD_ID), "")) {
            throw new BusinessException(ExceptionResultEnum.RECORD_ID_IS_NULL);
        }
        Long recordId = Long.parseLong(String.valueOf(mapParameter.get(SystemConstant.RECORD_ID)));
        if (Objects.isNull(mapParameter.get(Constants.HEADER_SOURCE)) || Objects.equals(mapParameter.get(Constants.HEADER_SOURCE), "")) {
            throw new BusinessException("来源不能为空!");
        }
        MonitorVideoSourceEnum source = MonitorVideoSourceEnum.valueOf(String.valueOf(mapParameter.get(Constants.HEADER_SOURCE)));
        //获取考试记录缓存
        ExamRecordStatusEnum statusEnum = ExamRecordCacheUtil.getStatus(recordId);
        if (Objects.isNull(statusEnum) || Objects.equals(statusEnum, ExamRecordStatusEnum.FINISHED) || Objects.equals(statusEnum, ExamRecordStatusEnum.PERSISTED) || statusEnum == ExamRecordStatusEnum.JUNK) {
            return ResultUtil.ok(Collections.singletonMap(SystemConstant.UPDATE_TIME, System.currentTimeMillis()));
        } else if (Objects.isNull(ExamRecordCacheUtil.getMonitorStatus(recordId, source))) {
            throw new BusinessException("推流状态为空");
        }
        //2022/04/21加入校验
        String monitorRecord = ExamRecordCacheUtil.getMonitorVideoSource(recordId);
        if (Objects.isNull(monitorRecord)) {
            TOeExamRecord tOeExamRecord = SystemConstant.getExamRecord(recordId);
            monitorRecord = tOeExamRecord.getMonitorVideoSource();
        }
        Map<String, String> monitorRecordMap = SystemConstant.getMonitorRecordMap(monitorRecord);
        if (Objects.isNull(monitorRecordMap)) {
            return ResultUtil.ok();
        } else {
            String monitorRecordStr = monitorRecordMap.get(source.name());
            if (Objects.isNull(monitorRecordStr)) {
                return ResultUtil.ok();
            }
        }

        SysConfig sysConfig = themisCacheService.addSysConfigCache(SystemConstant.MONITOR_CONFIG_PREFIX);
        Optional.ofNullable(sysConfig).orElseThrow(() -> new BusinessException("未配置监控前缀"));

        String liveUrl = SystemConstant.setStreamId(sysConfig.getConfigValue(), recordId, source);
        Long timestamp = System.currentTimeMillis();
        ExamRecordCacheUtil.setMonitorCallStatus(recordId, source, MonitorCallStatusSourceEnum.CANCEL, timestamp);
        tOeExamRecordService.sendExamRecordDataSaveMq(recordId, timestamp);
        String monitorKey = ExamRecordCacheUtil.getMonitorKey(recordId);
        MonitorStatusSourceEnum status = ExamRecordCacheUtil.getMonitorStatus(recordId, source);
//        TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.CANCEL, ExamRecordCacheUtil.getExamStudentId(recordId), null, ExamInvigilateCallCacheUtil.getBatchId(recordId));
        TIeExamInvigilateCallLog tIeExamInvigilateCallLog = new TIeExamInvigilateCallLog(recordId, source, liveUrl, status, monitorKey, MonitorCallStatusSourceEnum.CANCEL, ExamRecordCacheUtil.getExamStudentId(recordId), null);
        //监考监控通话信息 发送mq start
        MqDto mqDto = new MqDto(mqUtil.getTopic(), MqTagEnum.MONITOR_LOG.name(), tIeExamInvigilateCallLog, MqTagEnum.MONITOR_LOG, String.valueOf(tIeExamInvigilateCallLog.getId()), source.name());
        mqDtoService.assembleSendAsyncMsg(mqDto);
        //监考监控通话信息 发送mq end
        return ResultUtil.ok(Collections.singletonMap(SystemConstant.UPDATE_TIME, System.currentTimeMillis()));
    }
}