package cn.com.qmth.examcloud.core.questions.api.controller;

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

import javax.servlet.http.HttpServletResponse;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;

import cn.com.qmth.examcloud.api.commons.enums.AdminOperateType;
import cn.com.qmth.examcloud.api.commons.enums.CallType;
import cn.com.qmth.examcloud.api.commons.enums.DataRuleType;
import cn.com.qmth.examcloud.api.commons.security.bean.User;
import cn.com.qmth.examcloud.api.commons.security.bean.UserDataRule;
import cn.com.qmth.examcloud.commons.exception.StatusException;
import cn.com.qmth.examcloud.core.questions.base.enums.ExportWay;
import cn.com.qmth.examcloud.core.questions.base.enums.PaperSeqMode;
import cn.com.qmth.examcloud.core.questions.base.question.PaperDto;
import cn.com.qmth.examcloud.core.questions.base.question.QuestionDto;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExamPaper;
import cn.com.qmth.examcloud.core.questions.dao.entity.ExtractConfig;
import cn.com.qmth.examcloud.core.questions.service.ExtractConfigFileService;
import cn.com.qmth.examcloud.core.questions.service.ExtractConfigService;
import cn.com.qmth.examcloud.core.questions.service.bean.CouresInfo;
import cn.com.qmth.examcloud.core.questions.service.bean.dto.ExportPaperInfoModel;
import cn.com.qmth.examcloud.core.questions.service.bean.extract.SaveRandomPaperExtractConfigForToolDomain;
import cn.com.qmth.examcloud.core.questions.service.cache.ExtractConfigCache;
import cn.com.qmth.examcloud.reports.commons.bean.AdminOperateReport;
import cn.com.qmth.examcloud.reports.commons.util.ReportsUtil;
import cn.com.qmth.examcloud.web.security.DataRule;
import cn.com.qmth.examcloud.web.support.ControllerSupport;
import cn.com.qmth.examcloud.web.support.Naked;
import io.swagger.annotations.ApiOperation;

/**
 * @author chenken
 * @date 2017年4月14日 下午6:05:37
 * @company QMTH
 * @description 调卷规则控制器
 * @code 050
 */
@Controller
@RequestMapping("${api_cqb}/")
public class ExtractConfigController extends ControllerSupport {
	private static final Logger LOG = LoggerFactory.getLogger(ExtractConfigController.class);

	@Autowired
	private ExtractConfigService extractConfigService;

	@Autowired
	private ExtractConfigFileService extractConfigFileService;

	@Autowired
	private ExtractConfigCache extractConfigCache;

	@DataRule(type = DataRuleType.COURSE)
	@ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
	@GetMapping(value = "/findPageExtractConfig/{currentPage}/{pageSize}")
	public ResponseEntity<Object> findPageExtractConfig(@PathVariable int currentPage, @PathVariable int pageSize,
			@RequestParam("examId") Long examId, @RequestParam("courseNo") String courseNo) {
		try {
			User user = getAccessUser();
			UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
			Page<ExtractConfig> extractConfigPageList = extractConfigService.findPageExtractConfig(currentPage,
					pageSize, examId, courseNo, String.valueOf(user.getRootOrgId()), ud);
			return new ResponseEntity<>(extractConfigPageList, HttpStatus.OK);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			throw new StatusException("Q-050065", e.getMessage());
		}
	}

	@ApiOperation(value = "保存调卷规则", notes = "保存调卷规则")
	@PutMapping(value = "/extractConfig/{isBuildFile}")
	public ResponseEntity<Object> saveExtractConfig(@PathVariable Integer isBuildFile,
			@RequestBody ExtractConfig extractConfig, @RequestParam(required = false) PaperSeqMode seqMode) {
		if (extractConfig.getCallType() == null) {
			throw new StatusException("CallType不能为空");
		}
		String changeInfo = null;
		if (extractConfig.getId() != null) {
			changeInfo = getChangeInfo(extractConfig);
		}
		User user = getAccessUser();
		extractConfig.setOrgId(user.getRootOrgId() + "");
		extractConfig.setOrgName(user.getRootOrgName());
		if (!CallType.RANDOM_PAPER.equals(extractConfig.getCallType())) {
			extractConfig.setRandomPaperId(null);
			extractConfigFileService.saveExtractConfigAndBuildPaperFile(extractConfig, isBuildFile, user, seqMode);
		} else {
			if (extractConfig.getRandomPaperId() == null) {
				throw new StatusException("请选择随机抽题模板");
			}
			if (extractConfig.getPlayTime() == null) {
				throw new StatusException("请填写音频播放次数");
			}
			extractConfig.setExamPaperList(null);
			extractConfigService.saveExtractConfigForRandomPaper(extractConfig);
		}

		// 清除缓存
		extractConfigCache.remove(extractConfig.getExamId(), extractConfig.getCourseCode());
		if (extractConfig.getId() == null) {
			ReportsUtil.report(
					new AdminOperateReport(user.getRootOrgId(), user.getUserId(), AdminOperateType.TYPE23.getDesc(),
							"课程ID:" + extractConfig.getCourse().getId() + " 考试ID:" + extractConfig.getExamId()));
		} else {
			if (changeInfo != null) {
				ReportsUtil.report(new AdminOperateReport(user.getRootOrgId(), user.getUserId(),
						AdminOperateType.TYPE24.getDesc(), "课程ID:" + extractConfig.getCourse().getId() + " 考试ID:"
								+ extractConfig.getExamId() + changeInfo));
			}
		}
		return new ResponseEntity<>(HttpStatus.OK);
	}

