package com.yizhi.application.exam.controller;

import java.io.FileOutputStream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

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

import com.baomidou.mybatisplus.plugins.Page;
import com.yizhi.core.application.enums.InternationalEnums;
import com.yizhi.core.application.context.ContextHolder;
import com.yizhi.core.application.context.RequestContext;
import com.yizhi.core.application.log.LogEventPublisher;
import com.yizhi.exam.application.feign.ExamAnswerClient;
import com.yizhi.exam.application.feign.ExamAuthorizeClient;
import com.yizhi.exam.application.feign.ExamClient;
import com.yizhi.exam.application.vo.*;
import com.yizhi.exam.application.vo.domain.Exam;
import com.yizhi.exam.application.vo.domain.TrExamAuthorize;
import com.yizhi.exam.application.vo.exam.StatisticalCountVO;
import com.yizhi.system.application.model.RangeModel;
import com.yizhi.system.application.system.remote.AccountClient;
import com.yizhi.system.application.system.remote.OrganizationClient;
import com.yizhi.system.application.system.remote.SiteClient;
import com.yizhi.system.application.vo.AccountVO;
import com.yizhi.system.application.vo.OrgVO;
import com.yizhi.util.application.domain.Response;
import org.apache.commons.collections.CollectionUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import io.swagger.annotations.ApiParam;

/**
 * 〈一句话功能简述〉<br>
 * 〈考试统计〉
 *
 * @author phone
 * @create 2018/5/10
 * @since 1.0.0
 */
@Api(tags = "管理端-考试统计接口", description = "管理端-考试统计接口")
@RestController
@RequestMapping("/manage/exam")
public class ExamStatisticalController {

    private static final Logger LOGGER = LoggerFactory.getLogger(ExamStatisticalController.class);

    @Autowired
	ExamClient examClient;
    @Autowired
	ExamAuthorizeClient examAuthorizeClient;
    @Autowired
	AccountClient accountClient;
    @Autowired
	ExamAnswerClient examAnswerClient;
    @Autowired
	OrganizationClient organizationClient;
    @Autowired
	SiteClient siteClient;
    @Autowired
	LogEventPublisher publisher;
    //@Autowired
    //RabbitTemplate rabbitTemplate;
    @Autowired
    ExamStatisticalExport examStatisticalExport;

