package com.qmth.teachcloud.mark.entity;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import org.apache.commons.lang.math.RandomUtils;
import org.apache.commons.lang3.StringUtils;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.annotation.FieldStrategy;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.fasterxml.jackson.databind.annotation.JsonSerialize;
import com.fasterxml.jackson.databind.ser.std.ToStringSerializer;
import com.qmth.teachcloud.common.bean.vo.FilePathVo;
import com.qmth.teachcloud.common.entity.MarkQuestion;
import com.qmth.teachcloud.common.enums.ScanStatus;
import com.qmth.teachcloud.common.enums.mark.SubjectiveStatus;
import com.qmth.teachcloud.mark.dto.mark.ScoreItem;
import com.qmth.teachcloud.mark.utils.BigDecimalUtils;

import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;

/**
 * <p>
 * 考试考生库
 * </p>
 *
 * @author xf
 * @since 2023-09-22
 */
@TableName("mark_student")
@ApiModel(value = "MarkStudent对象", description = "考试考生库")
public class MarkStudent implements Serializable {

    public static final String SPLIT = ";";

    public static final String ANSWER_SPLIT = ",";

    public static final int SECRET_NUMBER_START = 10000000;

    public static final int SECRET_NUMBER_END = 99999999;

    private static final long serialVersionUID = 1L;

    @JsonSerialize(using = ToStringSerializer.class)
    @ApiModelProperty(value = "主键(和exam_student表id一样)")
    @TableId(value = "id")
    private Long id;

    @JsonSerialize(using = ToStringSerializer.class)
    @ApiModelProperty(value = "考试ID")
    private Long examId;

    @ApiModelProperty(value = "科目代码")
    private String courseCode;

    @ApiModelProperty(value = "科目名称")
    private String courseName;

    @ApiModelProperty(value = "试卷编号（交互）")
    private String coursePaperId;

    @ApiModelProperty(value = "试卷编号")
    private String paperNumber;

    @ApiModelProperty(value = "试卷类型")
    private String paperType;

    @ApiModelProperty(value = "密号")
    private String secretNumber;

    @ApiModelProperty(value = "学号")
    private String studentCode;

    @ApiModelProperty(value = "姓名")
    private String studentName;

    @ApiModelProperty(value = "试卷袋编号")
    private String packageCode;

    @ApiModelProperty(value = "校区")
    private String examPlace;

    @ApiModelProperty(value = "考场")
    private String examRoom;

    @ApiModelProperty(value = "备注")
    private String remark;

    @ApiModelProperty(value = "扫描批次号")
    private String batchCode;

    @ApiModelProperty(value = "原图数量")
    private Integer sheetCount;

    @ApiModelProperty(value = "原图地址url")
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private String sheetPath;

    @ApiModelProperty(value = "客观题识别结果")
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private String answers;

    @ApiModelProperty(value = "是否已上传")
    @TableField(value = "is_upload")
    private Boolean upload;

    @ApiModelProperty(value = "是否缺考")
    @TableField(value = "is_absent")
    private Boolean absent;

    @ApiModelProperty(value = "是否人工指定缺考")
    @TableField(value = "is_manual_absent")
    private Boolean manualAbsent;

    @ApiModelProperty(value = "是否违纪")
    @TableField(value = "is_breach")
    private Boolean breach;

    @ApiModelProperty(value = "上传时间")
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private Long uploadTime;

    @ApiModelProperty(value = "检查时间")
    @TableField(value = "check_time", updateStrategy = FieldStrategy.IGNORED)
    private Long checkTime;

    @JsonSerialize(using = ToStringSerializer.class)
    @ApiModelProperty(value = "检查人ID")
    @TableField(value = "check_user_id", updateStrategy = FieldStrategy.IGNORED)
    private Long checkUserId;

    @ApiModelProperty(value = "客观总分")
    @TableField(value = "objective_score", updateStrategy = FieldStrategy.IGNORED)
    private Double objectiveScore;

    @ApiModelProperty(value = "客观得分明细")
    @TableField(value = "objective_score_list", updateStrategy = FieldStrategy.IGNORED)
    private String objectiveScoreList;

