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

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

import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.PagingAndSortingRepository;

import cn.com.qmth.stmms.biz.exam.model.MarkGroup;
import cn.com.qmth.stmms.biz.exam.model.MarkGroupPK;
import cn.com.qmth.stmms.common.enums.MarkMode;
import cn.com.qmth.stmms.common.enums.MarkStatus;
import cn.com.qmth.stmms.common.enums.ScorePolicy;

public interface MarkGroupDao
        extends PagingAndSortingRepository<MarkGroup, MarkGroupPK>, JpaSpecificationExecutor<MarkGroup> {

    @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.number=?3")
    MarkGroup findOne(Integer examId, String subjectCode, Integer groupNumber);

    @Modifying(clearAutomatically = true)
    @Query("delete from MarkGroup q where q.pk.examId=?1")
    void deleteByExamId(Integer examId);

    @Modifying(clearAutomatically = true)
    @Query("delete from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
    void deleteByExamIdAndSubjectCode(Integer examId, String subjectCode);

    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.status in (?2)")
    long countByExamIdAndStatus(Integer examId, MarkStatus... status);

    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2")
    long countByExamIdAndSubjectCode(Integer examId, String subjectCode);

    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
            + "and q.pk.number=?3 and q.status in (?4)")
    long countByExamIdAndSubjectCodeAndNumberAndStatus(Integer examId, String subjectCode, Integer groupNumber,
            MarkStatus... status);

    @Query("select q from MarkGroup q where q.pk.examId=?1 order by q.pk.number")
    List<MarkGroup> findByExamId(Integer examId);

    @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 order by q.pk.number")
    List<MarkGroup> findByExamIdAndSubjectCode(Integer examId, String subjectCode);

    @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 "
            + "and q.status in (?3) order by q.pk.number")
    List<MarkGroup> findByExamIdAndSubjectCodeAndStatus(Integer examId, String subjectCode, MarkStatus... status);

    @Query("select q from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.status in (?3)"
            + "and q.doubleRate!=null and q.doubleRate>0 order by q.pk.number")
    List<MarkGroup> findByExamIdAndSubjectCodeAndStatusWithDouble(Integer examId, String subjectCode,
            MarkStatus... status);

    @Query("select q.pk.examId from MarkGroup q where q.status in (?1)")
    List<Integer> findExamIdByStatus(MarkStatus... status);

    @Query("select count(q) from MarkGroup q where q.pk.examId=?1")
    long countByExamId(Integer examId);

    @Query("select count(q) from MarkGroup q where q.pk.examId=?1 and q.pk.subjectCode=?2 and q.pk.number=?3 "
            + "and q.status=?4 and q.trialCount>q.libraryCount")
    long countByStatusAndTrailCount(Integer examId, String subjectCode, Integer number, MarkStatus status);

    @Query("select sum(g.totalScore) from MarkGroup g where g.pk.examId=?1 and g.pk.subjectCode=?2")
    Double sumTotalScore(Integer examId, String subjectCode);

    @Query("select sum(g.libraryCount) from MarkGroup g where g.pk.examId=?1")
    Integer sumLibraryCount(Integer examId);

    @Query("select sum(g.markedCount) from MarkGroup g where g.pk.examId=?1")
    Integer sumMarkedCount(Integer examId);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.libraryCount=?4, g.leftCount=(?4-g.markedCount) where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateLibraryCount(Integer examId, String subjectCode, Integer number, Integer totalCount);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.markedCount=?4, g.leftCount=(g.libraryCount-?4) where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateMarkedCount(Integer examId, String subjectCode, Integer number, Integer markedCount);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.leftCount = g.libraryCount, g.markedCount = 0 "
            + "where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void resetCount(Integer examId, String subjectCode, Integer number);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.picList=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updatePicList(Integer examId, String subjectCode, Integer number, String picList);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.totalScore=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateTotalScore(Integer examId, String subjectCode, Integer number, Double score);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.scorePolicy=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateScorePolicy(Integer examId, String subjectCode, Integer number, ScorePolicy policy);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.buildTime=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateBuildTime(Integer examId, String subjectCode, Integer number, Date time);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.buildTime=?3 where g.pk.examId=?1 and g.pk.subjectCode=?2")
    void updateBuildTime(Integer examId, String subjectCode, Date time);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.doubleRate=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateDoubleRate(Integer examId, String subjectCode, Integer number, Double doubleRate);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.markMode=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateMarkMode(Integer examId, String subjectCode, Integer number, MarkMode markMode);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.arbitrateThreshold=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateArbitrateThreshold(Integer examId, String subjectCode, Integer number, Double arbitrateThreshold);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.trialCount=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateTrialCount(Integer examId, String subjectCode, Integer number, Integer trialCount);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.sheetView=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3")
    void updateSheetView(Integer examId, String subjectCode, Integer number, boolean sheetView);

    @Modifying(clearAutomatically = true)
    @Query("update MarkGroup g set g.status=?4 where g.pk.examId=?1 and g.pk.subjectCode=?2 and g.pk.number=?3 "
            + "and g.status in (?5)")
    Integer updateStatus(Integer examId, String subjectCode, Integer number, MarkStatus newStatus,
            MarkStatus... currentStatus);

}
