package cn.com.qmth.stmms.admin.exam;

import java.util.HashMap;
import java.util.LinkedList;
import java.util.List;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
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 org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import cn.com.qmth.stmms.biz.campus.model.Campus;
import cn.com.qmth.stmms.biz.campus.service.CampusService;
import cn.com.qmth.stmms.biz.exam.model.Exam;
import cn.com.qmth.stmms.biz.exam.model.ExamPackage;
import cn.com.qmth.stmms.biz.exam.model.ExamStudent;
import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
import cn.com.qmth.stmms.biz.exam.service.ExamPackageService;
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.service.MarkService;
import cn.com.qmth.stmms.common.auth.annotation.RoleRequire;
import cn.com.qmth.stmms.common.domain.WebUser;
import cn.com.qmth.stmms.common.enums.Role;
import cn.com.qmth.stmms.common.utils.ExportExcel;
import cn.com.qmth.stmms.common.utils.ImportExcel;
import cn.com.qmth.stmms.common.utils.PictureUrlBuilder;
import cn.com.qmth.stmms.common.utils.RequestUtils;

import com.google.common.collect.Lists;

@Controller("examStudentController")
@RequestMapping("/admin/exam/student")
public class StudentController extends BaseExamController {

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

    @Autowired
    private CampusService campusService;

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private ExamService examService;

    @Autowired
    private MarkService markService;
    
    @Autowired
    private ExamPackageService packageService;

    @Value("${sheet.image.server}")
    private String imageServer;
    
    @Value("${package.image.server}")
    private String packageServer;

    @RequestMapping
    public String list(Model model, HttpServletRequest request, ExamStudentSearchQuery query) {
        WebUser wu = RequestUtils.getWebUser(request);
        int examId = getSessionExamId(request);
        query.setExamId(examId);
        if (query.getBatchCode() != null) {
            query.setBatchCode(StringUtils.upperCase(query.getBatchCode()));
        }
        subjectFilter(query, wu);
        query = studentService.findByQuery(query);
        if (query.getCurrentCount() > 0) {
            for (ExamStudent student : query.getResult()) {
                student.setSubject(subjectService.find(student.getExamId(), student.getSubjectCode()));
                buildSheetUrl(student);
                buildPackageUrl(student);
            }
            model.addAttribute("studentList", query.getResult());
        }
        model.addAttribute("query", query);
        model.addAttribute("campusList", studentService.findDistinctCampusName(examId));
        model.addAttribute("subjectList", getExamSubject(examId, wu));
        model.addAttribute("levelList", subjectService.listLevel(examId));
        model.addAttribute("categoryList", subjectService.listCategory(examId));
        model.addAttribute("imageServer", imageServer);
        model.addAttribute("packageServer", packageServer);
        return "modules/exam/studentList";
    }

    @RequestMapping(value = "/add")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String form(HttpServletRequest request, ExamStudent student, Model model) {
        Exam exam = examService.findById(getSessionExamId(request));
        model.addAttribute("student", student);
        model.addAttribute("subjectList", getExamSubject(exam.getId(), RequestUtils.getWebUser(request)));
        model.addAttribute("campusList", studentService.findDistinctCampusName(exam.getId()));
        return "modules/exam/studentForm";
    }

    @RequestMapping(value = "/update")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String update(HttpServletRequest request, Integer id, Model model) {
        Exam exam = examService.findById(getSessionExamId(request));
        ExamStudent student = studentService.findById(id);
        model.addAttribute("student", student);
        model.addAttribute("subjectList", getExamSubject(exam.getId(), RequestUtils.getWebUser(request)));
        model.addAttribute("campusList", studentService.findDistinctCampusName(exam.getId()));
        return "modules/exam/studentForm";
    }