	private String getChangeInfo(ExtractConfig now) {
		ExtractConfig old = extractConfigService.findConfigById(now.getId());
		StringBuilder sb = new StringBuilder();
		if (!CallType.RANDOM_PAPER.equals(now.getCallType())) {
			boolean paperChange = paperChange(old, now);
			if (paperChange) {
				sb.append("修改试卷选定,");
			}
			if (!paperChange && paperWeightChange(old, now)) {
				sb.append("修改试卷选取几率,");
			}
			if (old.getScrambling_the_question_order() != now.getScrambling_the_question_order()) {
				sb.append("修改客观题小题乱序,");
			}
			if (old.getScrambling_the_option_order() != now.getScrambling_the_option_order()) {
				sb.append("修改客观题选项乱序,");
			}
			if (old.getIfFinish() != now.getIfFinish()) {
				sb.append("修改是否生成文件,");
			}
		} else {
			if (old.getRandomPaperId() != now.getRandomPaperId()) {
				sb.append("修改随机抽题模板,");
			}
			if (old.getPlayTime() != now.getPlayTime()) {
				sb.append("修改音频播放次数,");
			}
		}
		if (sb.length() != 0) {
			sb.deleteCharAt(sb.length() - 1);
			return " 修改内容:" + sb.toString();
		}
		return null;
	}

	private boolean paperChange(ExtractConfig old, ExtractConfig now) {
		if (old.getExamPaperList() ==null&& now.getExamPaperList()!=null) {
			return true;
		}
		if (old.getExamPaperList() !=null&& now.getExamPaperList()==null) {
			return true;
		}
		if (old.getExamPaperList().size() != now.getExamPaperList().size()) {
			return true;
		}
		for (int i = 0; i < old.getExamPaperList().size(); i++) {
			ExamPaper oldPaper = old.getExamPaperList().get(i);
			ExamPaper nowPaper = now.getExamPaperList().get(i);
			if (!oldPaper.getPaper().getId().equals(nowPaper.getPaper().getId())) {
				return true;
			}
		}
		return false;
	}

	private boolean paperWeightChange(ExtractConfig old, ExtractConfig now) {
		for (int i = 0; i < old.getExamPaperList().size(); i++) {
			ExamPaper oldPaper = old.getExamPaperList().get(i);
			ExamPaper nowPaper = now.getExamPaperList().get(i);
			if (!oldPaper.getWeight().equals(nowPaper.getWeight())) {
				return true;
			}
		}
		return false;
	}

	@ApiOperation(value = "根据ID获取调卷规则", notes = "根据ID获取调卷规则")
	@GetMapping(value = "/extractConfig/{id}")
	public ResponseEntity<ExtractConfig> findExtractConfigById(@PathVariable String id) {
		ExtractConfig extractConfig = extractConfigService.findConfigById(id);
		return new ResponseEntity<ExtractConfig>(extractConfig, HttpStatus.OK);
	}

	@DataRule(type = DataRuleType.COURSE)
	@ApiOperation(value = "根据考试Id获取已经制定的调卷规则", notes = "根据考试Id获取已经制定的调卷规则")
	@GetMapping(value = "/findCourseByExtractConfig/{examId}")
	public ResponseEntity<Object> findCourseByExtractConfig(@PathVariable Long examId) {
		User user = getAccessUser();
		UserDataRule ud = getUserDataRule(DataRuleType.COURSE);
		List<CouresInfo> courseCodeList = extractConfigService.findCourseByExtractConfig(examId,
				user.getRootOrgId().toString(), ud);
		return new ResponseEntity<>(courseCodeList, HttpStatus.OK);
	}