	@GetMapping("/statistical/exam")
	@ApiOperation(value = "考试统计",response = StatisticalCountVO.class)
	public Response<StatisticalCountVO> statistical(
			ContextAndPageSizeVO contextAndPageSizeVO) {
		RangeModel rangeModel;
		RequestContext requestContext = ContextHolder.get();
		Long companyId = requestContext.getCompanyId();
		Long siteId = requestContext.getSiteId();
		contextAndPageSizeVO.setCompanyId(companyId);
		contextAndPageSizeVO.setSiteId(siteId);
		List<Long> orgIds = null;
		if(!requestContext.isAdmin() && !CollectionUtils.isEmpty(requestContext.getOrgIds())){
			orgIds = requestContext.getOrgIds();
			contextAndPageSizeVO.setOrgIds(orgIds);
		}
		List<StatisticalCountVO> statisticalCountVOS = new ArrayList<StatisticalCountVO>();
		StatisticalCountVO statisticalCountVO;
		Integer shouldExamNum = 0;
		Integer submitCount = 0;
		List<Exam> exams = examClient.selectExamListByName(contextAndPageSizeVO); // 根据考试名称获取所有考试信息
		Integer count = examClient.selectExamListByNameCount(contextAndPageSizeVO);
		for (Exam exam : exams) {
			statisticalCountVO = examAnswerClient.selectStaticalCount(exam.getId()); // 获取总分数和人数
			statisticalCountVO.setId(exam.getId());
			statisticalCountVO.setName(exam.getName());
			statisticalCountVO.setStartTime(exam.getStartTime());
			statisticalCountVO.setEndTime(exam.getEndTime());
			if(exam.getVisibleRange() == null){
				shouldExamNum = 0;
			} else if(exam.getVisibleRange() == 1){
				//全平台可见应考人数查询
				shouldExamNum = siteClient.getSitAccountCount(siteId,companyId);
			}else if(exam.getVisibleRange() == 2){
				//指定学员可见
				List<TrExamAuthorize> trExamAuthorizes = examAuthorizeClient.examCount(exam.getId());// 查询应考人数列表
				List<RangeModel> rangeModels = new ArrayList<>();
				for (TrExamAuthorize trExamAuthorize : trExamAuthorizes) {
					rangeModel = new RangeModel();
					switch (trExamAuthorize.getType()) {
						case 1:
							rangeModel.setType(2);
							break;
						case 2:
							rangeModel.setType(1);
							break;
						case 3:
							rangeModel.setType(3);
							break;
						default:
							rangeModel.setType(0);
							break;
					}
					rangeModel.setRelationId(trExamAuthorize.getRelationId());
					rangeModels.add(rangeModel);
				}
				Map<String, Object> map = null;
				try {
					map = accountClient.findMemberInfo(rangeModels);
					if (map != null) {
						shouldExamNum = Integer.parseInt(map.get("count") == null ? "0" : map.get("count").toString()); // 应考人数
					}
				}catch (Exception e){
					LOGGER.error("调用accountClient.findMemberInfo失败：参数为：" + rangeModels.toString(),e);
				}
			}
			statisticalCountVO.setShouldExamNum(shouldExamNum);
			submitCount = examAnswerClient.submitCount(exam.getId()); // 获取该考试实际参加人数
			statisticalCountVO.setSubmitCount(submitCount);
			int num = statisticalCountVO.getNum();
			// 通过人数
			statisticalCountVO.setByCount(examAnswerClient.selectByCount(exam.getId()));
			// 平均分计算
			BigDecimal score = statisticalCountVO.getScore();
			BigDecimal avgScore = null;
			int s = score.compareTo(BigDecimal.valueOf(0));
			if(s > 0 && num > 0){
				avgScore = score.divide(BigDecimal.valueOf(num)).setScale(2, BigDecimal.ROUND_HALF_UP);
			}
			statisticalCountVO.setAvgScore(avgScore);
			// 完成率计算
			BigDecimal complete = null;
			if(submitCount > 0 && shouldExamNum > 0){
				complete = BigDecimal.valueOf(submitCount).divide(BigDecimal.valueOf(shouldExamNum),2,BigDecimal.ROUND_HALF_UP);
			}
			if(complete != null){
				int a = complete.compareTo(BigDecimal.valueOf(0));
				if (a == -1){
					statisticalCountVO.setComplete(BigDecimal.valueOf(0));
				}else{
					statisticalCountVO.setComplete(complete);
				}
			}
			statisticalCountVOS.add(statisticalCountVO);
		}
		Map<String,Integer> page = new HashMap<String,Integer>();
		page.put("pageNo", contextAndPageSizeVO.getPageNo());
		page.put("pageSize", contextAndPageSizeVO.getPageSize());
		page.put("pageTotal",count);
		return Response.ok(statisticalCountVOS,page);
	}
	
