package cn.com.qmth.stmms.api.controller;

import java.util.Date;
import java.util.List;

import javax.servlet.http.HttpServletRequest;

import net.sf.json.JSONArray;
import net.sf.json.JSONObject;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.PathVariable;
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.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.com.qmth.stmms.api.dto.RefixStudent;
import cn.com.qmth.stmms.api.exception.ApiException;
import cn.com.qmth.stmms.api.utils.ScanStudentParameter;
import cn.com.qmth.stmms.biz.exam.model.CheckStudent;
import cn.com.qmth.stmms.biz.exam.model.Exam;
import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.exam.service.CheckStudentService;
import cn.com.qmth.stmms.biz.exam.service.ExamService;
import cn.com.qmth.stmms.biz.exam.service.ExamStudentService;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
import cn.com.qmth.stmms.common.annotation.Logging;
import cn.com.qmth.stmms.common.annotation.RoleRequire;
import cn.com.qmth.stmms.common.domain.ApiUser;
import cn.com.qmth.stmms.common.enums.CheckType;
import cn.com.qmth.stmms.common.enums.ExamStatus;
import cn.com.qmth.stmms.common.enums.ExamType;
import cn.com.qmth.stmms.common.enums.LogType;
import cn.com.qmth.stmms.common.enums.Role;
import cn.com.qmth.stmms.common.utils.DateUtils;
import cn.com.qmth.stmms.common.utils.RequestUtils;

@Controller
@RequestMapping("/api/scan")
public class ScanController extends BaseApiController {

    protected static Logger log = LoggerFactory.getLogger(ScanController.class);

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private ExamService examService;

    @Autowired
    private CheckStudentService checkStudentService;

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private MarkLibraryService libraryService;

    private static final String PAPER_TYPES_REGEX = "[a-zA-Z#]";

