package com.qmth.themis.business.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.reflect.TypeToken;
import com.qmth.themis.business.bean.StudentParams;
import com.qmth.themis.business.bean.admin.StudentPhotoUploadResponseBean;
import com.qmth.themis.business.cache.bean.ExamCacheBean;
import com.qmth.themis.business.cache.bean.ExamStudentCacheBean;
import com.qmth.themis.business.constant.SystemConstant;
import com.qmth.themis.business.dao.TEStudentMapper;
import com.qmth.themis.business.dto.cache.TEStudentCacheDto;
import com.qmth.themis.business.dto.response.*;
import com.qmth.themis.business.entity.*;
import com.qmth.themis.business.enums.MonitorVideoSourceEnum;
import com.qmth.themis.business.service.*;
import com.qmth.themis.business.util.OssUtil;
import com.qmth.themis.business.util.ServletUtil;
import com.qmth.themis.common.enums.ExceptionResultEnum;
import com.qmth.themis.common.exception.BusinessException;
import com.qmth.themis.common.util.GsonUtil;
import org.apache.commons.io.FilenameUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.*;

/**
 * @Description: 学生档案 服务实现类
 * @Param:
 * @return:
 * @Author: wangliang
 * @Date: 2020/6/25
 */
@Service
public class TEStudentServiceImpl extends ServiceImpl<TEStudentMapper, TEStudent> implements TEStudentService {

    @Resource
    TEStudentMapper teStudentMapper;

    @Resource
    OssUtil ossUtil;

    @Resource
    ThemisCacheService themisCacheService;

    @Resource
    TEExamService teExamService;

    @Resource
    TEExamStudentService teExamStudentService;

    @Resource
    TEExamStudentLogService teExamStudentLogService;

    @Resource
    TIeExamInvigilateNoticeService tIeExamInvigilateNoticeService;

    @Resource
    TIeExamMediaLogService tIeExamMediaLogService;

    /**
     * 学生档案查询
     *
     * @param iPage
     * @param identity
     * @param name
     * @param enable
     * @param orgId
     * @param photo
     * @return
     */
    @Override
    public IPage<TEStudentDto> studentQuery(IPage<Map> iPage, String identity, String name, Integer enable,
                                            Long orgId, Boolean photo) {
        return teStudentMapper.studentQuery(iPage, identity, name, enable, orgId, photo);
    }

    /**
     * 学生考试记录查询
     *
     * @param iPage
     * @param studentId
     * @param examId
     * @return
     */
    @Override
    public IPage<TEStudentExamRecordDto> studentExamRecordQuery(IPage<Map> iPage, Long studentId, Long examId) {
        IPage<TEStudentExamRecordDto> teStudentExamRecordDtoIPage = teStudentMapper.studentExamRecordQuery(iPage, studentId, examId);
        for (TEStudentExamRecordDto t : teStudentExamRecordDtoIPage.getRecords()) {
            if (Objects.nonNull(t.getTencentVideoUrl()) && !Objects.equals(t.getTencentVideoUrl().trim(), "")) {
                List<TEStudentMonitorRecordDto> monitorRecordList = GsonUtil.fromJson(t.getTencentVideoUrl(), new TypeToken<List<TEStudentMonitorRecordDto>>() {
                }.getType());
                Set<MonitorVideoSourceEnum> set = new LinkedHashSet<>(monitorRecordList.size());
                for (TEStudentMonitorRecordDto teStudentMonitorRecordDto : monitorRecordList) {
                    MonitorVideoSourceEnum monitorVideoSourceEnum = SystemConstant.getMonitorRecordVideoSource(teStudentMonitorRecordDto.getVideoSource());
                    if (Objects.nonNull(monitorVideoSourceEnum)) {
                        set.add(monitorVideoSourceEnum);
                    }
                }
                t.setMonitorRecord(set.toString().replaceAll("\\[", "").replaceAll("\\]", "").replaceAll(", ", ",").trim());
            } else if (Objects.nonNull(t.getVideoSource()) && !Objects.equals(t.getVideoSource().trim(), "")) {
                String[] strs = t.getVideoSource().split(",");
                Set<MonitorVideoSourceEnum> set = new LinkedHashSet<>(strs.length);
                for (String s : strs) {
                    MonitorVideoSourceEnum monitorVideoSourceEnum = SystemConstant.getMonitorRecordVideoSource(s);
                    if (Objects.nonNull(monitorVideoSourceEnum)) {
                        set.add(monitorVideoSourceEnum);
                    }
                }
                t.setMonitorRecord(set.toString().replaceAll("\\[", "").replaceAll("\\]", "").replaceAll(", ", ",").trim());
            }
        }
        return teStudentExamRecordDtoIPage;
    }

