package com.qmth.distributed.print.api;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.qmth.boot.api.annotation.Aac;
import com.qmth.boot.api.annotation.BOOL;
import com.qmth.boot.api.constant.ApiConstant;
import com.qmth.distributed.print.business.bean.dto.*;
import com.qmth.distributed.print.business.bean.params.ClientLoginParam;
import com.qmth.distributed.print.business.service.ClientService;
import com.qmth.teachcloud.common.bean.result.LoginResult;
import com.qmth.teachcloud.common.entity.BasicSchool;
import com.qmth.teachcloud.common.entity.SysUser;
import com.qmth.teachcloud.common.enums.AppSourceEnum;
import com.qmth.teachcloud.common.enums.ExceptionResultEnum;
import com.qmth.teachcloud.common.service.CommonCacheService;
import com.qmth.teachcloud.common.service.SysUserService;
import com.qmth.teachcloud.common.service.TeachcloudCommonService;
import com.qmth.teachcloud.common.util.Result;
import com.qmth.teachcloud.common.util.ResultUtil;
import io.swagger.annotations.*;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import javax.validation.Valid;
import java.security.NoSuchAlgorithmException;
import java.util.List;
import java.util.Map;
import java.util.Objects;

/**
 * 客户端接口（打印端）
 */
@Api(tags = "客户端Controller")
@RestController
@RequestMapping(ApiConstant.DEFAULT_URI_PREFIX + "/${prefix.url.client}")
//@Validated
public class ClientController {

    @Resource
    ClientService clientService;

    @Resource
    SysUserService sysUserService;

    @Resource
    CommonCacheService commonCacheService;

    @Resource
    TeachcloudCommonService teachcloudCommonService;

    /**
     * 登录
     *
     * @param login 登录参数
     */
    @ApiOperation(value = "登录")
    @RequestMapping(value = "/user/login", method = RequestMethod.POST)
    @ApiResponses({@ApiResponse(code = 200, message = "用户信息", response = LoginResult.class)})
    @Aac(auth = BOOL.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 = commonCacheService.schoolCache(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();
        }
        // 是否有客户端权限
        clientService.checkPrivilege(sysUser.getId());

        return ResultUtil.ok(teachcloudCommonService.login(login.getPassword(), sysUser, AppSourceEnum.SYSTEM));
    }

    /**
     * 试卷打样-列表
     *
     * @param machineCode 机器唯一码
     * @param orgId       机构ID
     * @param printPlanId 印刷计划ID
     * @param courseCode  课程代码
     * @param paperNumber 试卷编号
     * @param isTry       是否打样
     * @param isPass      是否合格
     * @param pageNumber  分页参数
     * @param pageSize    分页参数
     */
    @ApiOperation(value = "试卷打样-列表")
    @RequestMapping(value = "/paper_try/list", method = RequestMethod.POST)
    public Result paperTryList(@RequestParam("machineCode") String machineCode,
                               @RequestParam("orgId") Long orgId,
                               @RequestParam(value = "printPlanId", required = false) Long printPlanId,
                               @RequestParam(value = "courseCode", required = false) String courseCode,
                               @RequestParam(value = "paperNumber", required = false) String paperNumber,
                               @RequestParam(value = "isTry", required = false) Boolean isTry,
                               @RequestParam(value = "isPass", required = false) Boolean isPass,
                               @RequestParam Integer pageNumber,
                               @RequestParam Integer pageSize) {
        IPage<ClientExamTaskDto> examTasks = clientService.listTryTask(machineCode, orgId, printPlanId, courseCode, paperNumber, isTry, isPass, pageNumber, pageSize);
        return ResultUtil.ok(examTasks);
    }

    /**
     * 试卷打样-查看/试印/重印
     *
     * @param examTaskId 命题任务ID
     */
    @ApiOperation(value = "试卷打样-查看/试印/重印")
    @RequestMapping(value = "/paper_try/print", method = RequestMethod.POST)
    public Result paperTryPrint(@RequestParam("printPlanId") Long printPlanId,
                                @RequestParam("examTaskId") Long examTaskId) {
        List<Map<String, String>> list = clientService.getPaperUrl(printPlanId, examTaskId);
        return ResultUtil.ok(list);
    }