    @ApiModelProperty(value = "主观题状态")
    private SubjectiveStatus subjectiveStatus;

    @ApiModelProperty(value = "主观总分")
    @TableField(value = "subjective_score", updateStrategy = FieldStrategy.IGNORED)
    private Double subjectiveScore;

    @ApiModelProperty(value = "主观得分明细")
    @TableField(value = "subjective_score_list", updateStrategy = FieldStrategy.IGNORED)
    private String subjectiveScoreList;

    @ApiModelProperty(value = "学院")
    private String college;

    @ApiModelProperty(value = "专业")
    private String majorName;

    @ApiModelProperty(value = "班级")
    private String className;

    @ApiModelProperty(value = "任课老师")
    private String teacher;

    @ApiModelProperty(value = "任课老师ID")
    private Long teacherId;

    @ApiModelProperty(value = "扫描状态")
    private ScanStatus scanStatus;
    //识别缺考
    private Boolean omrAbsent;
    //识别缺考检查
    private Boolean omrAbsentChecked;
    //是否有填涂
    private Boolean questionFilled;

    //是否人工绑定
    private Boolean assigned;
    //人工绑定确认
    private Boolean assignConfirmed;
    //强制绑定，强制绑定为true时，assigned也为true
    private Boolean invalid;

    // 是否标记异常
    private Boolean absentSuspect;

    // 是否有缺页
    private Boolean incomplete;

    //违纪码
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private String breachCode;
    @TableField(updateStrategy = FieldStrategy.IGNORED)
    private Integer cardNumber;
    private Long examStartTime;
    private Long examEndTime;
    private Long createId;

    @TableField(exist = false)
    private String markPaperStatus;

    public MarkStudent() {
    }

    public MarkStudent(Long id, Long examId, String courseCode, String courseName,
                       String paperNumber, String coursePaperId, String paperType,
                       String studentCode, String studentName, String packageCode,
                       String examPlace, String examRoom, String college, String majorName, String className,
                       Long teacherId, String teacher, Long examStartTime, Long examEndTime, Long createId) {
        this.id = id;
        this.examId = examId;
        this.courseCode = courseCode;
        this.courseName = courseName;
        this.paperNumber = paperNumber;
        this.coursePaperId = coursePaperId;
        this.paperType = paperType;
        this.studentCode = studentCode;
        this.studentName = studentName;
        this.packageCode = packageCode;
        this.examPlace = examPlace;
        this.examRoom = examRoom;
        this.college = college;
        this.majorName = majorName;
        this.className = className;
        this.teacherId = teacherId;
        this.teacher = teacher;
        this.sheetCount = 0;
        this.upload = false;
        this.absent = false;
        this.manualAbsent = false;
        this.breach = false;
        this.absentSuspect = false;
        this.assignConfirmed = false;
        this.subjectiveStatus = SubjectiveStatus.UNMARK;
        this.scanStatus = ScanStatus.UNEXIST;
        this.omrAbsent = false;
        this.omrAbsentChecked = false;
        this.examStartTime = examStartTime;
        this.examEndTime = examEndTime;
        this.createId = createId;
    }

    public Long getId() {
        return id;
    }

    public void setId(Long id) {
        this.id = id;
    }

    public Long getExamId() {
        return examId;
    }

    public void setExamId(Long examId) {
        this.examId = examId;
    }

    public String getCourseCode() {
        return courseCode;
    }

    public void setCourseCode(String courseCode) {
        this.courseCode = courseCode;
    }

    public String getCourseName() {
        return courseName;
    }

    public void setCourseName(String courseName) {
        this.courseName = courseName;
    }

    public String getPaperNumber() {
        return paperNumber;
    }

    public void setPaperNumber(String paperNumber) {
        this.paperNumber = paperNumber;
    }

    public String getPaperType() {
        return paperType;
    }

    public void setPaperType(String paperType) {
        this.paperType = paperType;
    }

    public String getSecretNumber() {
        return secretNumber;
    }

    public void setSecretNumber(String secretNumber) {
        this.secretNumber = secretNumber;
    }

