package cn.com.qmth.stmms.ms.log.controller;

import cn.com.qmth.stmms.ms.commons.utils.SqlUtil;
import cn.com.qmth.stmms.ms.commons.utils.specification.PagingAndSortingDTO;
import cn.com.qmth.stmms.ms.commons.web.PageableDTO;
import cn.com.qmth.stmms.ms.core.domain.*;
import cn.com.qmth.stmms.ms.core.domain.enums.TrialEnum;
import cn.com.qmth.stmms.ms.core.domain.user.Role;
import cn.com.qmth.stmms.ms.core.repository.MarkLogRepo;
import cn.com.qmth.stmms.ms.core.repository.PaperRepo;
import cn.com.qmth.stmms.ms.core.repository.WorkRepo;
import cn.com.qmth.stmms.ms.core.vo.Subject;
import cn.com.qmth.stmms.ms.marking.assembler.PaperAssembler;
import cn.com.qmth.stmms.ms.marking.dto.PaperDTO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.jdbc.core.JdbcTemplate;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.*;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.Predicate;
import javax.servlet.http.HttpServletRequest;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

//import io.swagger.annotations.Api;
//import io.swagger.annotations.ApiOperation;
//import io.swagger.annotations.ApiParam;

//@Api(tags = "纪检审计接口controller")
@RestController
@RequestMapping("api/marklog")
public class MarkLogController {

    @Autowired
    MarkLogRepo markLogRepo;

    @Autowired
    PaperRepo paperRepo;

    @Autowired
    WorkRepo workRepo;

    @Autowired
    SqlUtil sqlUtil;

    @Autowired
    private PaperAssembler paperAssembler;

    JdbcTemplate jdbcTemplate;

    //    @ApiOperation(value = "纪检审计查询接口")
    @GetMapping("/selectMarkLog")
    public PagingAndSortingDTO selectMarkLog(
//            @ApiParam(value = "科目", required = false)
            @RequestParam(required = false) String subject,
//                                             @ApiParam(value = "准考证号", required = false)
            @RequestParam(required = false) Long examNumber,
//                                             @ApiParam(value = "学生姓名", required = false)
            @RequestParam(required = false) String studentName,
//                                             @ApiParam(value = "操作类型(1：分档，2：打分，3：回评档位，4：回评分数，5：档位打回，6：档位打回回评，7：一键定档，8：标准卷设置)", required = false)
            @RequestParam(required = false) Integer operType,
//                                             @ApiParam(value = "开始时间", required = false)
            @RequestParam(required = false) String startTime,
//                                             @ApiParam(value = "结束时间", required = false)
            @RequestParam(required = false) String endTime,
            @RequestParam(required = false) Long workId,
            @RequestParam Integer curPage,
            @RequestParam Integer pageSize) {
        Pageable pageable = new PageRequest(curPage, pageSize, Sort.Direction.DESC, "createTime");
        Specification<MarkLog> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (Objects.nonNull(subject)) {
                predicates.add(cb.equal(root.get("subject").as(String.class), subject));
            }
            if (Objects.nonNull(examNumber)) {
                predicates.add(cb.equal(root.get("examNumber").as(String.class), examNumber));
            }
            if (Objects.nonNull(studentName)) {
                predicates.add(cb.like(root.get("studentName").as(String.class), "%" + studentName + "%"));
            }
            if (Objects.nonNull(operType)) {
                predicates.add(cb.equal(root.get("operType").as(Integer.class), operType));
            }
            if (Objects.nonNull(startTime)) {
                //大于或等于传入时间
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime").as(String.class), startTime));
            }
            if (Objects.nonNull(endTime)) {
                //小于或等于传入时间
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime").as(String.class), endTime));
            }
            if (Objects.nonNull(workId)) {
                predicates.add(cb.equal(root.get("workId").as(Long.class), workId));
            }
            List<Map> mapList = MarkLogOperType.listTypes();
            if (mapList != null && mapList.size() > 0) {
                    CriteriaBuilder.In<Object> in = cb.in(root.get("operType"));
                    for (Map map : mapList) {
                        in.value(map.get("id"));
                    }
                    predicates.add(cb.and(cb.and(in)));
            }
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        Page<MarkLog> result = markLogRepo.findAll(specification, pageable);
        return new PagingAndSortingDTO(result.getNumber(), result.getSize(), result.getTotalPages(),
                result.getTotalElements(), result.getContent());
    }