    /**
     * 试卷打样-批量试印
     *
     * @param machineCode 机器码
     * @param orgId       机构ID
     * @param printPlanId 印刷计划ID
     * @param courseCode  课程代码
     * @param paperNumber 试卷编号
     * @param isTry       是否打样
     * @param isPass      是否通过
     */
    @ApiOperation(value = "试卷打样-批量试印")
    @RequestMapping(value = "/paper_try/print_batch", method = RequestMethod.POST)
    public Result printBatch(@RequestParam("machineCode") String machineCode,
                             @RequestParam("orgId") Long orgId,
                             @RequestParam(value = "printPlanId", required = false) Long printPlanId,
                             @RequestParam(value = "courseCode", required = false) String courseCode,
                             @RequestParam(value = "paperNumber", required = false) String paperNumber,
                             @RequestParam(value = "isTry", required = false) Boolean isTry,
                             @RequestParam(value = "isPass", required = false) Boolean isPass) {
        List<Map<String, Object>> urls = clientService.getBatchUrl(machineCode, orgId, printPlanId, courseCode, paperNumber, isTry, isPass);
        return ResultUtil.ok(urls);
    }

    /**
     * 试卷打样-标记合格状态
     *
     * @param machineCode 机器码
     * @param isPass      是否通过
     * @param userId      用户Id
     */
    @ApiOperation(value = "试卷打样-标记合格状态")
    @RequestMapping(value = "/paper_try/tag_pass", method = RequestMethod.POST)
    public Result paperTryTagPass(@RequestParam("printPlanId") Long printPlanId,
                                  @RequestParam("courseCode") String courseCode,
                                  @RequestParam("courseName") String courseName,
                                  @RequestParam("paperNumber") String paperNumber,
                                  @RequestParam("machineCode") String machineCode,
                                  @RequestParam("isPass") Boolean isPass,
                                  @RequestParam("userId") Long userId) {
        Boolean isSuccess = clientService.tagPass(printPlanId, courseCode, courseName, paperNumber, machineCode, isPass, userId);
        return ResultUtil.ok(isSuccess);
    }

    /**
     * 印刷管理-查询列表
     *
     * @param machineCode   机器码
     * @param orgId         机构ID
     * @param printPlanId   印刷计划ID
     * @param status        状态
     * @param courseCode    课程代码
     * @param paperNumber   试卷编号
     * @param examPlace     考点
     * @param examRoom      考场
     * @param examStartTime 考试时间（开始）
     * @param examEndTime   考试时间（结束）
     * @param isDownload    是否缓存
     * @param validate      是否校验
     * @param pageNumber    分页参数
     * @param pageSize      分页参数
     */
    @ApiOperation(value = "印刷管理-查询列表")
    @RequestMapping(value = "/print/task_list", method = RequestMethod.POST)
    public Result printTaskList(@RequestParam("machineCode") String machineCode,
                                @RequestParam("orgId") Long orgId,
                                @RequestParam(value = "printPlanId", required = false) String printPlanId,
                                @RequestParam(value = "status", required = false) String status,
                                @RequestParam(value = "courseCode", required = false) String courseCode,
                                @RequestParam(value = "paperNumber", required = false) String paperNumber,
                                @RequestParam(value = "examPlace", required = false) String examPlace,
                                @RequestParam(value = "examRoom", required = false) String examRoom,
                                @RequestParam(value = "examStartTime", required = false) Long examStartTime,
                                @RequestParam(value = "examEndTime", required = false) Long examEndTime,
                                @RequestParam(value = "isDownload", required = false) Boolean isDownload,
                                @RequestParam(value = "validate", required = false) Boolean validate,
                                @RequestParam Integer pageNumber,
                                @RequestParam Integer pageSize) {
        IPage<ClientPrintTaskDto> printTaskDtoIPage = clientService.listClientPrintTask(machineCode, orgId, printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate, pageNumber, pageSize);
        return ResultUtil.ok(printTaskDtoIPage);
    }