    public String getStudentCode() {
        return studentCode;
    }

    public void setStudentCode(String studentCode) {
        this.studentCode = studentCode;
    }

    public String getStudentName() {
        return studentName;
    }

    public void setStudentName(String studentName) {
        this.studentName = studentName;
    }

    public String getPackageCode() {
        return packageCode;
    }

    public void setPackageCode(String packageCode) {
        this.packageCode = packageCode;
    }

    public String getExamPlace() {
        return examPlace;
    }

    public void setExamPlace(String examPlace) {
        this.examPlace = examPlace;
    }

    public String getExamRoom() {
        return examRoom;
    }

    public void setExamRoom(String examRoom) {
        this.examRoom = examRoom;
    }

    public String getRemark() {
        return remark;
    }

    public void setRemark(String remark) {
        this.remark = remark;
    }

    public String getBatchCode() {
        return batchCode;
    }

    public void setBatchCode(String batchCode) {
        this.batchCode = batchCode;
    }

    public Integer getSheetCount() {
        return sheetCount;
    }

    public void setSheetCount(Integer sheetCount) {
        this.sheetCount = sheetCount;
    }

    public String getSheetPath() {
        return sheetPath;
    }

    public void setSheetPath(String sheetPath) {
        this.sheetPath = sheetPath;
    }

    public String getAnswers() {
        return answers;
    }

    public void setAnswers(String answers) {
        this.answers = answers;
    }

    public Boolean getUpload() {
        return upload;
    }

    public void setUpload(Boolean upload) {
        this.upload = upload;
    }

    public Boolean getAbsent() {
        return absent;
    }

    public void setAbsent(Boolean absent) {
        this.absent = absent;
    }

    public Boolean getManualAbsent() {
        return manualAbsent;
    }

    public void setManualAbsent(Boolean manualAbsent) {
        this.manualAbsent = manualAbsent;
    }

    public Boolean getBreach() {
        return breach;
    }

    public void setBreach(Boolean breach) {
        this.breach = breach;
    }

    public Long getUploadTime() {
        return uploadTime;
    }

    public void setUploadTime(Long uploadTime) {
        this.uploadTime = uploadTime;
    }

    public Long getCheckTime() {
        return checkTime;
    }

    public void setCheckTime(Long checkTime) {
        this.checkTime = checkTime;
    }

    public Long getCheckUserId() {
        return checkUserId;
    }

    public void setCheckUserId(Long checkUserId) {
        this.checkUserId = checkUserId;
    }

    public Double getObjectiveScore() {
        return objectiveScore;
    }

    public void setObjectiveScore(Double objectiveScore) {
        this.objectiveScore = objectiveScore;
    }

    public String getObjectiveScoreList() {
        return objectiveScoreList;
    }

    public void setObjectiveScoreList(String objectiveScoreList) {
        this.objectiveScoreList = objectiveScoreList;
    }

    public SubjectiveStatus getSubjectiveStatus() {
        return subjectiveStatus;
    }

    public void setSubjectiveStatus(SubjectiveStatus subjectiveStatus) {
        this.subjectiveStatus = subjectiveStatus;
    }

    public Double getSubjectiveScore() {
        return subjectiveScore;
    }

    public void setSubjectiveScore(Double subjectiveScore) {
        this.subjectiveScore = subjectiveScore;
    }

    public String getSubjectiveScoreList() {
        return subjectiveScoreList;
    }

    public void setSubjectiveScoreList(String subjectiveScoreList) {
        this.subjectiveScoreList = subjectiveScoreList;
    }

    public String getCollege() {
        return college;
    }

    public void setCollege(String college) {
        this.college = college;
    }

    public String getMajorName() {
        return majorName;
    }

    public void setMajorName(String majorName) {
        this.majorName = majorName;
    }

    public String getClassName() {
        return className;
    }

    public void setClassName(String className) {
        this.className = className;
    }

    public String getTeacher() {
        return teacher;
    }

    public void setTeacher(String teacher) {
        this.teacher = teacher;
    }

    public Long getTeacherId() {
        return teacherId;
    }