    /**
     * 底照上传
     *
     * @param orgId
     * @param identity
     * @param file
     * @param md5
     * @param cover
     * @return
     */
    @Transactional
    @Override
    public StudentPhotoUploadResponseBean photoUpload(Long orgId, String identity, MultipartFile file, String md5, Boolean cover) {
        QueryWrapper<TEStudent> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(TEStudent::getOrgId, orgId);
        wrapper.lambda().eq(TEStudent::getIdentity, identity);
        TEStudent student = this.getOne(wrapper);
        Optional.ofNullable(student).orElseThrow(() -> new BusinessException("学生不存在"));

        String filePath = null;
        if ((Objects.nonNull(cover) && cover) || ((Objects.isNull(cover) || !cover) && Objects.isNull(student.getBasePhotoPath()))) {
            String suffix = "." + FilenameUtils.getExtension(file.getOriginalFilename());
            filePath = "base_photo/" + orgId + "/" + student.getId() + suffix;
            InputStream in = null;
            try {
                student.setBasePhotoPath(filePath);
                this.saveOrUpdate(student);
                themisCacheService.updateStudentAccountCache(student.getId());
                in = file.getInputStream();
                ossUtil.upload(true, filePath, in, md5);
//                String url = ossUtil.getAliYunOssPublicDomain().getPublicUrl() + File.separator + filePath;
//                StudentPhotoUploadResponseBean ret = new StudentPhotoUploadResponseBean();
//                ret.setPhotoUrl(url);
//                return ret;
            } catch (IOException e) {
                throw new BusinessException("文件读取出错");
            } finally {
                if (in != null) {
                    try {
                        in.close();
                    } catch (IOException e) {
                    }
                }
            }
        } else {
            filePath = student.getBasePhotoPath();
        }
        String url = ossUtil.getAliYunOssPublicDomain().getPublicUrl() + File.separator + filePath;
        StudentPhotoUploadResponseBean ret = new StudentPhotoUploadResponseBean();
        ret.setPhotoUrl(url);
        return ret;
    }

    /**
     * 修改学生密码
     *
     * @param studentParams
     */
    @Override
    @Transactional
    public void updatePwd(StudentParams studentParams) {
        TEStudent teStudent = this.getById(studentParams.getId());
        Optional.ofNullable(teStudent).orElseThrow(() -> new BusinessException(ExceptionResultEnum.STUDENT_INFO_IS_NULL));
        TBUser tbUser = (TBUser) ServletUtil.getRequestAccount();
        teStudent.setPassword(studentParams.getPassword());
        teStudent.setUpdateId(Objects.nonNull(tbUser) ? tbUser.getId() : -1);
        this.updateById(teStudent);
        themisCacheService.updateStudentAccountCache(teStudent.getId());
    }