    /**
     * 印刷管理-导出
     *
     * @param response      response
     * @param machineCode   机器码
     * @param orgId         机构ID
     * @param printPlanId   印刷计划ID
     * @param status        状态
     * @param courseCode    课程代码
     * @param paperNumber   试卷编号
     * @param examPlace     考点
     * @param examRoom      考场
     * @param examStartTime 考试时间（开始）
     * @param examEndTime   考试时间（结束）
     * @param isDownload    是否缓存
     * @param validate      是否核验
     */
    @ApiOperation(value = "印刷管理-导出")
    @RequestMapping(value = "/print/task_list_export", method = RequestMethod.POST)
    public void printTaskListExport(HttpServletResponse response,
                                    @RequestParam("machineCode") String machineCode,
                                    @RequestParam("orgId") Long orgId,
                                    @RequestParam(value = "printPlanId", required = false) String printPlanId,
                                    @RequestParam(value = "status", required = false) String status,
                                    @RequestParam(value = "courseCode", required = false) String courseCode,
                                    @RequestParam(value = "paperNumber", required = false) String paperNumber,
                                    @RequestParam(value = "examPlace", required = false) String examPlace,
                                    @RequestParam(value = "examRoom", required = false) String examRoom,
                                    @RequestParam(value = "examStartTime", required = false) Long examStartTime,
                                    @RequestParam(value = "examEndTime", required = false) Long examEndTime,
                                    @RequestParam(value = "isDownload", required = false) Boolean isDownload,
                                    @RequestParam(value = "validate", required = false) Boolean validate) throws Exception {
        clientService.exportClientPrintTask(response, machineCode, orgId, printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate);
    }

    /**
     * 印刷管理-汇总数据查询
     *
     * @param machineCode   机器码
     * @param orgId         机构ID
     * @param printPlanId   印刷计划ID
     * @param status        状态
     * @param courseCode    课程代码
     * @param paperNumber   试卷编号
     * @param examPlace     考点
     * @param examRoom      考场
     * @param examStartTime 考试时间（开始）
     * @param examEndTime   考试时间（结束）
     * @param isDownload    是否缓存
     * @param validate      是否校验
     */
    @ApiOperation(value = "印刷管理-汇总数据查询")
    @RequestMapping(value = "/print/task_total_data", method = RequestMethod.POST)
    public Result printTaskTotalData(@RequestParam("machineCode") String machineCode,
                                     @RequestParam("orgId") Long orgId,
                                     @RequestParam(value = "printPlanId", required = false) String printPlanId,
                                     @RequestParam(value = "status", required = false) String status,
                                     @RequestParam(value = "courseCode", required = false) String courseCode,
                                     @RequestParam(value = "paperNumber", required = false) String paperNumber,
                                     @RequestParam(value = "examPlace", required = false) String examPlace,
                                     @RequestParam(value = "examRoom", required = false) String examRoom,
                                     @RequestParam(value = "examStartTime", required = false) Long examStartTime,
                                     @RequestParam(value = "examEndTime", required = false) Long examEndTime,
                                     @RequestParam(value = "isDownload", required = false) Boolean isDownload,
                                     @RequestParam(value = "validate", required = false) Boolean validate) {
        ClientPrintTaskTotalDto clientPrintTaskTotalDto = clientService.taskTotalData(printPlanId, orgId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate, machineCode);
        return ResultUtil.ok(clientPrintTaskTotalDto);
    }


    /**
     * 印刷管理-查看
     *
     * @param examDetailId 命题任务ID
     */
    @ApiOperation(value = "印刷管理-查看")
    @RequestMapping(value = "/print/preview", method = RequestMethod.POST)
    public Result printPreview(@RequestParam("examDetailId") Long examDetailId) {
        Map<String, Object> map = clientService.getUrlByExamDetailId(examDetailId);
        return ResultUtil.ok(map);
    }