    public void setTeacherId(Long teacherId) {
        this.teacherId = teacherId;
    }

    public ScanStatus getScanStatus() {
        return scanStatus;
    }

    public void setScanStatus(ScanStatus scanStatus) {
        this.scanStatus = scanStatus;
    }

    public Boolean getQuestionFilled() {
        return questionFilled;
    }

    public void setQuestionFilled(Boolean questionFilled) {
        this.questionFilled = questionFilled;
    }

    public Boolean getAssigned() {
        return assigned;
    }

    public void setAssigned(Boolean assigned) {
        this.assigned = assigned;
    }

    public Boolean getAbsentSuspect() {
        return absentSuspect;
    }

    public void setAbsentSuspect(Boolean absentSuspect) {
        this.absentSuspect = absentSuspect;
    }

    public Boolean getIncomplete() {
        return incomplete;
    }

    public void setIncomplete(Boolean incomplete) {
        this.incomplete = incomplete;
    }

    public String getBreachCode() {
        return breachCode;
    }

    public void setBreachCode(String breachCode) {
        this.breachCode = breachCode;
    }

    public Boolean getOmrAbsent() {
        return omrAbsent;
    }

    public void setOmrAbsent(Boolean omrAbsent) {
        this.omrAbsent = omrAbsent;
    }

    public Integer getCardNumber() {
        return cardNumber;
    }

    public void setCardNumber(Integer cardNumber) {
        this.cardNumber = cardNumber;
    }

    public static String buildScoreList(List<ScoreItem> scoreList) {
        if (scoreList != null) {
            return StringUtils.join(scoreList, ";");
        } else {
            return null;
        }
    }

    public void randomSecretNumber() {
        secretNumber = String.valueOf((int) (RandomUtils.nextDouble() * (SECRET_NUMBER_END - SECRET_NUMBER_START)) + SECRET_NUMBER_START);
    }

    public Boolean getOmrAbsentChecked() {
        return omrAbsentChecked;
    }

    public void setOmrAbsentChecked(Boolean omrAbsentChecked) {
        this.omrAbsentChecked = omrAbsentChecked;
    }

    public String getCoursePaperId() {
        return coursePaperId;
    }

    public void setCoursePaperId(String coursePaperId) {
        this.coursePaperId = coursePaperId;
    }

    public double getTotalScore() {
        double score = 0;
        if (objectiveScore != null) {
            score = BigDecimalUtils.add(score, objectiveScore);
        }
        if (subjectiveScore != null) {
            score = BigDecimalUtils.add(score, subjectiveScore);
        }
        return score;
    }

    public List<String> getAnswerList() {
        List<String> list = new ArrayList<>();
        if(StringUtils.isNotBlank(answers)){
        	try {
				list = JSON.parseArray(answers, String.class);
			} catch (Exception e) {
				String[] values = StringUtils.split(StringUtils.trimToNull(answers), ANSWER_SPLIT);
		        if (values != null && values.length > 0) {
		            for (String answer : values) {
		                list.add(StringUtils.trim(answer));
		            }
		        }
			}
        }
        return list;
    }

    public List<String> getSheetPathList() {
        List<String> list = new ArrayList<String>();
        String trimSheetPath = StringUtils.trimToNull(sheetPath);
        if (StringUtils.isNotBlank(trimSheetPath)) {
            List<FilePathVo> vos = JSON.parseArray(trimSheetPath, FilePathVo.class);
            for (FilePathVo filePathVo : vos) {
                list.add(JSON.toJSONString(filePathVo));
            }
        }
        return list;
    }

    public void setScoreList(List<ScoreItem> scoreList, boolean objective) {
        if (scoreList != null) {
            if (objective) {
                setObjectiveScoreList(StringUtils.join(scoreList, SPLIT));
            } else {
                setSubjectiveScoreList(StringUtils.join(scoreList, SPLIT));
            }
        }
    }

