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

import java.util.ArrayList;
import java.util.HashSet;
import java.util.LinkedHashSet;
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.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.servlet.mvc.support.RedirectAttributes;

import com.google.common.collect.Lists;

import cn.com.qmth.stmms.admin.utils.PageUtil;
import cn.com.qmth.stmms.admin.vo.InspectedStudentVO;
import cn.com.qmth.stmms.admin.vo.TagStudentVO;
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.model.ImportQuery;
import cn.com.qmth.stmms.biz.exam.query.ExamStudentSearchQuery;
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.ImportQueryService;
import cn.com.qmth.stmms.biz.file.service.FileService;
import cn.com.qmth.stmms.biz.mark.model.Task;
import cn.com.qmth.stmms.biz.mark.service.TaskService;
import cn.com.qmth.stmms.common.annotation.Logging;
import cn.com.qmth.stmms.common.domain.WebUser;
import cn.com.qmth.stmms.common.enums.ImportType;
import cn.com.qmth.stmms.common.enums.LogType;
import cn.com.qmth.stmms.common.enums.SubjectiveStatus;
import cn.com.qmth.stmms.common.utils.ExportExcel;
import cn.com.qmth.stmms.common.utils.ImportExcel;
import cn.com.qmth.stmms.common.utils.RequestUtils;
import net.sf.json.JSONObject;

@Controller("importQueryController")
@RequestMapping("/admin/exam/inspected/import")
public class ImportQueryController extends BaseExamController {

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

    @Autowired
    private ExamStudentService studentService;

    @Autowired
    private ImportQueryService queryService;

    @Autowired
    private FileService fileService;


    @Autowired
    private TaskService taskService;

    @Autowired
    private ExamService examService;

    public static final String DB_ITEM_JOINER = ":";

    public static final String UN_SELECTIVE_SCORE = "-1";

    @RequestMapping("/list")
    public String list(Model model, HttpServletRequest request, ExamStudentSearchQuery query) {
        int examId = getSessionExamId(request);
        WebUser wu = RequestUtils.getWebUser(request);
        ImportQuery importQuery = queryService.findByExamIdAndUserIdAndType(examId, wu.getId(), ImportType.INSPECTED);
        int inspectCount = 0;
        if (importQuery != null) {
            inspectCount = importQuery.getStudentCodeList().size() > 0 ? 0 : importQuery.getStudentIdList().size();
        }
        model.addAttribute("inspectCount", inspectCount);
        if (inspectCount > 0) {
            List<?> ids = PageUtil
                    .startPage(importQuery.getStudentIdList(), query.getPageNumber(), query.getPageSize());
            List<ExamStudent> list = new ArrayList<ExamStudent>();
            if (ids != null) {
                for (Object id : ids) {
                    ExamStudent student = studentService.findById((int) id);
                    if (importQuery.getTagIdList().contains(id)) {
                        student.setTagValue("1");
                    }
                    if (student.getSubjectiveScoreList() != null) {
                        student.setSubjectiveScoreList(student.getSubjectiveScoreList()
                                .replace(UN_SELECTIVE_SCORE, "/"));
                    }
                    list.add(student);
                }
            }
            query.setTotalPage(PageUtil.pageCount(importQuery.getStudentIdList(), query.getPageNumber(),
                    query.getPageSize()));
            query.setTotalCount(inspectCount);
            query.setResult(list);
        }
        model.addAttribute("query", query);
        return "modules/exam/inspectedImportList";
    }

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

    @Logging(menu = "导入复核名单", type = LogType.IMPORT_FILE)
    @RequestMapping(method = RequestMethod.POST)
    public String importFile(HttpServletRequest request, MultipartFile file, RedirectAttributes redirectAttributes) {
        int examId = getSessionExamId(request);
        WebUser wu = RequestUtils.getWebUser(request);
        queryService.deleteByExamIdAndUserIdAndType(examId, wu.getId(), ImportType.INSPECTED);
        try {
            int successNum = 0;
            int failureNum = 0;
            Set<Integer> successStudent = new LinkedHashSet<Integer>();
            Set<String> failureStudent = new HashSet<String>();
            ImportExcel ei = new ImportExcel(file, 1, 0);
            List<InspectedStudentVO> list = ei.getDataList(InspectedStudentVO.class);
            if (list.size() > 1000) {
                addMessage(redirectAttributes, "导入考生失败！数据超过1000行");
                return "redirect:/admin/exam/inspected/list";
            }
            for (InspectedStudentVO studentVO : list) {
                if (StringUtils.isBlank(studentVO.getStudentCode()) || StringUtils.isBlank(studentVO.getSubjectCode())) {
                    continue;
                }
                List<ExamStudent> studentList = studentService.findByExamIdAndStudentCodeAndSubjectCode(examId,
                        studentVO.getStudentCode(), studentVO.getSubjectCode());
                if (!studentList.isEmpty()) {
                    for (ExamStudent examStudent : studentList) {
                        if (SubjectiveStatus.MARKED.equals(examStudent.getSubjectiveStatus())) {
                            successStudent.add(examStudent.getId());
                            successNum++;
                        } else {
                            failureStudent
                                    .add(studentVO.getSubjectCode() + DB_ITEM_JOINER + studentVO.getStudentCode());
                            failureNum++;
                        }
                    }
                } else {
                    failureStudent.add(studentVO.getSubjectCode() + DB_ITEM_JOINER + studentVO.getStudentCode());
                    failureNum++;
                }
            }
            ImportQuery importQuery = new ImportQuery(examId, wu.getId(), ImportType.INSPECTED, successStudent,
                    failureStudent);
            queryService.save(importQuery);
            String message = "已成功导入 " + successNum + " 条，关联考生记录 " + successStudent.size() + " 条";
            if (failureNum > 0) {
                message = "失败 " + failureNum + " 条";
            }
            addMessage(redirectAttributes, message);
            RequestUtils.setLog(request, message);
        } catch (Exception e) {
            log.error("Batch import inpectedStudent error!", e);
            addMessage(redirectAttributes, "导入考生失败！失败信息：" + e.getMessage());
            return "redirect:/admin/exam/inspected/list";
        }
        return "redirect:/admin/exam/inspected/import/list";
    }