    /**
     * 印刷管理-印刷/缓存数据
     *
     * @param examDetailId 考场ID
     * @param machineCode  机器码
     * @param printUser    打印员
     */
    @ApiOperation(value = "印刷管理-印刷/缓存数据")
    @RequestMapping(value = "/print/get_print_data", method = RequestMethod.POST)
    public Result printGetPrintData(@RequestParam("examDetailId") Long examDetailId,
                                    @RequestParam("machineCode") String machineCode,
                                    @RequestParam("isPrint") Boolean isPrint,
                                    @RequestParam(value = "printUser", required = false) String printUser) {
        Map<String, Object> map = clientService.getPrintData(examDetailId, machineCode, isPrint, printUser);
        return ResultUtil.ok(map);
    }

    /**
     * 印刷管理-批量缓存数据
     *
     * @param orgId       机构ID
     * @param machineCode 机器码
     */
    @ApiOperation(value = "印刷管理-批量缓存数据")
    @RequestMapping(value = "/print/get_print_data_batch", method = RequestMethod.POST)
    public Result printGetPrintDataBatch(@RequestParam("machineCode") String machineCode,
                                         @RequestParam("orgId") Long orgId,
                                         @RequestParam(value = "printPlanId", required = false) String printPlanId,
                                         @RequestParam(value = "status", required = false) String status,
                                         @RequestParam(value = "courseCode", required = false) String courseCode,
                                         @RequestParam(value = "paperNumber", required = false) String paperNumber,
                                         @RequestParam(value = "examPlace", required = false) String examPlace,
                                         @RequestParam(value = "examRoom", required = false) String examRoom,
                                         @RequestParam(value = "examStartTime", required = false) Long examStartTime,
                                         @RequestParam(value = "examEndTime", required = false) Long examEndTime,
                                         @RequestParam(value = "isDownload", required = false) Boolean isDownload,
                                         @RequestParam(value = "validate", required = false) Boolean validate) {
        List<Map<String, Object>> list = clientService.getPrintDataBatch(machineCode, orgId, printPlanId, status, courseCode, paperNumber, examPlace, examRoom, examStartTime, examEndTime, isDownload, validate);
        return ResultUtil.ok(list);
    }

    /**
     * @param examDetailId 考场ID
     * @param machineCode  机器码
     * @param isDownload   是否缓存
     */
    @ApiOperation(value = "印刷管理-缓存后更新状态")
    @RequestMapping(value = "/print/update_download", method = RequestMethod.POST)
    public Result updateDownload(@RequestParam("examDetailId") Long examDetailId,
                                 @RequestParam("machineCode") String machineCode,
                                 @RequestParam("isDownload") Boolean isDownload) {
        Boolean isSuccess = clientService.updateDownload(examDetailId, machineCode, isDownload);
        return ResultUtil.ok(isSuccess);
    }

    /**
     * 印刷管理-校验
     *
     * @param examDetailId 考场ID
     * @param packageCode  机器码
     * @param lastCode     校验条码号
     */
    @ApiOperation(value = "印刷管理-校验")
    @RequestMapping(value = "/print/validate_data", method = RequestMethod.POST)
    public Result dataCheck(@RequestParam("examDetailId") Long examDetailId,
                            @RequestParam("packageCode") String packageCode,
                            @RequestParam("lastCode") String lastCode) {
        Boolean isSuccess = clientService.validateData(examDetailId, packageCode, lastCode);
        return ResultUtil.ok(isSuccess);
    }

    /**
     * 印刷管理-更新打印进度
     *
     * @param examDetailId  考场ID
     * @param machineCode   机器码
     * @param printProgress 打印进度
     */
    @ApiOperation(value = "印刷管理-更新打印进度")
    @RequestMapping(value = "/print/update_progress", method = RequestMethod.POST)
    public Result updateProgress(@RequestParam("examDetailId") Long examDetailId,
                                 @RequestParam("machineCode") String machineCode,
                                 @RequestParam("printProgress") Integer printProgress,
                                 @RequestParam(value = "isPrint", required = false) Boolean isPrint) {
        Boolean isSuccess = clientService.updatePrintProgress(examDetailId, machineCode, printProgress, isPrint);
        return ResultUtil.ok(isSuccess);
    }