    /**
     * 上传考生识别结果
     *
     * @param request
     * @param examId
     * @param scStudentParameter
     * @return
     */
    @Logging(menu = "扫描端-考生识别上传", type = LogType.UPDATE)
    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCANNER, Role.SCAN_ADMIN })
    @RequestMapping(value = "/student/{examId}", method = RequestMethod.POST)
    @ResponseBody
    public JSONArray saveStudent(HttpServletRequest request, @PathVariable Integer examId,
            @RequestBody ScanStudentParameter[] scStudentParameter) {
        ApiUser user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        JSONArray array = new JSONArray();
        // 判断上传权限
        if (exam == null || !exam.getSchoolId().equals(user.getSchoolId())
                || !ExamStatus.START.equals(exam.getStatus()) || !ExamType.SCAN_IMAGE.equals(exam.getType())) {
            throw ApiException.EXAM_NOT_ACCESSIBLED;
        }
        if (scStudentParameter != null && scStudentParameter.length > 0) {
            for (ScanStudentParameter sc : scStudentParameter) {
                ExamStudent student = studentService.findByExamIdAndExamNumber(examId, sc.getExamNumber());
                if (student != null) {
                    student.setUpload(true);
                    student.setAbsent(sc.isAbsent());
                    student.setAnswers(sc.getAnswers().toUpperCase());
                    student.setBatchCode(sc.getBatchCode());
                    student.setSliceCount(sc.getSliceCount());
                    student.setSheetCount(sc.getSheetCount());
                    if (sc.getPaperType() != null) {
                        if (sc.getPaperType().matches(PAPER_TYPES_REGEX)) {
                            student.setPaperType(sc.getPaperType());
                        } else {
                            continue;
                        }
                    }
                    student.setCardNumber(sc.getCardNumber());
                    // 同步更新评卷任务
                    if (saveUploadStudent(student)) {
                        JSONObject obj = new JSONObject();
                        obj.accumulate("examNumber", student.getExamNumber());
                        obj.accumulate("uploadTime", DateUtils.formatDateTime(student.getUploadTime()));
                        array.add(obj);
                        // 增加人工审核数据
                        if (sc.isManual()) {
                            checkStudentService.save(new CheckStudent(student.getId(), examId,
                                    student.getSubjectCode(), CheckType.MANUAL));
                        }
                    }
                }
            }
        }
        return array;
    }

    @Logging(menu = "扫描端-考生识别上传取消", type = LogType.UPDATE)
    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCANNER, Role.SCAN_ADMIN })
    @RequestMapping(value = "/student/delete", method = RequestMethod.POST)
    @ResponseBody
    public JSONObject deleteStudent(HttpServletRequest request, @RequestParam Integer examId,
            @RequestParam String examNumber, @RequestParam(required = false, defaultValue = "true") Boolean checkMark) {
        ApiUser user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        // 判断上传权限
        if (exam == null || !exam.getSchoolId().equals(user.getSchoolId())
                || !ExamStatus.START.equals(exam.getStatus()) || !ExamType.SCAN_IMAGE.equals(exam.getType())) {
            throw ApiException.EXAM_NOT_ACCESSIBLED;
        }
        examNumber = validate("examNumber", examNumber, true, 32);
        ExamStudent student = studentService.findByExamIdAndExamNumber(examId, examNumber);
        if (student == null) {
            throw ApiException.QUERY_PARAM_ERROR.replaceMessage("examNumber invalid");
        }
        if (checkMark) {
            List<MarkLibrary> list = libraryService.findByStudentId(student.getId());
            if (!list.isEmpty()) {
                throw ApiException.QUERY_PARAM_ERROR.replaceMessage("examNumber has library");
            }
        }
        student.setPaperType("#");
        JSONObject obj = new JSONObject();
        if (studentService.resetScanInfo(student)) {
            subjectService.updateUploadCount(
                    student.getExamId(),
                    student.getSubjectCode(),
                    (int) studentService.countUploadedByExamIdAndSubjectCode(student.getExamId(),
                            student.getSubjectCode()));
            checkStudentService.deleteByStudentId(student.getId());
            obj.accumulate("examNumber", student.getExamNumber());
            obj.accumulate("updateTime", DateUtils.formatDateTime(new Date()));
        }
        return obj;
    }

    /**
     * 上传考生识别结果
     *
     * @param request
     * @param examId
     * @param scStudentParameter
     * @return
     */
    @Logging(menu = "扫描端-考生二次识别客观题上传", type = LogType.UPDATE)
    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SCANNER, Role.SCAN_ADMIN })
    @RequestMapping(value = "/student/answer/{examId}", method = RequestMethod.POST)
    @ResponseBody
    public JSONArray updateStudentAnswer(HttpServletRequest request, @PathVariable Integer examId,
            @RequestBody RefixStudent[] refixStudents) {
        ApiUser user = RequestUtils.getApiUser(request);
        Exam exam = examService.findById(examId);
        JSONArray array = new JSONArray();
        // 判断上传权限
        if (exam == null || !exam.getSchoolId().equals(user.getSchoolId())
                || !ExamStatus.START.equals(exam.getStatus()) || !ExamType.SCAN_IMAGE.equals(exam.getType())) {
            throw ApiException.EXAM_NOT_ACCESSIBLED;
        }
        if (refixStudents != null && refixStudents.length > 0) {
            for (RefixStudent sc : refixStudents) {
                ExamStudent student = studentService.findByExamIdAndExamNumber(examId, sc.getExamNumber());
                if (student != null && student.isUpload()) {
                    // 同步更新评卷任务,返回失败的考生
                    student.setAnswers(sc.getAnswers());
                    if (!saveUploadStudent(student)) {
                        JSONObject obj = new JSONObject();
                        obj.accumulate("examNumber", student.getExamNumber());
                        array.add(obj);
                    }
                } else {
                    JSONObject obj = new JSONObject();
                    obj.accumulate("examNumber", sc.getExamNumber());
                    array.add(obj);
                }
            }
        }
        return array;
    }
}
