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

import java.text.DecimalFormat;
import java.util.LinkedList;
import java.util.List;
import java.util.Set;

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.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.servlet.mvc.support.RedirectAttributes;

import cn.com.qmth.stmms.admin.dto.MarkInfoDTO;
import cn.com.qmth.stmms.admin.dto.MarkerInfoDTO;
import cn.com.qmth.stmms.admin.vo.SubjectLibraryVO;
import cn.com.qmth.stmms.biz.exam.model.ExamSubject;
import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
import cn.com.qmth.stmms.biz.exam.model.Marker;
import cn.com.qmth.stmms.biz.exam.service.ExamQuestionService;
import cn.com.qmth.stmms.biz.exam.service.ExamSubjectService;
import cn.com.qmth.stmms.biz.exam.service.MarkGroupService;
import cn.com.qmth.stmms.biz.exam.service.MarkerService;
import cn.com.qmth.stmms.biz.exam.service.query.ExamSubjectSearchQuery;
import cn.com.qmth.stmms.biz.lock.LockService;
import cn.com.qmth.stmms.biz.mark.query.MarkLibrarySearchQuery;
import cn.com.qmth.stmms.biz.mark.service.MarkLibraryService;
import cn.com.qmth.stmms.biz.user.service.UserService;
import cn.com.qmth.stmms.common.annotation.Logging;
import cn.com.qmth.stmms.common.annotation.RoleRequire;
import cn.com.qmth.stmms.common.domain.WebUser;
import cn.com.qmth.stmms.common.enums.LibraryStatus;
import cn.com.qmth.stmms.common.enums.LockType;
import cn.com.qmth.stmms.common.enums.LogType;
import cn.com.qmth.stmms.common.enums.MarkStatus;
import cn.com.qmth.stmms.common.enums.Role;
import cn.com.qmth.stmms.common.utils.ExportExcel;
import cn.com.qmth.stmms.common.utils.RequestUtils;

@Controller("markInfoController")
@RequestMapping("/admin/exam/mark")
public class MarkController extends BaseExamController {

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

    @Autowired
    private ExamSubjectService subjectService;

    @Autowired
    private MarkerService markerService;

    @Autowired
    private MarkGroupService groupService;

    @Autowired
    private ExamQuestionService questionService;

    @Autowired
    private UserService userService;

    @Autowired
    private MarkLibraryService libraryService;

    @Autowired
    private LockService lockService;

    /**
     * 评卷进度
     *
     * @param request
     * @param model
     * @param query
     * @return
     */
    @Logging(menu = "评卷管理查询", type = LogType.QUERY)
    @RequestMapping(value = { "", "/subject" })
    public String subjectList(HttpServletRequest request, Model model, ExamSubjectSearchQuery query) {
        WebUser wu = RequestUtils.getWebUser(request);
        int examId = getSessionExamId(request);
        query.setExamId(examId);
        Set<String> unFinishSet = libraryService.findSubjectUnFinishByExamId(examId);
        unFinishSet.addAll(questionService.FindSubjectCodeByExamIdAndObjectiveAndGroupNumberIsNull(examId, false));
        if (query.getFinished() != null) {
            String subjectCodeIn = StringUtils.join(unFinishSet, ",");
            if (query.getFinished()) {
                query.setCodeNotIn(subjectCodeIn);
            } else {
                query.setCodeIn(subjectCodeIn);
            }
        }
        if (wu.isSubjectHeader()) {
            String subjectCodeIn = StringUtils.join(wu.getSubjectCodeSet(), ",");
            query.setCodeIn(subjectCodeIn);
        }
        query = subjectService.findByQuery(query);

        List<SubjectLibraryVO> list = new LinkedList<SubjectLibraryVO>();
        for (ExamSubject subject : query.getResult()) {
            SubjectLibraryVO vo = new SubjectLibraryVO();
            vo.setSubject(subject);
            vo.setStudentCount(subject.getUploadCount());
            vo.setGroupCount(groupService.countByExamAndSubject(examId, subject.getCode()));
            MarkLibrarySearchQuery mQuery = new MarkLibrarySearchQuery();
            mQuery.setExamId(examId);
            mQuery.setSubjectCode(subject.getCode());
            long libraryCount = libraryService.countByQuery(mQuery);
            mQuery.addStatus(LibraryStatus.MARKED);
            long markedCount = libraryService.countByQuery(mQuery);
            vo.setMarkedCount(markedCount);
            mQuery.addStatus(LibraryStatus.ARBITRATED);
            mQuery.addStatus(LibraryStatus.INSPECTED);
            long totalMarkedCount = libraryService.countByQuery(mQuery);
            String percent = libraryCount > 0 ? (new DecimalFormat("####.###").format(totalMarkedCount * 100.0
                    / libraryCount) + "%") : "0%";
            vo.setPercent(percent);
            long count = questionService.countByExamIdAndSubjectAndObjectiveAndGroupNumberIsNull(examId,
                    subject.getCode(), false);
            vo.setGroupFinish(count == 0);
            list.add(vo);
        }
        MarkLibrarySearchQuery mQuery = new MarkLibrarySearchQuery();
        mQuery.setExamId(examId);
        long total = libraryService.countByQuery(mQuery);
        mQuery.addStatus(LibraryStatus.MARKED);
        mQuery.addStatus(LibraryStatus.ARBITRATED);
        mQuery.addStatus(LibraryStatus.INSPECTED);
        long markedCount = libraryService.countByQuery(mQuery);
        long subjectCount = subjectService.count(examId);
        model.addAttribute("unMarkedCount", total - markedCount);
        model.addAttribute("markedCount", markedCount);
        model.addAttribute("unFinishCount", unFinishSet.size());
        model.addAttribute("finishCount", subjectCount - unFinishSet.size());
        model.addAttribute("resultList", list);
        model.addAttribute("query", query);
        model.addAttribute("subjectList", getExamSubject(examId, wu));
        model.addAttribute("levelList", subjectService.listLevel(examId));
        model.addAttribute("categoryList", subjectService.listCategory(examId));
        return "modules/exam/markInfo";
    }