    /**
     * 重打-查询考生列表
     *
     * @param examDetailId 考场ID
     * @param ticketNumber 准考证号
     * @param studentName  学号
     * @param courseCode   课程代码
     */
    @ApiOperation(value = "重打-查询考生列表")
    @RequestMapping(value = "/print/list_student", method = RequestMethod.POST)
    public Result listStudent(@RequestParam("examDetailId") Long examDetailId,
                              @RequestParam(value = "ticketNumber", required = false) String ticketNumber,
                              @RequestParam(value = "studentName", required = false) String studentName,
                              @RequestParam(value = "courseCode", required = false) String courseCode,
                              @RequestParam Integer pageNumber,
                              @RequestParam Integer pageSize) {
        IPage<ClientExamStudentDto> examStudentDtoIPage = clientService.listStudent(examDetailId, ticketNumber, studentName, courseCode, pageNumber, pageSize);
        return ResultUtil.ok(examStudentDtoIPage);
    }

    /**
     * 重打-内容查询
     *
     * @param examDetailId 考场ID
     * @param ticketNumber 准考证号
     * @param type         类型
     */
    @ApiOperation(value = "重打-内容查询")
    @RequestMapping(value = "/print/get_reprint_data", method = RequestMethod.POST)
    public Result getReprintData(@RequestParam("examDetailId") Long examDetailId,
                                 @RequestParam("ticketNumber") String ticketNumber,
                                 @RequestParam("type") String type) {
        Map<String, Object> map = clientService.getReprintData(examDetailId, ticketNumber, type);
        return ResultUtil.ok(map);
    }

    /**
     * 统计查询-查询列表
     *
     * @param orgId         机构ID
     * @param printPlanId   印刷计划ID
     * @param examPlace     考点
     * @param examStartTime 考试时间（开始）
     * @param examEndTime   考试时间（结束）
     * @param courseCode    课程代码
     * @param paperNumber   试卷编号
     * @param pageNumber    分页参数
     * @param pageSize      分页参数
     */
    @ApiOperation(value = "统计查询-查询列表")
    @RequestMapping(value = "/print/statistics_list", method = RequestMethod.POST)
    public Result printStatisticsList(@RequestParam("orgId") Long orgId,
                                      @RequestParam(value = "printPlanId", required = false) String printPlanId,
                                      @RequestParam(value = "examPlace", required = false) String examPlace,
                                      @RequestParam(value = "examStartTime", required = false) Long examStartTime,
                                      @RequestParam(value = "examEndTime", required = false) Long examEndTime,
                                      @RequestParam(value = "courseCode", required = false) String courseCode,
                                      @RequestParam(value = "paperNumber", required = false) String paperNumber,
                                      @RequestParam Integer pageNumber,
                                      @RequestParam Integer pageSize) {
        IPage<ClientPrintStatisticsDto> statisticsDtoIPage = clientService.listClientPrintStatistics(orgId, printPlanId, examPlace, examStartTime, examEndTime, courseCode, paperNumber, pageNumber, pageSize);
        return ResultUtil.ok(statisticsDtoIPage);
    }

    /**
     * 统计查询-汇总数据查询
     *
     * @param orgId         机构ID
     * @param printPlanId   印刷计划Id
     * @param examPlace     考点
     * @param examStartTime 考试时间（开始）
     * @param examEndTime   考试时间（结束）
     * @param courseCode    课程代码
     * @param paperNumber   试卷编号
     */
    @ApiOperation(value = "统计查询-汇总数据查询")
    @RequestMapping(value = "/print/statistics_total_data", method = RequestMethod.POST)
    public Result printStatisticsTotalData(@RequestParam("orgId") Long orgId,
                                           @RequestParam(value = "printPlanId", required = false) String printPlanId,
                                           @RequestParam(value = "examPlace", required = false) String examPlace,
                                           @RequestParam(value = "examStartTime", required = false) Long examStartTime,
                                           @RequestParam(value = "examEndTime", required = false) Long examEndTime,
                                           @RequestParam(value = "courseCode", required = false) String courseCode,
                                           @RequestParam(value = "paperNumber", required = false) String paperNumber) {
        ClientPrintStatisticsTotalDto statisticsTotalDto = clientService.clientStatisticsTotalData(orgId, printPlanId, examPlace, examStartTime, examEndTime, courseCode, paperNumber);
        return ResultUtil.ok(statisticsTotalDto);
    }
}