    @RequestMapping(value = "/save")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String save(ExamStudent student, Model model, RedirectAttributes redirectAttributes,
            HttpServletRequest request, HttpServletResponse response) {
        int examId = getSessionExamId(request);
        Exam exam = examService.findById(examId);
        ExamSubject subject = subjectService.find(examId, student.getSubjectCode());
        Campus campus = campusService.findBySchoolAndName(exam.getSchoolId(), student.getCampusName());
        if (subject == null) {
            addMessage(redirectAttributes, "科目不存在");
        } else if (campus == null) {
            addMessage(redirectAttributes, "学习中心不存在");
        } else {
            if (student.getId() != null) {
                ExamStudent previous = studentService.findById(student.getId());
                if (previous != null) {
                	// String previousSubjectCode = previous.getSubjectCode();
                	student.setExamId(examId);
                	ExamStudent old = checkExamNumber(student, new HashMap<String, ExamStudent>(), new HashMap<String, ExamStudent>());
                	if(old !=null && !old.getExamNumber().equals(previous.getExamNumber())){
                		addMessage(redirectAttributes, "准考证号" + student.getExamNumber() + "已经存在");
                		return "redirect:/admin/exam/student";
                	}
                	if (!previous.isUpload()) {
                        // 还未扫描上传的考生，才能修改准考证号、学习中心、科目
                        previous.setCampusName(student.getCampusName());
                        previous.setSubjectCode(subject.getCode());
                        previous.setSubjectName(subject.getName());
                        previous.setExamNumber(student.getExamNumber());
                	}
                    previous.setStudentCode(student.getStudentCode());
                    previous.setName(student.getName());
                    previous.setPackageCode(student.getPackageCode());
                    previous.setCollege(student.getCollege());
            		previous.setClassName(student.getClassName());
            		previous.setTeacher(student.getTeacher());
                    previous = studentService.save(previous);
                        // if
                        // (!previousSubjectCode.equals(previous.getSubjectCode()))
                        // {
                        // // 更新科目上传考生数量
                        // subjectService.updateUploadCount(examId,
                        // previousSubjectCode);
                        // subjectService.updateUploadCount(examId,
                        // previous.getSubjectCode());
                        // // 删除已生成的评卷任务
                        // libraryService.deleteByStudent(previous.getId());
                        // // 更新科目大题任务数量
                        // groupService.updateLibraryCount(examId,
                        // previousSubjectCode);
                        // // 重置科目所有大题构造评卷任务时间
                        // groupService.resetBuildTime(examId,
                        // previous.getSubjectCode());
                        // }
                        addMessage(redirectAttributes, "考生" + previous.getName() + "保存成功");
                } else {
                    addMessage(redirectAttributes, "考生不存在");
                }
            } else {
                student.setExamId(examId);
                student.setSchoolId(exam.getSchoolId());
                student.setSubjectName(subject.getName());
                student.setAbsent(false);
                student.setUpload(false);
                student.setException(false);
                student.setSliceCount(0);
                student.setSheetCount(0);
                student.setObjectiveScore(0d);
                student.setSubjectiveScore(0d);
                ExamStudent old = checkExamNumber(student, new HashMap<String, ExamStudent>(), new HashMap<String, ExamStudent>());
                if(old!=null){
                	addMessage(redirectAttributes, "准考证号" + student.getExamNumber() + "已经存在");
                	return "redirect:/admin/exam/student";
                } else{
                	studentService.save(student);
                }
                addMessage(redirectAttributes, "考生" + student.getName() + "保存成功");
            }
        }
        return "redirect:/admin/exam/student";
    }

    @RequestMapping(value = "/delete")
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String delete(Integer id, RedirectAttributes redirectAttributes) {
        ExamStudent student = studentService.findById(id);
        if (student != null) {
            studentService.deleteById(id);
            markService.deleteByStudent(student);
            subjectService.updateUploadCount(student.getExamId(), student.getSubjectCode(), (int) studentService
                    .countUploadedByExamIdAndSubjectCode(student.getExamId(), student.getSubjectCode()));
            addMessage(redirectAttributes, "删除考生成功");
        } else {
            addMessage(redirectAttributes, "找不到对应的考生");
        }
        return "redirect:/admin/exam/student";
    }

