package cn.com.qmth.stmms.biz.mark.dao;

import cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
import cn.com.qmth.stmms.common.enums.LibraryStatus;

import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;

import java.util.Date;
import java.util.List;
import java.util.Set;

public interface MarkLibraryDao extends JpaRepository<MarkLibrary, Integer>, JpaSpecificationExecutor<MarkLibrary> {

//    List<MarkLibrary> findByExamIdAndSubjectCode(Integer examId, String subjectCode, Pageable page);
//
//    List<MarkLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndStatus(Integer examId, String subjectCode,
//            Integer groupNumber, LibraryStatus status, Pageable page);
//
//    List<MarkLibrary> findByExamIdAndSubjectCodeAndGroupNumberAndStatusIn(Integer examId, String subjectCode,
//            Integer groupNumber, Set<LibraryStatus> statusSet, Pageable page);

    @Query("select l1 from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 and l1.status in (?5) and (l1.markerId=?4 or l1.markerId is null ) "
            + "and not exists (select l2 from MarkLibrary l2 where l2.studentId=l1.studentId and l2.id!=l1.id and l2.markerId=?4 and l2.markerScore is not null) ")
    List<MarkLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
            Set<LibraryStatus> statusSet, Pageable page);

    @Query("select l1 from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 and l1.status in (?6) and (l1.markerId=?4 or l1.markerId is null ) "
            + "and not exists (select l2 from MarkLibrary l2 where l2.studentId=l1.studentId and l2.id!=l1.id and l2.markerId=?4 and l2.markerScore is not null) "
            + "and exists (select mc.id from MarkerClass mc, ExamStudent s where l1.studentId=s.id and mc.examId=?1 and mc.userId=?5 and s.className=mc.className)")
    List<MarkLibrary> findUnMarkedFilterClass(Integer examId, String subjectCode, Integer groupNumber,
            Integer markerId, Integer userId, Set<LibraryStatus> statusSet, Pageable page);

    List<MarkLibrary> findByMarkerId(Integer markerId);

    @Query("select l from MarkLibrary l where l.markerId=?1 and l.status not in (?2)")
    List<MarkLibrary> findByMarkerIdAndStatusNotIn(Integer markerId, LibraryStatus... status);

    List<MarkLibrary> findByMarkerIdAndStatus(Integer markerId, LibraryStatus status, Pageable page);

    @Query("select l from MarkLibrary l where l.studentId=?1 order by l.groupNumber ")
    List<MarkLibrary> findByStudentId(Integer studentId);

    List<MarkLibrary> findByStudentIdAndGroupNumber(Integer studentId, Integer groupNumber);

    @Query("select l from MarkLibrary l where l.studentId=?1 and l.groupNumber=?2 and l.status in (?3) ")
    List<MarkLibrary> findByStudentIdAndGroupNumberAndStatus(Integer studentId, Integer groupNumber,
            LibraryStatus... status);

    @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3")
    long countByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);

//    @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3 and f.taskNumber=?4")
//    long countByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(Integer examId, String subjectCode,
//            Integer groupNumber, Integer taskNumber);

    @Query("select count(f) from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.groupNumber=?3 and f.status in (?4)")
    long countByExamIdAndSubjectCodeAndGroupNumberAndStatus(Integer examId, String subjectCode, Integer groupNumber,
            LibraryStatus... status);

    @Query("select count(f) from MarkLibrary f where f.studentId=?1 and f.groupNumber=?2")
    long countByStudentIdAndGroupNumber(Integer studentId, Integer groupNumber);

//    @Query("select count(f) from MarkLibrary f where f.studentId=?1 and f.markerId=?2")
//    long countByStudentIdAndMarkerId(Integer studentId, Integer markerId);

    @Query("select count(f) from MarkLibrary f where f.studentId=?1 and f.markerId=?2 and f.id!=?3")
    long countByStudentIdAndMarkerIdAndIdNotEqual(Integer studentId, Integer markerId, Integer id);

    @Query("select count(f) from MarkLibrary f where f.id=?1 and f.status=?2")
    long countByIdAndStatus(Integer id, LibraryStatus status);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary m set m.status=?4, m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null, m.markerSpent=null, "
            + "m.headerId=null , m.headerTime=null , m.headerScore=null , m.headerScoreList=null where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
    void resetByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber,
            LibraryStatus status);

//    @Modifying(clearAutomatically = true)
//    @Query("update MarkLibrary m set m.status=?2, m.markerId=null, m.markerTime=null, m.markerScore=null, m.markerScoreList=null, m.markerSpent=null, "
//            + "m.headerId=null , m.headerTime=null , m.headerScore=null , m.headerScoreList=null where m.markerId=?1 and m.status not in (?3) ")
//    void resetByMarkerId(Integer markerId, LibraryStatus status, LibraryStatus... notInStatus);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary m set m.status=?6, m.markerId=?2, m.rejectReason=?3, m.markerTime=null, m.markerScore=null, m.markerScoreList=null, m.markerSpent=null, "
            + "m.headerId=?4 , m.headerTime=?5 , m.headerScore=null , m.headerScoreList=null where m.id=?1 and m.status in (?7)")
    int resetById(Integer id, Integer markerId, String reason, Integer rejecterId, Date date, LibraryStatus newStatus,
            LibraryStatus... previousStatus);

    @Query("select f.markerId, count(f) as markerCount from MarkLibrary f where f.examId=?1 and f.status in (?2) group by f.markerId")
    List<Object[]> countMarkerAndStatus(Integer examId, LibraryStatus... status);

    @Query("select f.markerId, count(f) as markerCount from MarkLibrary f where f.examId=?1 and f.subjectCode in (?2) and f.status in (?3) and f.markerScore != -1 group by f.markerId")
    List<Object[]> countMarkerAndStatusAndSubjectCodeIn(Integer examId, Set<String> codes, LibraryStatus... status);