    @Logging(menu = "整体评卷进度导出", type = LogType.EXPORT)
    @RequestMapping(value = "/export-progress", method = RequestMethod.POST)
    public String exportProgress(HttpServletRequest request, HttpServletResponse response,
            RedirectAttributes redirectAttributes) {
        WebUser wu = RequestUtils.getWebUser(request);
        int examId = getSessionExamId(request);
        List<MarkInfoDTO> result = new LinkedList<MarkInfoDTO>();
        List<ExamSubject> list = subjectService.list(examId);
        if (wu.isSubjectHeader()) {
            list = getExamSubject(examId, wu);
        }
        for (ExamSubject subject : list) {
            MarkInfoDTO dto = new MarkInfoDTO(subject);
            MarkLibrarySearchQuery mQuery = new MarkLibrarySearchQuery();
            mQuery.setExamId(examId);
            mQuery.setSubjectCode(subject.getCode());
            long libraryCount = libraryService.countByQuery(mQuery);
            mQuery.addStatus(LibraryStatus.MARKED);
            long inspectedCount = libraryService.countByQuery(mQuery);
            dto.setInspectedCount(inspectedCount);
            mQuery.addStatus(LibraryStatus.ARBITRATED);
            mQuery.addStatus(LibraryStatus.INSPECTED);
            long totalMarkedCount = libraryService.countByQuery(mQuery);
            String percent = libraryCount > 0 ? (new DecimalFormat("####.###").format(totalMarkedCount * 100.0
                    / libraryCount) + "%") : "0%";
            dto.setPercent(percent);
            dto.setGroupCount(groupService.countByExamAndSubject(examId, subject.getCode()));
            result.add(dto);
        }

        try {
            String fileName = "整体评卷进度.xlsx";
            new ExportExcel("整体评卷进度", MarkInfoDTO.class).setDataList(result).write(response, fileName).dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "导出整体评卷进度失败！" + e.getMessage());
            return "redirect:/admin/exam/mark";
        }
    }

    @Logging(menu = "评卷员工作量导出", type = LogType.EXPORT)
    @RequestMapping(value = "/export-marker", method = RequestMethod.POST)
    public String exportMarker(HttpServletRequest request, HttpServletResponse response,
            RedirectAttributes redirectAttributes) {
        WebUser wu = RequestUtils.getWebUser(request);
        int examId = getSessionExamId(request);
        List<MarkerInfoDTO> result = new LinkedList<MarkerInfoDTO>();
        List<Marker> list = markerService.getMarkCount(examId);
        if (wu.isSubjectHeader()) {
            list = markerService.getMarkCount(examId, wu.getSubjectCodeSet());
        }
        for (Marker marker : list) {
            MarkGroup group = groupService.findOne(examId, marker.getSubjectCode(), marker.getGroupNumber());
            group.setQuestionList(questionService.findByExamAndSubjectAndObjectiveAndGroupNumber(examId,
                    group.getSubjectCode(), false, group.getNumber()));
            marker.setUser(userService.findById(marker.getUserId()));
            MarkerInfoDTO dto = new MarkerInfoDTO(marker, subjectService.find(marker.getExamId(),
                    marker.getSubjectCode()), group);
            dto.setTotalScore(questionService.sumTotalScoreByGroupNumber(examId, marker.getSubjectCode(), false,
                    marker.getGroupNumber()));
            result.add(dto);
        }

        try {
            String fileName = "评卷员工作量.xlsx";
            new ExportExcel("评卷员工作量", MarkerInfoDTO.class).setDataList(result).write(response, fileName).dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "导出评卷员工作量失败！" + e.getMessage());
            return "redirect:/admin/exam/mark";
        }
    }

    @Logging(menu = "大题关闭", type = LogType.QUERY)
    @RequestMapping("/finish")
    @RoleRequire({ Role.SCHOOL_ADMIN, Role.SUBJECT_HEADER, Role.COLLEGE_ADMIN })
    public String finish(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes,
            @RequestParam String[] codes) {
        int examId = getSessionExamId(request);
        for (String code : codes) {
            MarkLibrarySearchQuery mQuery = new MarkLibrarySearchQuery();
            mQuery.setExamId(examId);
            mQuery.setSubjectCode(code);
            long libraryCount = libraryService.countByQuery(mQuery);
            mQuery.addStatus(LibraryStatus.MARKED);
            mQuery.addStatus(LibraryStatus.ARBITRATED);
            mQuery.addStatus(LibraryStatus.INSPECTED);
            long markedCount = libraryService.countByQuery(mQuery);
            if (markedCount != libraryCount) {
                continue;
            }
            List<MarkGroup> groups = groupService.findByExamAndSubject(examId, code);
            for (MarkGroup group : groups) {
                if (group == null) {
                    continue;
                }
                try {
                    lockService.waitlock(LockType.GROUP, group.getExamId(), group.getSubjectCode(), group.getNumber());
                    if (group.getStatus() == MarkStatus.FORMAL && group.getLeftCount() == 0) {
                        groupService
                                .updateStatus(examId, code, group.getNumber(), MarkStatus.FINISH, group.getStatus());
                    }
                } finally {
                    lockService.unlock(LockType.GROUP, group.getExamId(), group.getSubjectCode(), group.getNumber());
                }
            }
        }
        return "redirect:/admin/exam/mark";
    }
    

}