    /**
     * 视频监考回放查询接口
     *
     * @param iPage
     * @param examRecordId
     * @param monitorRecord
     * @param log
     * @return
     */
    @Override
    public TEStudentExamRecordVideoDto examRecordVideoQuery(IPage<Map> iPage, Long examRecordId, MonitorVideoSourceEnum monitorRecord, Boolean log) {
        TOeExamRecord tOeExamRecord = SystemConstant.getExamRecord(examRecordId);
        List<TEExamStudentLog> teExamStudentLogList = null;
        ExamCacheBean examCacheBean = teExamService.getExamCacheBean(tOeExamRecord.getExamId());
        ExamStudentCacheBean examStudentCacheBean = teExamStudentService.getExamStudentCacheBean(tOeExamRecord.getExamStudentId());

        if (Objects.nonNull(log) && log) {
            QueryWrapper<TEExamStudentLog> teExamStudentLogQueryWrapper = new QueryWrapper<>();
            teExamStudentLogQueryWrapper.lambda().eq(TEExamStudentLog::getExamStudentId, examStudentCacheBean.getId())
                    .eq(TEExamStudentLog::getExamRecordId, examRecordId)
                    .orderByAsc(TEExamStudentLog::getCreateTime);
            teExamStudentLogList = teExamStudentLogService.list(teExamStudentLogQueryWrapper);
            if (!CollectionUtils.isEmpty(teExamStudentLogList)) {
                teExamStudentLogList = teExamStudentLogList.get(0).ipChange(teExamStudentLogList);
            }

            TEStudentCacheDto teStudent = themisCacheService.addStudentAccountCache(examStudentCacheBean.getStudentId());
            //加入文本和语音消息轨迹
            List<TIeExamInvigilateNotice> tIeExamInvigilateNoticeList = tIeExamInvigilateNoticeService.queryNoticeByExamRecordId(examRecordId);
            if (!CollectionUtils.isEmpty(tIeExamInvigilateNoticeList)) {
                for (TIeExamInvigilateNotice t : tIeExamInvigilateNoticeList) {
                    teExamStudentLogList.add(new TEExamStudentLog(teStudent.getId(), tOeExamRecord.getExamStudentId(), t.getExamRecordId(), t.getType(), t.getContent(), t.getFormUserId(), t.getFormUserName(), t.getSendTime()));
                }
            }

            //加入多媒体消息轨迹
            List<TIeExamMediaLog> tIeExamMediaLogList = tIeExamMediaLogService.queryMediaByExamRecordId(examRecordId);
            if (!CollectionUtils.isEmpty(tIeExamMediaLogList)) {
                for (TIeExamMediaLog t : tIeExamMediaLogList) {
                    teExamStudentLogList.add(new TEExamStudentLog(teStudent.getId(), tOeExamRecord.getExamStudentId(), t.getExamRecordId(), t.getType(), t.getContent(), t.getCreateTime()));
                }
            }
            Collections.sort(teExamStudentLogList);
        }

        IPage<TEStudentExamRecordVideoMessageDto> teStudentExamRecordVideoMessageDtoIPage = null;
        if (Objects.isNull(tOeExamRecord.getTencentVideoUrl())) {
            teStudentExamRecordVideoMessageDtoIPage = teStudentMapper.examRecordVideoQuery(iPage, examRecordId, Objects.nonNull(monitorRecord) ? monitorRecord.name().toLowerCase() : null);
        } else {
            JSONArray jsonArray = JSONArray.parseArray(tOeExamRecord.getTencentVideoUrl());
            List<TEStudentExamRecordVideoMessageDto> teStudentExamRecordVideoMessageDtoList = new ArrayList<>(jsonArray.size());
            for (int i = 0; i < jsonArray.size(); i++) {
                JSONObject json = (JSONObject) jsonArray.get(i);
                TEStudentExamRecordVideoMessageDto teStudentExamRecordVideoMessageDto = new TEStudentExamRecordVideoMessageDto((String) json.get(SystemConstant.VIDEO_SOURCE), tOeExamRecord.getFirstStartTime(), tOeExamRecord.getFinishTime(), (String) json.get(SystemConstant.VIDEO_URL));
                if (Objects.nonNull(monitorRecord)) {
                    if (MonitorVideoSourceEnum.valueOf(teStudentExamRecordVideoMessageDto.getVideoSource()) == monitorRecord) {
                        teStudentExamRecordVideoMessageDtoList.add(teStudentExamRecordVideoMessageDto);
                        break;
                    }
                } else {
                    teStudentExamRecordVideoMessageDtoList.add(teStudentExamRecordVideoMessageDto);
                }
            }
            teStudentExamRecordVideoMessageDtoIPage = new Page<>(iPage.getCurrent(), iPage.getSize());
            teStudentExamRecordVideoMessageDtoIPage.setRecords(teStudentExamRecordVideoMessageDtoList);
            teStudentExamRecordVideoMessageDtoIPage.setTotal(teStudentExamRecordVideoMessageDtoList.size());
        }
        return new TEStudentExamRecordVideoDto(Objects.nonNull(examCacheBean) ? examCacheBean.getId() : null,
                Objects.nonNull(examCacheBean) ? examCacheBean.getName() : null, Objects.nonNull(examStudentCacheBean) ? examStudentCacheBean.getId() : null, examRecordId, Objects.nonNull(examStudentCacheBean) ? examStudentCacheBean.getCourseCode() : null,
                Objects.nonNull(examStudentCacheBean) ? examStudentCacheBean.getCourseName() : null, Objects.nonNull(examStudentCacheBean) ? examStudentCacheBean.getIdentity() : null, Objects.nonNull(examStudentCacheBean) ? examStudentCacheBean.getName() : null,
                tOeExamRecord.getFirstStartTime(), teExamStudentLogList, teStudentExamRecordVideoMessageDtoIPage);
    }
}