	@ApiOperation(value = "学员考试详情", notes = "返回该学员考试列表", response = StatisticalByUserVO.class)
	@PostMapping("/statistical/exam/user")
	@ApiImplicitParams({
		@ApiImplicitParam(name="examId" , value="考试id", dataType="Long"),
		@ApiImplicitParam(name="orgNameLike" , value="部门编码或部门名称", dataType="String"),
		@ApiImplicitParam(name="accountNameLike" , value="用户关键字", dataType="String"),
		@ApiImplicitParam(name="pageNo" , value="当前页", dataType="Integer"),
		@ApiImplicitParam(name="pageSize" , value="每页条数", dataType="Integer")
	})
	public Response<Page<StatisticalByUserVO>> examByUser(@RequestBody ExamCountByUserVO vo) throws Exception {
		if(vo.getPageNo() == null){
			vo.setPageNo(1);
		}
		if(vo.getPageSize() == null){
			vo.setPageSize(20);
		}
		RequestContext context = ContextHolder.get();
		Long companyId = context.getCompanyId();
		vo.setCompanyId(companyId);
		vo.setSiteId(context.getSiteId());
		if(vo.getOrgNameLike() != null){
			//根据 部门编码或部门名称  获取 orgId 集合
			List<OrgVO> OrgList = null;
			try{
				OrgList = organizationClient.fuzzySearchOrgByName(vo.getOrgNameLike(), companyId);
			}catch (Exception e) {
				LOGGER.error(e.getMessage());
			}
			if(OrgList != null && OrgList.size() > 0){
				List<Long> orgIds = OrgList.stream().map(OrgVO::getId).collect(Collectors.toList());
				if(orgIds != null && orgIds.size() > 0){
					vo.setOrgIds(orgIds);
				}
			}
		}
		if(vo.getAccountNameLike() != null){
			//根据 用户关键字 获取用户id 集合
			List<AccountVO> accountList = null;
			try{
				accountList = accountClient.fuzzySearchAccountByName(vo.getAccountNameLike(), companyId);
			}catch (Exception e) {
				LOGGER.error(e.getMessage());
			}
			if(accountList != null && accountList.size() > 0){
				List<Long> accountIds = accountList.stream().map(AccountVO::getId).collect(Collectors.toList());
				if(accountIds != null && accountIds.size() > 0){
					vo.setAccountIds(accountIds);
				}
			}
		}
		
		try{
			Page<StatisticalByUserVO> page = examClient.examByUser(vo);
			//获取 用户名称，  部门名称
			if(page != null){
				List<StatisticalByUserVO> records = page.getRecords();
				if(records != null && records.size() > 0){
					for(StatisticalByUserVO uvo : records){
						// 部门名称
						String chiefOrgNames = null;
						try{
							chiefOrgNames = organizationClient.getChiefOrgNames(uvo.getOrgId(), companyId).get(0);
						}catch (Exception e) {
							LOGGER.error(e.getMessage());
						}
						uvo.setOrgName(chiefOrgNames);
						// 用户信息
						AccountVO findById = null;
						try{
							findById = accountClient.findById(uvo.getAccountId());
						}catch (Exception e) {
							LOGGER.error(e.getMessage());
						}
						if(findById != null){
							uvo.setAccountName(findById.getName());
							//uvo.setName(findById.getFullName());
						}
					}
				}
			}
			return Response.ok(page);
		}catch (Exception e) {
			e.printStackTrace();
			LOGGER.error("学员考试详情:" + e);
			return Response.fail();
		}
	}
					@ApiOperation(value = "学员考试答卷详情", notes = "返回该学员考试答卷列表", response = AnswerDetailVO.class)
	@PostMapping("/statistical/exam/user/detail")
	@ApiImplicitParams({
		@ApiImplicitParam(name="accountId" , value="用户id", dataType="Integer"),
		@ApiImplicitParam(name="examId" , value="考试id", dataType="Integer"),
		@ApiImplicitParam(name="pageNo" , value="当前页", dataType="Integer"),
		@ApiImplicitParam(name="pageSize" , value="每页条数", dataType="Integer")
	})
	public Response<List<AnswerDetailVO>> userExamDetail(@RequestBody ExamAnswerByUserVO vo){
		if(vo.getAccountId() == null){
			return Response.fail(InternationalEnums.EXAMSTATISTICALCONTROLLER1.getCode());
		}
		if(vo.getExamId() == null){
			return Response.fail(InternationalEnums.EXAMSTATISTICALCONTROLLER2.getCode());
		}
		if(vo.getPageNo() == null){
			vo.setPageNo(1);
		}
		if(vo.getPageSize() == null){
			vo.setPageSize(20);
		}
		try{
			List<AnswerDetailVO> answerDetailVO = examAnswerClient.getAnswerDetailList(vo);
			return Response.ok(answerDetailVO);
		}catch (Exception e) {
			LOGGER.error("学员考试答卷详情:" + e);
			return Response.fail();
		}
	}
	
	//OssUpload 上传阿里云
	@ApiOperation(value = "按考试统计 下载结果数据", notes = "查询，制作excel文档，上传阿里云, 发送任务", response = AnswerDetailVO.class)
	@PostMapping("/statistical/exam/export")
	@ApiImplicitParams({
		@ApiImplicitParam(name="examName" , value="考试名称", dataType="String"),
		@ApiImplicitParam(name="startTime" , value="开始时间", dataType="Date"),
		@ApiImplicitParam(name="endTime" , value="结束时间", dataType="Date")
	})
	public Response<String> statisticalExport(HttpServletRequest request, HttpServletResponse response, @RequestBody ExamCountExportParamVO vo){
		 Map<String,Object> map=new HashMap<String,Object>();
		  map.put("vo", vo);
		  map.put("accountId", ContextHolder.get().getAccountId());
		  map.put("request", request);
		  map.put("siteId", ContextHolder.get().getSiteId());
		  map.put("companyId", ContextHolder.get().getCompanyId());
		  examStatisticalExport.execute(map, true);
		  return Response.ok();
	}
}