package com.qmth.paper.library.business.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.qmth.paper.library.business.bean.vo.PathSequenceVo;
import com.qmth.paper.library.business.bean.vo.RecognitionResultVo;
import com.qmth.paper.library.business.entity.PaperLibrary;
import com.qmth.paper.library.business.entity.PaperLibraryOther;
import com.qmth.paper.library.business.entity.PaperScanTask;
import com.qmth.paper.library.business.service.*;
import com.qmth.paper.library.common.contant.SystemConstant;
import com.qmth.paper.library.common.entity.BasicFileType;
import com.qmth.paper.library.common.entity.ExamStudent;
import com.qmth.paper.library.common.entity.SysPrivilege;
import com.qmth.paper.library.common.enums.ExceptionResultEnum;
import com.qmth.paper.library.common.enums.UploadFileEnum;
import com.qmth.paper.library.common.lock.LockService;
import com.qmth.paper.library.common.lock.LockType;
import com.qmth.paper.library.common.service.BasicBatchNumberService;
import com.qmth.paper.library.common.service.SysPrivilegeService;
import com.qmth.paper.library.common.util.ServletUtil;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.Date;
import java.util.List;
import java.util.Objects;

/**
 * <p>
 * 客户端 服务实现类
 * </p>
 */
@Service
public class ClientServiceImpl implements ClientService {

    @Resource
    private PaperScanTaskService paperScanTaskService;
    @Resource
    private SysPrivilegeService sysPrivilegeService;
    @Resource
    private PaperLibraryService paperLibraryService;
    @Resource
    private PaperLibraryOtherService paperLibraryOtherService;
    @Resource
    private PaperLibraryCommonService paperLibraryCommonService;
    @Resource
    private ExamStudentService examStudentService;
    @Resource
    private BusinessCacheService businessCacheService;
    @Resource
    private LockService lockService;
    @Resource
    private BasicBatchNumberService basicBatchNumberService;
    @Resource
    private BasicFileTypeService basicFileTypeService;

    @Override
    public PaperScanTask pageScanTask(Long examId, String courseCode) {
        // 查询任务
        QueryWrapper<PaperScanTask> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda().eq(PaperScanTask::getExamId, examId)
                .eq(PaperScanTask::getCourseCode, courseCode);
        return paperScanTaskService.getOne(queryWrapper);
    }

    @Override
    public void checkPrivilege(Long userId) {
        List<SysPrivilege> sysPrivileges = sysPrivilegeService.getClientUrlByUserId(userId);
        long count = sysPrivileges.stream().filter(m -> "client".equalsIgnoreCase(m.getUrl())).count();
        if (count == 0) {
            throw ExceptionResultEnum.ERROR.exception("用户没有权限，无法登录");
        }
    }

    @Transactional
    @Override
    public Long pictureUpload(Long paperScanTaskId, String studentCode, Integer x, Integer y, Integer width, Integer height, Integer rotate,
            MultipartFile frontFile, String frontMd5, MultipartFile versoFile, String versoMd5, Long scanUserId, String batchNo, Integer studentPaperNo) {

        if (Objects.isNull(frontFile) || frontFile.getSize() == 0) {
            throw ExceptionResultEnum.ERROR.exception("frontFile（正面图片）为空");
        }
        if (Objects.isNull(versoFile) || versoFile.getSize() == 0) {
            throw ExceptionResultEnum.ERROR.exception("versoFile（背面图片）为空");
        }

        try {
            String frontFileMd5 = DigestUtils.md5Hex(frontFile.getBytes());
            if (!Objects.equals(frontMd5, frontFileMd5)) {
                throw ExceptionResultEnum.MD5_EQUALS_FALSE.exception();
            }
            String versoFileMd5 = DigestUtils.md5Hex(versoFile.getBytes());
            if (!Objects.equals(versoMd5, versoFileMd5)) {
                throw ExceptionResultEnum.MD5_EQUALS_FALSE.exception();
            }

            PaperScanTask paperScanTask = businessCacheService.getPaperScanTask(paperScanTaskId);
            if (paperScanTask == null) {
                throw ExceptionResultEnum.ERROR.exception("扫描任务不存在");
            }

            // 识别条码区或者考生信息（前端studentCode有值时，不识别，只保存条码裁切图）
            RecognitionResultVo recognitionVo = paperLibraryService.recognition(paperScanTask, studentCode, frontFile, x, y, width, height, rotate);
            PaperLibrary paperLibrary = new PaperLibrary();
            paperLibrary.setId(SystemConstant.getDbUuid());
            paperLibrary.setPaperScanTaskId(paperScanTaskId);
            paperLibrary.setBatchNo(batchNo); // 提交批次号
            paperLibrary.setCreateId(scanUserId);
            paperLibrary.setCreateTime(System.currentTimeMillis());
            paperLibrary.setSchoolId(paperScanTask.getSchoolId());
            paperLibrary.setCreateDate(DateFormatUtils.format(new Date(), SystemConstant.SHORT_DATE_PATTERN));
            // 校验是否存在，不存在创建考生并绑定上
            ExamStudent examStudent = examStudentService.getByExamIdAndCourseCodeAndStudentCode(paperScanTask.getExamId(), paperScanTask.getCourseCode(), recognitionVo.getBindResult());
            if (examStudent == null) {
                throw ExceptionResultEnum.ERROR.exception(String.format("课程[%s(%s)]，学号[%s]的学生不存在", paperScanTask.getCourseName(), paperScanTask.getCourseCode(), studentCode));
//                BasicExam basicExam = basicExamService.getById(paperScanTask.getExamId());
//                examStudent = new ExamStudent(schoolId, basicExam.getSemesterId(), basicExam.getId(), paperScanTask.getCourseCode(), paperScanTask.getCourseName(), recognitionVo.getBindResult(), studentCode, true, true);
//                if (StoreTypeEnum.ROOM.equals(paperScanTask.getStoreType())) {
//                    examStudent.setExamRoom(studentCode);
//                }
//                if (StoreTypeEnum.CLASS.equals(paperScanTask.getStoreType())) {
//                    examStudent.setClassName(studentCode);
//                }
//                // 保存考生
//                examStudentService.save(examStudent);
            }
            paperLibrary.setStudentId(examStudent.getId());
            //考生图片序号
            int studentMaxSequence = paperLibraryService.getStudentMaxSequence(paperScanTaskId, batchNo, examStudent.getId());
            int studentSequence = studentMaxSequence + studentPaperNo;
            paperLibrary.setSequence(studentSequence);
            // 保存图片，生成路径
            PathSequenceVo pathSequenceVo = paperLibraryCommonService.saveLibraryFile(paperScanTask, examStudent, UploadFileEnum.IMAGE, studentSequence, frontFile, versoFile);
            paperLibrary.setPath(pathSequenceVo.getPath());


            paperLibrary.setBindResult(recognitionVo.getBindResult());
            paperLibrary.setRecognizeResult(recognitionVo.getRecognizeResult());
            paperLibraryService.save(paperLibrary);
            // 在controller层调用更新和添加锁
/*            if (save) {
                // 统计考生数量
//                int studentCount = examStudentService.countByExamIdAndCourseCode(examStudent.getExamId(), examStudent.getCourseCode());
                // 更新扫描任务扫描考生数量、扫描图片数量
                paperScanTaskService.updateScanCount(paperScanTaskId);
                // 更新考生绑定图片数量
                examStudentService.updateBindCount(examStudent.getId());
                // 更新批次号
                basicBatchNumberService.updateBatchNo(paperScanTask.getExamId(), scanUserId, batchNo);
                // 清除pdf文件记录
                examStudentService.clearPdfFilePath(examStudent.getId());
            }*/
            return examStudent.getId();

        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("保存图片失败：" + e.getMessage());
        }
    }