	@ApiOperation(value = "根据考试ID和课程ID获取调卷规则", notes = "根据考试ID和课程ID获取调卷规则")
	@GetMapping(value = "/extractConfig/{examId}/{courseCode}")
	public ResponseEntity<ExtractConfig> findExtractConfig(@PathVariable Long examId, @PathVariable String courseCode) {
		ExtractConfig condition = new ExtractConfig();
		condition.setExamId(examId);
		condition.setCourseCode(courseCode);
		ExtractConfig extractConfig = extractConfigService.findConfig(condition);
		return new ResponseEntity<ExtractConfig>(extractConfig, HttpStatus.OK);
	}

	@Naked
	@ApiOperation(value = "抽取考试试卷", notes = "抽取考试试卷")
	@GetMapping(value = "/extract/{exam_id}/{course_code}/{group_code}")
	public ResponseEntity<Object> extract(@PathVariable Long exam_id, @PathVariable String course_code,
			@PathVariable String group_code) {
		try {
			Map<String, Object> returnMap = extractConfigService.extractExamPaper(exam_id, course_code, group_code);
			if (returnMap.get("errorMsg") == null) {
				PaperDto paperDto = (PaperDto) returnMap.get("paperDto");
				return new ResponseEntity<>(paperDto, HttpStatus.OK);
			} else {
				return new ResponseEntity<>(returnMap.get("errorMsg") + "", HttpStatus.OK);
			}
		} catch (Exception e) {
			LOG.error("抽卷失败", e);
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	@Naked
	@ApiOperation(value = "抽取单个试题", notes = "抽取单个试题")
	@GetMapping(value = "/extractQues/{examId}/{courseCode}/{groupCode}/{paperDetailUnitId}")
	public ResponseEntity<Object> extractQuestion(@PathVariable String examId, @PathVariable String courseCode,
			@PathVariable String groupCode, @PathVariable String paperDetailUnitId) {
		try {
			QuestionDto questionDto = extractConfigService.extractExamQuestion(examId, courseCode, groupCode,
					paperDetailUnitId);
			return new ResponseEntity<>(questionDto, HttpStatus.OK);
		} catch (Exception e) {
			LOG.error("抽题失败", e);
			return new ResponseEntity<>("抽题失败:" + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR);
		}

	}

	@Naked
	@ApiOperation(value = "判断试卷中的题是否都为客观题(单选、多选、判断)，包括套题中的小题", notes = "判断试卷中的题是否都为客观题(单选、多选、判断)，包括套题中的小题")
	@GetMapping(value = "/checkObjective/{paperId}")
	public ResponseEntity<Map<String, Object>> checkIsAllObjectiveQuestion(@PathVariable String paperId) {
		Map<String, Object> quesMap = new HashMap<>();
		try {
			if (StringUtils.isBlank(paperId)) {
				quesMap.put("message", "paperId不能为空");
				return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
			}
			boolean result = extractConfigService.checkIsAllQbjectiveQuestion(paperId);
			quesMap.put("result", result);
			quesMap.put("message", result ? "全为客观题" : "不全为客观题");
			return new ResponseEntity<>(quesMap, HttpStatus.OK);
		} catch (Exception e) {
			LOG.error("调用checkIsAllQbjectiveQuestion失败", e);
			quesMap.put("result", "error");
			quesMap.put("message", "调用失败");
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	@Naked
	@ApiOperation(value = "导出单张考试试卷、答案、试卷结构", notes = "导出单张考试试卷、答案、试卷结构")
	@GetMapping(value = "/exportSingleExamPaperInfo/{orgId}/{exportWay}/{examId}/{courseId}/{exportContentList}/{loginName}")
	public void exportSingleExamPaperInfo(HttpServletResponse response, @PathVariable String exportWay,
			@PathVariable String orgId, @PathVariable String examId, @PathVariable String courseId,
			@PathVariable String exportContentList, @PathVariable String loginName,
			@RequestParam(required = false) String psw) {
		ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
		exportModel.setExportWay(ExportWay.strToEnum(exportWay));
		exportModel.setExamId(examId);
		exportModel.setCourseId(courseId);
		String[] exportContentArray = exportContentList.split(",");
		List<String> list = new ArrayList<>();
		for (int i = 0; i < exportContentArray.length; i++) {
			list.add(exportContentArray[i]);
		}
		exportModel.setExportContentList(list);
		try {
			extractConfigFileService.exportExamPaperInfo(exportModel, response, loginName, orgId, psw);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
		}
	}

	@ApiOperation(value = "导出试卷文件前校验", notes = "导出试卷文件前校验")
	@GetMapping(value = "/exportBatchExamPaperInfoCheck/{exportWay}/{examId}")
	public ResponseEntity<Object> exportExamPaperInfoCheck(HttpServletResponse response, @PathVariable String exportWay,
			@PathVariable String examId) {
		ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
		exportModel.setExportWay(ExportWay.strToEnum(exportWay));
		exportModel.setExamId(examId);
		try {
			extractConfigFileService.exportExamPaperInfoCheck(exportModel, response);
			return new ResponseEntity<>(HttpStatus.OK);
		} catch (Exception e) {
			LOG.error(e.getMessage(), e);
			throw new StatusException("Q-050200", e.getMessage());
		}
	}

	@Naked
	@ApiOperation(value = "导出整个考试下所有 课程的试卷、答案、试卷结构", notes = "导出整个考试下所有 课程的试卷、答案、试卷结构")
	@GetMapping(value = "/exportBatchExamPaperInfo/{orgId}/{exportWay}/{examId}/{exportContentList}/{loginName}")
	public void exportBatchExamPaperInfo(HttpServletResponse response, @PathVariable String exportWay,
			@PathVariable String orgId, @PathVariable String examId, @PathVariable String exportContentList,
			@PathVariable String loginName) {
		ExportPaperInfoModel exportModel = new ExportPaperInfoModel();
		exportModel.setExportWay(ExportWay.strToEnum(exportWay));
		exportModel.setExamId(examId);
		String[] exportContentArray = exportContentList.split(",");
		List<String> list = new ArrayList<>();
		for (int i = 0; i < exportContentArray.length; i++) {
			list.add(exportContentArray[i]);
		}
		exportModel.setExportContentList(list);
		try {
			extractConfigFileService.exportExamPaperInfo(exportModel, response, loginName, orgId, null);
		} catch (StatusException e) {
			throw e;
		} catch (Exception e) {
			throw new StatusException("500", "系统错误", e);
		}
	}

	@Naked
	@ApiOperation(value = "根据试卷id抽取考试试卷", notes = "根据试卷id抽取考试试卷")
	@GetMapping(value = "/extract/paper/{paperId}")
	public ResponseEntity<Object> extractPaper(@PathVariable String paperId) {
		try {
			Map<String, Object> returnMap = extractConfigService.extractPaper(paperId);
			if (returnMap.get("errorMsg") == null) {
				PaperDto paperDto = (PaperDto) returnMap.get("paperDto");
				return new ResponseEntity<>(paperDto, HttpStatus.OK);
			} else {
				return new ResponseEntity<>(returnMap.get("errorMsg") + "", HttpStatus.OK);
			}
		} catch (Exception e) {
			LOG.error("抽卷失败", e);
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	@Naked
	@ApiOperation(value = "测试获取试卷Dto", notes = "测试获取试卷Dto")
	@GetMapping(value = "/extract/getPaperDto/{paperId}")
	public ResponseEntity<Object> getPaperDto(@PathVariable String paperId) {
		try {
			PaperDto paperDto = extractConfigService.getPaperDtoByPaperNew(paperId);
			return new ResponseEntity<>(paperDto, HttpStatus.OK);
		} catch (Exception e) {
			LOG.error("获取试卷Dto失败", e);
			return new ResponseEntity<>(HttpStatus.INTERNAL_SERVER_ERROR);
		}
	}

	@Naked
	@ApiOperation(value = "通过试卷id得到答案", notes = "通过试卷id得到答案")
	@GetMapping(value = "/extract/getAnswerHtml/{paperId}")
	public ResponseEntity<Object> getAnswerHtml(@PathVariable String paperId) {
		String answerHtml = extractConfigService.getAnswerHtml(paperId);
		return new ResponseEntity<>(answerHtml, HttpStatus.OK);
	}

	@ResponseBody
	@ApiOperation("随机抽卷调卷规则创建")
    @PostMapping("extract_config/randompaper/save")
	public void saveRandomPaperExtractConfig(@RequestBody SaveRandomPaperExtractConfigForToolDomain req) {
    	extractConfigService.saveExtractConfigForRandomPaper(req);
	}

}