    @RequestMapping(value = "/template")
    public String importFileTemplate(HttpServletResponse response, RedirectAttributes redirectAttributes) {
        try {
            String fileName = "考生数据导入模板.xlsx";
            List<ExamStudent> list = Lists.newArrayList();
            list.add(new ExamStudent());
            new ExportExcel("考生数据", ExamStudent.class, 2).setDataList(list).write(response, fileName).dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "导入模板下载失败！失败信息：" + e.getMessage());
        }
        return "redirect:/admin/exam/student";
    }

    @RequestMapping(value = "/import", method = RequestMethod.POST)
    @RoleRequire(Role.SCHOOL_ADMIN)
    public String importFile(HttpServletRequest request, MultipartFile file, RedirectAttributes redirectAttributes) {
        int examId = getSessionExamId(request);
        Exam exam = examService.findById(examId);
        try {
            int successNum = 0;
            int failureNum = 0;
            StringBuilder failureMsg = new StringBuilder();
            ImportExcel ei = new ImportExcel(file, 1, 0);
            List<ExamStudent> list = ei.getDataList(ExamStudent.class);
            List<ExamStudent> saveList = new LinkedList<ExamStudent>();
            Map<String, ExamStudent> saveMap = new HashMap<String, ExamStudent>();
            Map<String, ExamStudent> current = null;
            // 当数据库中已存在考生小于一定数量，则一次性取出所有考生，用于校验准考证号是否重复
            if (studentService.countByExamId(examId) < 10000) {
                current = new HashMap<String, ExamStudent>();
                List<ExamStudent> list2 = studentService.findByExamId(examId);
                for (ExamStudent s : list2) {
                    current.put(s.getExamNumber(), s);
                }
            }

            for (ExamStudent student : list) {
                if (StringUtils.isBlank(student.getExamNumber()) || StringUtils.isBlank(student.getName())
                        || StringUtils.isBlank(student.getSubjectCode())
                        || StringUtils.isBlank(student.getSubjectName())
                        || StringUtils.isBlank(student.getCampusName())
                        || StringUtils.isBlank(student.getCollege())
                        || StringUtils.isBlank(student.getClassName())
                        || StringUtils.isBlank(student.getTeacher())
                        || StringUtils.isBlank(student.getStudentCode()) ) {
                    continue;
                }

                student.setExamId(examId);
                student.setSchoolId(exam.getSchoolId());
                student.setAbsent(false);
                student.setUpload(false);
                student.setException(false);
                student.setSliceCount(0);
                student.setSheetCount(0);
                student.setObjectiveScore(0d);
                student.setSubjectiveScore(0d);
                ExamStudent previous = checkExamNumber(student, current, saveMap);
                if(previous!=null){
                	student = updatePrevious(student, previous);
                }
                saveList.add(student);
                saveMap.put(student.getExamNumber(), student);
            }

            successNum = studentService.batchSave(saveList);

            if (failureNum > 0) {
                failureMsg.insert(0, "，失败 " + failureNum + " 条用户");
            }
            addMessage(redirectAttributes, "已成功导入 " + successNum + " 条用户" + failureMsg);
        } catch (Exception e) {
            log.error("Batch import student error!", e);
            addMessage(redirectAttributes, "导入考生失败！失败信息：" + e.getMessage());
        }
        return "redirect:/admin/exam/student";
    }

    @RequestMapping(value = "/export", method = RequestMethod.POST)
    public String exportFile(ExamStudentSearchQuery query, HttpServletRequest request, HttpServletResponse response,
            RedirectAttributes redirectAttributes) {
        WebUser wu = RequestUtils.getWebUser(request);
        int examId = getSessionExamId(request);
        try {
            query.setPageNumber(1);
            query.setPageSize(Integer.MAX_VALUE);
            query.setExamId(examId);
            query.orderByExamNumber();
            subjectFilter(query, wu);
            query = studentService.findByQuery(query);
            for (ExamStudent student : query.getResult()) {
                ExamSubject subject = subjectService.find(student.getExamId(), student.getSubjectCode());
                student.setSubjectName(subject != null ? subject.getName() : "");
                student.setSubjectLevel(subject != null ? subject.getLevel() : "");
                student.setSubjectCategory(subject != null ? subject.getCategory() : "");
                student.setSubjectRemark(subject != null ? subject.getRemark() : "");
            }
            String fileName = "考生数据.xlsx";
            new ExportExcel("考生数据", ExamStudent.class).setDataList(query.getResult()).write(response, fileName)
                    .dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "导出考生数据失败！" + e.getMessage());
        }
        return "redirect:/admin/exam/student";
    }

    @RequestMapping("/sheetTag")
    @ResponseBody
    public Object getSheetTag(HttpServletRequest request, @RequestParam Integer id) {
        ExamStudent student = studentService.findById(id);
        if (student != null) {
            return studentService.buildSheetTags(student);
        } else {
            return new HashMap<>();
        }
    }

    private ExamStudent checkExamNumber(ExamStudent student, Map<String, ExamStudent> current,
            Map<String, ExamStudent> saveMap) {
        ExamStudent previous = saveMap.get(student.getExamNumber());

        if (previous != null) {
        	return previous;
        }
        if (current != null && !current.isEmpty()) {
            previous = current.get(student.getExamNumber());
        } else {
            previous = studentService.findByExamIdAndExamNumber(student.getExamId(), student.getExamNumber());
        }
        if (previous != null) {
        	return previous;
        }
        return null;
    }

	private ExamStudent updatePrevious(ExamStudent student, ExamStudent previous) {
		previous.setCollege(student.getCollege());
		previous.setClassName(student.getClassName());
		previous.setTeacher(student.getTeacher());
		previous.setExamRoom(student.getExamRoom());
		previous.setExamSite(student.getExamSite());
		previous.setRemark(student.getRemark());
		previous.setSubjectLevel(student.getSubjectLevel());
		previous.setSubjectCategory(student.getSubjectCategory());
		previous.setSubjectRemark(student.getSubjectRemark());
		return previous;
	}

    private void buildSheetUrl(ExamStudent student) {
        Campus campus = campusService.findBySchoolAndName(student.getSchoolId(), student.getCampusName());
        student.setSheetUrls(PictureUrlBuilder.getSheetUrls(student.getExamId(), campus.getId(),
                student.getSubjectCode(), student.getExamNumber(), student.getSheetCount()));
    }
    
    private void buildPackageUrl(ExamStudent student) {
        if (StringUtils.isNotBlank(student.getPackageCode())) {
            ExamPackage ep = packageService.find(student.getExamId(), student.getPackageCode());
            if (ep != null && ep.getPicCount() > 0) {
                student.setPackageUrls(PictureUrlBuilder.getPackageUrls(student.getExamId(), student.getPackageCode(),
                        ep.getPicCount()));
            }
        }
    }
}