    /**
     * 采集日志
     *
     * @param subject
     * @param examNumber
     * @param studentName
     * @param createUserId
     * @param startTime
     * @param endTime
     * @param curPage
     * @param pageSize
     * @return
     */
    @GetMapping("/selectCollectMarkLog")
    public PagingAndSortingDTO selectCollectMarkLog(
            @RequestParam(required = false) String subject,
            @RequestParam(required = false) Long examNumber,
            @RequestParam(required = false) String studentName,
            @RequestParam(required = false) String createUserId,
            @RequestParam(required = false) String startTime,
            @RequestParam(required = false) String endTime,
            @RequestParam(required = false) Long workId,
            @RequestParam Integer curPage,
            @RequestParam Integer pageSize) {
        Pageable pageable = new PageRequest(curPage, pageSize, Sort.Direction.DESC, "createTime");
        Specification<MarkLog> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            if (Objects.nonNull(subject)) {
                predicates.add(cb.equal(root.get("subject").as(String.class), subject));
            }
            if (Objects.nonNull(examNumber)) {
                predicates.add(cb.equal(root.get("examNumber").as(String.class), examNumber));
            }
            if (Objects.nonNull(studentName)) {
                predicates.add(cb.like(root.get("studentName").as(String.class), "%" + studentName + "%"));
            }
            if (Objects.nonNull(createUserId)) {
                predicates.add(cb.equal(root.get("createUserId").as(String.class), createUserId));
            }
            if (Objects.nonNull(startTime)) {
                //大于或等于传入时间
                predicates.add(cb.greaterThanOrEqualTo(root.get("createTime").as(String.class), startTime));
            }
            if (Objects.nonNull(endTime)) {
                //小于或等于传入时间
                predicates.add(cb.lessThanOrEqualTo(root.get("createTime").as(String.class), endTime));
            }
            if (Objects.nonNull(workId)) {
                predicates.add(cb.equal(root.get("workId").as(Long.class), workId));
            }
            //采集端
            predicates.add(cb.equal(root.get("operType").as(Integer.class), MarkLogOperType.COLLECT.getId()));
            return cb.and(predicates.toArray(new Predicate[predicates.size()]));
        };
        Page<MarkLog> result = markLogRepo.findAll(specification, pageable);
        return new PagingAndSortingDTO(result.getNumber(), result.getSize(), result.getTotalPages(),
                result.getTotalElements(), result.getContent());
    }

    /**
     * 采集成功记录日志
     *
     * @param workId
     * @param request
     * @return
     * @throws ParseException
     */
    @RequestMapping(value = "/saveCollectLog", method = RequestMethod.POST)
    public Object saveCollectLog(Long workId, HttpServletRequest request) throws ParseException {
        //取采集用户id
        Long clientUserId = Long.valueOf(request.getParameter("clientUserId"));
        //取采集用户名称
        String clientUsername = request.getParameter("clientUsername");
        //学生信息
        String name = request.getParameter("name");
        //科目信息
        Integer subjectId = Integer.valueOf(request.getParameter("subjectId"));
        //准考证号
        String examNumber = request.getParameter("examNumber");
        //试卷信息
        List<Paper> paperList = paperRepo.findByWorkIdAndExamNumber(workId, examNumber);

        Integer operType = MarkLogOperType.COLLECT.getId();
        Subject subject = Subject.values()[subjectId - 1];

        Work work = workRepo.findOne(workId);

        MarkLog markLog = new MarkLog();
        markLog.setCreateUserId(clientUserId);
        markLog.setCreateUserName(clientUsername);
        markLog.setCreateRole(Role.COLLECTOR.getName());
        markLog.setSubject(subject.toString());
        markLog.setExamNumber(examNumber);
        markLog.setStudentName(name);
        markLog.setOperType(operType);
        markLog.setWorkId(workId);
        markLog.setWorkName(work.getName());
        if (paperList != null && paperList.size() > 0) {
            Paper paper = paperList.get(0);
            markLog.setPaperId(paper.getId());
        }
        markLog.setStage(MarkStage.INIT);
        //识别方式
        String manual = request.getParameter("manual");
        //增加考生不存在备注
        markLog.setRemark(paperList == null || paperList.size() == 0 ? "考生不存在" : "0".equals(manual) ? "正常扫描" : "1".equals(manual) ? "手工绑定" : null);
        //操作时间
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        String time = request.getParameter("time");
        markLog.setCreateTime(formatter.parse(time));
        //登录时间
        String clientUserLoginTime = request.getParameter("clientUserLoginTime");
        markLog.setLoginTime(formatter.parse(clientUserLoginTime));
        //退出时间(没有退出时间)
        return markLogRepo.saveAndFlush(markLog);
    }

    /**
     * 设备监控
     *
     * @param workId
     * @return
     * @throws ParseException
     */
    @RequestMapping(value = "/equipmentMonitor", method = RequestMethod.GET)
    public Object saveCollectLog(Long workId, Pageable pageable) {
        List<Map> mapList = markLogRepo.findByWorkId(workId);
        if (!mapList.isEmpty() && mapList.size() > 0) {
            List<Long> longs = mapList.stream().map(m -> Long.valueOf(m.get("id").toString())).collect(Collectors.toList());

            Specification<MarkLog> specification = (root, query, builder) -> {
                List<Predicate> predicates = new ArrayList<>();
                if (longs != null && longs.size() > 0) {
                    CriteriaBuilder.In<Object> in = builder.in(root.get("id"));
                    for (Long id : longs) {
                        in.value(id);
                    }
                    predicates.add(builder.and(builder.and(in)));
                }
                return builder.and(predicates.toArray(new Predicate[predicates.size()]));
            };
            Page<MarkLog> markLogs = markLogRepo.findAll(specification, pageable);
            List<MarkLog> list = markLogs.getContent();
            List<Map> arrayList = new ArrayList<>();
            for (MarkLog markLog : list) {
                Map map = new HashMap();
                map.put("createUserName", markLog.getCreateUserName());
                Paper paper = paperRepo.findOne(markLog.getPaperId());
                PaperDTO paperDTO = paperAssembler.toDTO(paper);
                map.put("imgSrc", paperDTO.getImgSrc());
                map.put("thumbSrc", paperDTO.getThumbSrc());
                arrayList.add(map);
            }

            return new PageableDTO(arrayList, markLogs.getTotalElements(), markLogs.getTotalPages(), pageable.getPageNumber());
        }
        return null;
    }

    /**
     * 设备监控
     *
     * @return
     * @throws ParseException
     */
    @RequestMapping(value = "/listTypes", method = RequestMethod.GET)
    public Object listTypes() {
        return MarkLogOperType.listTypes();
    }
}