    @Override
    public boolean otherUpload(Long paperScanTaskId, MultipartFile frontFile, String frontMd5, MultipartFile versoFile, String versoMd5, Long fileTypeId, String classRoomName) {
        Long userId = Long.valueOf(ServletUtil.getRequestHeaderUserId().toString());
        if (Objects.isNull(frontFile) || frontFile.getSize() == 0) {
            throw ExceptionResultEnum.ERROR.exception("frontFile（正面图片）为空");
        }
        if (Objects.isNull(versoFile) || versoFile.getSize() == 0) {
            throw ExceptionResultEnum.ERROR.exception("versoFile（背面图片）为空");
        }
        try {
            lockService.waitlock(LockType.UPLOAD_OTHER_FILE, paperScanTaskId, fileTypeId);
            String frontFileMd5 = DigestUtils.md5Hex(frontFile.getBytes());
            if (!Objects.equals(frontMd5, frontFileMd5)) {
                throw ExceptionResultEnum.MD5_EQUALS_FALSE.exception();
            }
            String versoFileMd5 = DigestUtils.md5Hex(versoFile.getBytes());
            if (!Objects.equals(versoMd5, versoFileMd5)) {
                throw ExceptionResultEnum.MD5_EQUALS_FALSE.exception();
            }

            PaperScanTask paperScanTask = businessCacheService.getPaperScanTask(paperScanTaskId);
            if (paperScanTask == null) {
                throw ExceptionResultEnum.ERROR.exception("扫描任务不存在");
            }
            PaperLibraryOther paperLibraryOther = new PaperLibraryOther();
            paperLibraryOther.setId(SystemConstant.getDbUuid());
            paperLibraryOther.setPaperScanTaskId(paperScanTaskId);
            paperLibraryOther.setCreateId(userId);
            paperLibraryOther.setCreateTime(System.currentTimeMillis());

            BasicFileType basicFileType = basicFileTypeService.getById(fileTypeId);
            if (basicFileType == null) {
                throw ExceptionResultEnum.ERROR.exception("文件类型不存在，请重新选择");
            }
            paperLibraryOther.setFileTypeId(fileTypeId);

            int maxSequence = paperLibraryOtherService.getMaxSequence(paperScanTaskId, fileTypeId);
            paperLibraryOther.setSequence(maxSequence);
            // 保存图片，生成路径
            PathSequenceVo pathSequenceVo = paperLibraryCommonService.saveLibraryOtherFile(paperScanTask, UploadFileEnum.IMAGE, basicFileType.getName() + maxSequence, classRoomName, frontFile, versoFile);
            paperLibraryOther.setPath(pathSequenceVo.getPath());

            return paperLibraryOtherService.save(paperLibraryOther);
        } catch (Exception e) {
            throw ExceptionResultEnum.ERROR.exception("保存图片失败：" + e.getMessage());
        } finally {
            lockService.unlock(LockType.UPLOAD_OTHER_FILE, paperScanTaskId, fileTypeId);
        }
    }

    @Transactional
    @Override
    public boolean updateCount(Long paperScanTaskId, Long examId, Long studentId, Long scanUserId, String batchNo) {
        // 更新扫描任务扫描考生数量、扫描图片数量
        paperScanTaskService.updateScanCountNoLock(paperScanTaskId);
        // 更新考生绑定图片数量
        examStudentService.updateBindCount(studentId);
        // 更新批次号
        basicBatchNumberService.updateBatchNo(examId, scanUserId, batchNo);
        // 清除pdf文件记录
        examStudentService.clearPdfFilePath(studentId);
        return true;
    }
}