    @Logging(menu = "复核名单重置", type = LogType.UPDATE)
    @RequestMapping(value = "/reset")
    public String reset(HttpServletRequest request, Model model, RedirectAttributes redirectAttributes) {
        int examId = getSessionExamId(request);
        WebUser wu = RequestUtils.getWebUser(request);
        queryService.deleteByExamIdAndUserIdAndType(examId, wu.getId(), ImportType.INSPECTED);
        addMessage(redirectAttributes, "重置成功");
        return "redirect:/admin/exam/inspected/list";
    }

    @RequestMapping(value = "/export")
    public String export(HttpServletRequest request, HttpServletResponse response, RedirectAttributes redirectAttributes) {
        int examId = getSessionExamId(request);
        WebUser wu = RequestUtils.getWebUser(request);
        try {
            String fileName = "错误信息.xlsx";
            List<InspectedStudentVO> list = Lists.newArrayList();
            ImportQuery importQuery = queryService.findByExamIdAndUserIdAndType(examId, wu.getId(),
                    ImportType.INSPECTED);
            for (String studentCode : importQuery.getStudentCodeList()) {
                String[] s = studentCode.split(DB_ITEM_JOINER);
                list.add(new InspectedStudentVO(s[0], s[1]));
            }
            new ExportExcel("错误信息", InspectedStudentVO.class, 2).setDataList(list).write(response, fileName).dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "错误信息下载失败！失败信息：" + e.getMessage());
        }
        return "redirect:/admin/exam/inspected/import/list";
    }

    @RequestMapping("/getSetting")
    @ResponseBody
    public JSONObject getSetting(HttpServletRequest request, @RequestParam(required = false) Integer studentId) {
        int examId = getSessionExamId(request);
        WebUser wu = RequestUtils.getWebUser(request);
        ImportQuery importQuery = queryService.findByExamIdAndUserIdAndType(examId, wu.getId(), ImportType.INSPECTED);
        int inspectCount = importQuery.getStudentCodeList().size() > 0 ? 0 : importQuery.getStudentIdList().size();
        List<Integer> studentIds = importQuery.getStudentIdList();
        List<Integer> tagIds = importQuery.getTagIdList();
        if (studentId != null) {
            studentIds = new ArrayList<Integer>();
            studentIds.add(studentId);
        }
        JSONObject setting = new JSONObject();
        Exam exam = examService.findById(examId);
        setting.accumulate("examType", exam.getType());
        setting.accumulate("inspectCount", inspectCount);
        setting.accumulate("fileServer", fileService.getFileServer());
        setting.accumulate("studentIds", inspectCount > 0 ? studentIds : new ArrayList<Integer>());
        setting.accumulate("tagIds", tagIds);
        setting.accumulate("message", inspectCount > 0 ? "" : "没有待复核的任务");
        return setting;
    }

    @RequestMapping("/getTask")
    @ResponseBody
    public Task info(HttpServletRequest request, @RequestParam Integer studentId) {
        ExamStudent student = studentService.findById(studentId);
        Task task = null;
        if (student != null) {
            task = taskService.build(student);
        }
        return task;
    }

    @RequestMapping("/tag")
    @ResponseBody
    public Object tag(HttpServletRequest request, @RequestParam Integer studentId, @RequestParam boolean isTag) {
        ExamStudent student = studentService.findById(studentId);
        JSONObject obj = new JSONObject();
        if (student != null) {
            int examId = getSessionExamId(request);
            WebUser wu = RequestUtils.getWebUser(request);
            ImportQuery importQuery = queryService.findByExamIdAndUserIdAndType(examId, wu.getId(),
                    ImportType.INSPECTED);
            List<Integer> ids = importQuery.getTagIdList();
            if (isTag && !ids.contains(studentId)) {
                ids.add(studentId);
            }
            if (!isTag && ids.contains(studentId)) {
                ids.remove(studentId);
            }
            importQuery.buildTag(ids);
            queryService.save(importQuery);
            obj.accumulate("success", true);
        } else {
            obj.accumulate("success", false);
            obj.accumulate("message", "无法标记，请刷新页面");
        }
        return obj;
    }

    @RequestMapping(value = "/exportTag")
    public String exportTag(HttpServletRequest request, HttpServletResponse response,
            RedirectAttributes redirectAttributes) {
        int examId = getSessionExamId(request);
        WebUser wu = RequestUtils.getWebUser(request);
        try {
            String fileName = "标记卷.xlsx";
            List<TagStudentVO> list = Lists.newArrayList();
            ImportQuery importQuery = queryService.findByExamIdAndUserIdAndType(examId, wu.getId(),
                    ImportType.INSPECTED);
            for (Integer studentId : importQuery.getTagIdList()) {
                list.add(new TagStudentVO(studentService.findById(studentId)));
            }
            new ExportExcel("标记卷信息", TagStudentVO.class, 2).setDataList(list).write(response, fileName).dispose();
            return null;
        } catch (Exception e) {
            addMessage(redirectAttributes, "标记卷下载失败！失败信息：" + e.getMessage());
        }
        return "redirect:/admin/exam/inspected/import/list";
    }
}
