package com.qmth.paper.library.api;


import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.qmth.boot.api.annotation.Aac;
import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.paper.library.business.bean.params.ClientLoginParam;
import com.qmth.paper.library.business.entity.PaperScanTask;
import com.qmth.paper.library.business.service.ClientService;
import com.qmth.paper.library.business.service.ExamStudentService;
import com.qmth.paper.library.business.service.PaperScanTaskService;
import com.qmth.paper.library.common.bean.result.LoginResult;
import com.qmth.paper.library.common.contant.ApiPrefixConstant;
import com.qmth.paper.library.common.entity.BasicSchool;
import com.qmth.paper.library.common.entity.ExamStudent;
import com.qmth.paper.library.common.entity.SysUser;
import com.qmth.paper.library.common.enums.AppSourceEnum;
import com.qmth.paper.library.common.enums.ExceptionResultEnum;
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.BasicSchoolService;
import com.qmth.paper.library.common.service.LibraryCommonService;
import com.qmth.paper.library.common.service.SysUserService;
import com.qmth.paper.library.common.util.Result;
import com.qmth.paper.library.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.springframework.validation.BindingResult;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import javax.validation.Valid;
import java.security.NoSuchAlgorithmException;
import java.util.Objects;

/**
 * <p>
 * 扫描端 前端控制器
 * </p>
 */