    public List<ScoreItem> getScoreList(boolean objective) {
        List<ScoreItem> scoreList = new LinkedList<ScoreItem>();
        try {
            String[] values = StringUtils.split(objective ? objectiveScoreList : subjectiveScoreList, SPLIT);
            for (String value : values) {
                ScoreItem item = ScoreItem.parse(value, objective);
                item.setObjective(objective);
                if (item != null) {
                    scoreList.add(item);
                }
            }
        } catch (Exception e) {
        }
        return scoreList;
    }

    public List<ScoreItem> getScoreList(boolean objective, List<MarkQuestion> questionList) {
        List<ScoreItem> scoreList = new LinkedList<ScoreItem>();
        try {
            String[] values = StringUtils.split(objective ? objectiveScoreList : subjectiveScoreList, SPLIT);
            int i = 0;
            for (String value : values) {
                i++;
                if (questionList.size() < i) {
                    break;
                }
                MarkQuestion question = questionList.get(i - 1);
                if (question.getTotalScore() == null || question.getTotalScore() == 0) {
                    continue;
                }
                ScoreItem item = ScoreItem.parse(value, objective);
                item.setObjective(objective);
                item.setMainNumber(question.getMainNumber());
                item.setTitle(question.getMainTitle());
                item.setTotalScore(question.getTotalScore());
                item.setSubNumber(question.getSubNumber());
                if (item != null) {
                    scoreList.add(item);
                }
            }
        } catch (Exception e) {
        }
        return scoreList;
    }

    public Boolean getAssignConfirmed() {
        return assignConfirmed;
    }

    public void setAssignConfirmed(Boolean assignConfirmed) {
        this.assignConfirmed = assignConfirmed;
    }

    public Long getExamStartTime() {
        return examStartTime;
    }

    public void setExamStartTime(Long examStartTime) {
        this.examStartTime = examStartTime;
    }

    public Long getExamEndTime() {
        return examEndTime;
    }

    public void setExamEndTime(Long examEndTime) {
        this.examEndTime = examEndTime;
    }

    public Long getCreateId() {
        return createId;
    }

    public void setCreateId(Long createId) {
        this.createId = createId;
    }

    public String getMarkPaperStatus() {
        return markPaperStatus;
    }

    public void setMarkPaperStatus(String markPaperStatus) {
        this.markPaperStatus = markPaperStatus;
    }
    public Boolean getInvalid() {
        return invalid;
    }

    public void setInvalid(Boolean invalid) {
        this.invalid = invalid;
    }
    @Override
    public String toString() {
        return "MarkStudent{" +
                "id=" + id +
                ", examId=" + examId +
                ", courseCode=" + courseCode +
                ", courseName=" + courseName +
                ", paperNumber=" + paperNumber +
                ", secretNumber=" + secretNumber +
                ", studentCode=" + studentCode +
                ", studentName=" + studentName +
                ", packageCode=" + packageCode +
                ", examPlace=" + examPlace +
                ", examRoom=" + examRoom +
                ", remark=" + remark +
                ", batchCode=" + batchCode +
                ", sheetCount=" + sheetCount +
                ", answers=" + answers +
                ", isUpload=" + upload +
                ", isAbsent=" + absent +
                ", isManualAbsent=" + manualAbsent +
                ", isBreach=" + breach +
                ", uploadTime=" + uploadTime +
                ", checkTime=" + checkTime +
                ", checkUserId=" + checkUserId +
                ", objectiveScore=" + objectiveScore +
                ", objectiveScoreList=" + objectiveScoreList +
                ", subjectiveStatus=" + subjectiveStatus +
                ", subjectiveScore=" + subjectiveScore +
                ", subjectiveScoreList=" + subjectiveScoreList +
                ", college=" + college +
                ", className=" + className +
                ", teacher=" + teacher +
                ", scanStatus=" + scanStatus +
                ", questionFilled=" + questionFilled +
                ", assigned=" + assigned +
                ", invalid=" + invalid +
                ", absentSuspect=" + absentSuspect +
                ", incomplete=" + incomplete +
                ", breachCode=" + breachCode +
                ", omrAbsent=" + omrAbsent +
                ", cardNumber=" + cardNumber +
                ", coursePaperId=" + coursePaperId +
                "}";
    }

}
