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

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

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 cn.com.qmth.stmms.biz.mark.model.MarkLibrary;
import cn.com.qmth.stmms.common.enums.LibraryStatus;

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 not exists (select l2 from MarkLibrary l2 where l2.studentId=l1.studentId and l2.id!=l1.id and l2.markerId=?4)")
    List<MarkLibrary> findUnMarked(Integer examId, String subjectCode, Integer groupNumber, Integer markerId,
            Set<LibraryStatus> statusSet, Pageable page);

    List<MarkLibrary> findByMarkerId(Integer markerId);

    @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);

    List<MarkLibrary> findByStudentIdAndGroupNumberAndStatus(Integer studentId, Integer groupNumber,
            LibraryStatus status);

    @Query("select count(*) 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(*) 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(*) 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(*) from MarkLibrary f where f.studentId=?1 and f.groupNumber=?2")
    long countByStudentIdAndGroupNumber(Integer studentId, Integer groupNumber);

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

    @Query("select count(*) 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 distinct l.campusId from MarkLibrary l where l.examId=?1 and l.tags is not null")
    List<Integer> findTagCampusId(Integer examId);

    @Query("select distinct l.subjectCode from MarkLibrary l where l.examId=?1 and l.tags is not null")
    List<String> findTagSubjectCode(Integer examId);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary m set m.status=?4, m.tags=null, 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.tags=null, 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!=?3 and m.status!=?4 ")
    void resetByMarkerId(Integer markerId, LibraryStatus status, LibraryStatus libraryStatus1,
            LibraryStatus libraryStatus2);

    @Modifying(clearAutomatically = true)
    @Query("update MarkLibrary m set m.status=?2, m.tags=null, 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.id=?1 and m.status=?3")
    int resetById(Integer id, LibraryStatus newStatus, LibraryStatus previousStatus);

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

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

    @Query("select count(*) 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.tags=?8 where l.id=?1 and l.status in (?9) 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 tags, LibraryStatus... previousStatus);

    @Query("select m.markerScore ,count(*) from MarkLibrary m where m.examId=?1 and m.subjectCode=?2 and m.groupNumber=?3 and m.markerId=?4 and m.status=?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.status=?4 group by m.markerScore ")
    List<Double> findScore(int examId, String subjectCode, Integer groupNumber, LibraryStatus status);

}