@Api(tags = "扫描端Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + ApiPrefixConstant.PREFIX_CLIENT)
@Validated
public class ClientController {

    @Resource
    private ClientService clientService;
    @Resource
    private SysUserService sysUserService;
    @Resource
    private BasicSchoolService basicSchoolService;
    @Resource
    private BasicBatchNumberService basicBatchNumberService;
    @Resource
    private ExamStudentService examStudentService;
    @Resource
    private LibraryCommonService libraryCommonService;
    @Resource
    private PaperScanTaskService paperScanTaskService;
    @Resource
    private LockService lockService;

    /**
     * 登录
     */
    @ApiOperation(value = "登录")
    @PostMapping("/user/login")
    @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = LoginResult.class)})
    @Aac(auth = false)
    public Result login(@ApiParam(value = "用户信息", required = true) @Valid @RequestBody ClientLoginParam login, BindingResult bindingResult) throws NoSuchAlgorithmException {
        if (bindingResult.hasErrors()) {
            return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }

        BasicSchool basicSchool = basicSchoolService.getBySchoolCode(login.getSchoolCode());
        if (Objects.isNull(basicSchool)) {
            throw ExceptionResultEnum.SCHOOL_NO_DATA.exception();
        }

        QueryWrapper<SysUser> wrapper = new QueryWrapper<>();
        wrapper.lambda().eq(SysUser::getSchoolId, basicSchool.getId()).eq(SysUser::getLoginName, login.getLoginName());
        SysUser sysUser = sysUserService.getOne(wrapper);
        // 用户不存在
        if (Objects.isNull(sysUser)) {
            throw ExceptionResultEnum.USER_NO_DATA.exception();
        }
        // 校验密码
        if (!Objects.equals(sysUser.getPassword(), login.getPassword())) {
            throw ExceptionResultEnum.USER_NO_DATA.exception();
        }
        // 是否有客户端权限
        clientService.checkPrivilege(sysUser.getId());
        return ResultUtil.ok(libraryCommonService.login(login.getPassword(), sysUser, AppSourceEnum.PAPER_LIBRARY_CLIENT));
    }

    @ApiOperation(value = "任务查询")
    @PostMapping("/task/get")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result page(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                       @ApiParam(value = "课程", required = true) @RequestParam String courseCode) {
        return ResultUtil.ok(clientService.pageScanTask(examId, courseCode));
    }

    @ApiOperation(value = "上传图片")
    @PostMapping("/picture/upload")
    @ApiResponses({@ApiResponse(code = 200, message = "保存图片成功", response = Result.class)})
    public Result pictureUpload(@ApiParam(value = "扫描任务ID", required = true) @RequestParam Long paperScanTaskId,
                                @ApiParam(value = "学号") @RequestParam(required = false) String studentCode,
                                @ApiParam(value = "x") @RequestParam Integer x,
                                @ApiParam(value = "y") @RequestParam Integer y,
                                @ApiParam(value = "width") @RequestParam Integer width,
                                @ApiParam(value = "height") @RequestParam Integer height,
                                @ApiParam(value = "旋转角度") @RequestParam(defaultValue = "0") Integer rotate,
                                @ApiParam(value = "正面图片", required = true) @RequestParam MultipartFile frontFile,
                                @ApiParam(value = "正面图片md5", required = true) @RequestParam String frontMd5,
                                @ApiParam(value = "背面图片", required = true) @RequestParam MultipartFile versoFile,
                                @ApiParam(value = "背面图片md5", required = true) @RequestParam String versoMd5,
                                @ApiParam(value = "采集用户ID", required = true) @RequestParam Long scanUserId,
                                @ApiParam(value = "批次号", required = true) @RequestParam String batchNo,
                                @ApiParam(value = "图片序号", required = true) @RequestParam Integer studentPaperNo) {
        Long studentId;
        try {
            lockService.waitlock(LockType.GET_MAX_SEQUENCE, paperScanTaskId, studentCode);
            studentId = clientService.pictureUpload(paperScanTaskId, studentCode, x, y, width, height, rotate, frontFile, frontMd5, versoFile, versoMd5,
                    scanUserId, batchNo, studentPaperNo);
        } finally {
            lockService.unlock(LockType.GET_MAX_SEQUENCE, paperScanTaskId, studentCode);
        }

        PaperScanTask task = paperScanTaskService.getById(paperScanTaskId);
        try {
            lockService.waitlock(LockType.UPDATE_SCAN_PAPER_COUNT, paperScanTaskId);
            clientService.updateCount(paperScanTaskId, task.getExamId(), studentId, scanUserId, batchNo);
        } finally {
            lockService.unlock(LockType.UPDATE_SCAN_PAPER_COUNT, paperScanTaskId);
        }
        return ResultUtil.ok();
    }

    @ApiOperation(value = "上传其它图片")
    @PostMapping("/other/upload")
    @ApiResponses({@ApiResponse(code = 200, message = "保存图片成功", response = Result.class)})
    public Result otherUpload(@ApiParam(value = "扫描任务ID", required = true) @RequestParam Long paperScanTaskId,
                              @ApiParam(value = "正面图片", required = true) @RequestParam MultipartFile frontFile,
                              @ApiParam(value = "正面图片md5", required = true) @RequestParam String frontMd5,
                              @ApiParam(value = "背面图片", required = true) @RequestParam MultipartFile versoFile,
                              @ApiParam(value = "背面图片md5", required = true) @RequestParam String versoMd5,
                              @ApiParam(value = "文件类型ID", required = true) @RequestParam Long fileTypeId,
                              @ApiParam(value = "考场/班级的名称") @RequestParam(required = false) String classRoomName) {
        return ResultUtil.ok(clientService.otherUpload(paperScanTaskId, frontFile, frontMd5, versoFile, versoMd5, fileTypeId, classRoomName));
    }

    @ApiOperation(value = "根据学号获取考生信息")
    @PostMapping("/student/get")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result getStudent(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                             @ApiParam(value = "课程代码", required = true) @RequestParam String courseCode,
                             @ApiParam(value = "学号", required = true) @RequestParam String studentCode) {
        return ResultUtil.ok(examStudentService.getByExamIdAndCourseCodeAndStudentCode(examId, courseCode, studentCode));
    }

    @ApiOperation(value = "保存学生")
    @PostMapping("/student/save")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result saveStudent(@Valid @RequestBody ExamStudent examStudent, BindingResult bindingResult) {
        if (bindingResult.hasErrors()) {
            return ResultUtil.error(bindingResult.getAllErrors().get(0).getDefaultMessage());
        }
        return ResultUtil.ok(examStudentService.saveExamStudentFromClient(examStudent));
    }

    @ApiOperation(value = "获取考场/班级")
    @PostMapping("/classroom/get")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result getClassroom(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                               @ApiParam(value = "课程代码", required = true) @RequestParam String courseCode) {
        return ResultUtil.ok(examStudentService.listByStoreType(examId, courseCode));
    }

    @ApiOperation(value = "查询批次号")
    @PostMapping("/batch_no/get")
    @ApiResponses({@ApiResponse(code = 200, message = "查询成功", response = Result.class)})
    public Result getBatchNumber(@ApiParam(value = "考试ID", required = true) @RequestParam Long examId,
                                 @ApiParam(value = "用户ID", required = true) @RequestParam Long userId) {
        return ResultUtil.ok(basicBatchNumberService.getOrAddByExamIdAndUserId(examId, userId));
    }
}