//    @Query("select f.markerId, count(f) as markerCount from MarkLibrary f where f.examId=?1 and f.subjectCode=?2 and f.status in (?3) group by f.markerId")
//    List<Object[]> countMarkerAndStatus(Integer examId, String subjectCode, LibraryStatus... status);

    @Query("select count(f) from MarkLibrary f where f.markerId=?1 and f.status in (?2)")
    long countByMarkerAndStatus(Integer markerId, LibraryStatus... status);

    @Modifying
    @Query("delete MarkLibrary m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3")
    void deleteByExamIdAndSubjectCodeAndGroupNumber(Integer examId, String subjectCode, Integer groupNumber);

    @Modifying
    @Query("delete MarkLibrary m where m.studentId=?1")
    void deleteByStudentId(Integer studentId);

    @Query("select l from MarkLibrary l where l.studentId=?1 and l.status=?2 order by l.groupNumber ")
    List<MarkLibrary> findByStudentIdAndStatus(Integer studentId, LibraryStatus status);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary m set m.headerId=?3, m.headerScore=?4, m.headerScoreList=?5, m.headerTime=?6, m.status=?7 "
            + " where m.studentId=?1 and m.groupNumber=?2")
    void updateHeaderResult(Integer studentId, Integer groupNumber, Integer userId, Double totalScore,
            String scoreList, Date updateTime, LibraryStatus arbitrated);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary m set m.status=?3 where m.studentId=?1 and m.groupNumber=?2")
    void updateByStudentIdAndGroupNumber(Integer studentId, Integer groupNumber, LibraryStatus status);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary l set l.status=?2, l.markerId=?3, l.markerScore=?4, l.markerScoreList=?5, l.markerTime=?6, "
            + "l.markerSpent=?7, l.rejectReason=?8, l.headerId=?9, l.headerTime=?10  where l.id=?1 and l.status in (?11) and (l.markerId=null or l.markerId=?3)")
    int updateMarkerResult(Integer id, LibraryStatus newStatus, Integer markerId, Double markerScore,
            String markerScoreList, Date markerTime, Integer spent, String resson, Integer rejecterId, Date rejectTime,
            LibraryStatus... previousStatus);

    @Query("select m.markerScore ,count(m) from MarkLibrary m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3 and m.markerId=?4 and m.markerScore != -1 and m.status in (?5)  group by m.markerScore ")
    List<Object[]> findScoreCount(int examId, String subjectCode, Integer groupNumber, Integer markerId,
            LibraryStatus... status);

    @Query("select m.markerScore from MarkLibrary m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3 and m.markerScore !=-1 and m.status in (?4) group by m.markerScore ")
    List<Double> findScore(int examId, String subjectCode, Integer groupNumber, LibraryStatus... status);

    @Modifying
    @Query("delete MarkLibrary m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3 and m.taskNumber=?4")
    void deleteByExamIdAndSubjectCodeAndGroupNumberAndTaskNumber(Integer examId, String subjectCode,
            Integer groupNumber, Integer taskNumber);

    MarkLibrary findByStudentIdAndGroupNumberAndTaskNumber(Integer studentId, Integer groupNumber, Integer taskNumber);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary l set l.status=?2, l.markerId=?3, l.markerTime=?4,l.markerScore=?6,l.markerScoreList=?7, "
            + "l.markerSpent=?5 where l.id=?1 and l.status in (?8) and (l.markerId=null or l.markerId=?3)")
    int updateProblemResult(Integer id, LibraryStatus newStatus, Integer markerId, Date markerTime, Integer spent,
            Double markerScore, String markerScoreList, LibraryStatus... previousStatus);

    @Query("select distinct m.subjectCode from MarkLibrary m where m.examId=?1 and m.status not in (?2) ")
    Set<String> findSubjectUnFinishByExamId(int examId, LibraryStatus... status);

    @Query("select count(l1) from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 "
            + "and exists (select mc.id from MarkerClass mc, ExamStudent s where l1.studentId=s.id  and mc.examId=?1 and mc.userId=?4 and s.className=mc.className)")
    long countFilterClass(Integer examId, String subjectCode, Integer groupNumber, Integer userId);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary l set l.unansweredCount=?2 where l.id=?1")
    void updateUnansweredCount(Integer id, int unansweredCount);

    @Query("select count(l1) from MarkLibrary l1 where l1.examId=?1 and l1.subjectCode=?2 and l1.groupNumber=?3 and l1.status in (?5) "
            + "and exists (select mc.id from MarkerClass mc, ExamStudent s where l1.studentId=s.id  and mc.examId=?1 and mc.userId=?4 and s.className=mc.className)")
    long countMarkedFilterClass(Integer examId, String subjectCode, Integer groupNumber, Integer userId,
            LibraryStatus... status);
}
