package com.iqser.red.service.persistence.management.v1.processor.service.persistence.repository.annotationentity;

import java.time.OffsetDateTime;
import java.util.List;
import java.util.Optional;

import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Modifying;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;

import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.AnnotationEntityId;
import com.iqser.red.service.persistence.management.v1.processor.entity.annotations.ManualRedactionEntryEntity;

public interface ManualRedactionRepository extends JpaRepository<ManualRedactionEntryEntity, AnnotationEntityId>, AnnotationEntityRepository {

    @Modifying
    @Query("update ManualRedactionEntryEntity m set m.softDeletedTime = :softDeleteTime where m.id = :id")
    void updateSoftDelete(@Param("id") AnnotationEntityId id, @Param("softDeleteTime") OffsetDateTime softDeleteTime);


    @Modifying
    @Query("update ManualRedactionEntryEntity m set m.addToDictionary = :isAddOrRemoveFromDictionary, m.addToDossierDictionary = :isAddOrRemoveFromDossierDictionary where m.id = :id")
    void updateStatus(@Param("id") AnnotationEntityId id,
                      @Param("isAddOrRemoveFromDictionary") boolean isAddOrRemoveFromDictionary,
                      @Param("isAddOrRemoveFromDossierDictionary") boolean isAddOrRemoveFromDossierDictionary);


    @Query("select m from ManualRedactionEntryEntity m where m.id = :id and m.softDeletedTime is null")
    Optional<ManualRedactionEntryEntity> findAddRedaction(@Param("id") AnnotationEntityId id);


    @Query("select m from ManualRedactionEntryEntity m where m.id.fileId = :fileId and (:includeDeletions = true or m.softDeletedTime is null)")
    List<ManualRedactionEntryEntity> findByFileIdIncludeDeletions(@Param("fileId") String fileId, @Param("includeDeletions") boolean includeDeletions);


    @Query("select m from ManualRedactionEntryEntity m where m.id.fileId = :fileId and m.processedDate is null")
    List<ManualRedactionEntryEntity> findByFileIdAndUnprocessed(@Param("fileId") String fileId);


    @Query("""
            select m
            from ManualRedactionEntryEntity m
            where m.id.fileId = :fileId
            and ((:unprocessed = true and m.processedDate is null) or :unprocessed = false)
            and (:includeDeletions = true or m.softDeletedTime is null)
            and (:includeDictChanges = true or (m.addToDictionary = false and m.addToAllDossiers = false))
            """)
    List<ManualRedactionEntryEntity> findByFileIdAndOptions(@Param("fileId") String fileId,
                                                            @Param("includeDeletions") boolean includeDeletions,
                                                            @Param("unprocessed") boolean unprocessed,
                                                            @Param("includeDictChanges") boolean includeDictChanges);


    @Query("""
            select m
            from ManualRedactionEntryEntity m
            where m.id.fileId = :fileId
            and ((:unprocessed = true and m.processedDate is null) or :unprocessed = false)
            and (:includeDeletions = true or m.softDeletedTime is null)
            and (:includeDictChanges = true or (m.addToDictionary = false and m.addToAllDossiers = false))
            and m.id.annotationId in (:annotationIds)
            """)
    List<ManualRedactionEntryEntity> findByFileIdAndOptionsAndAnnotationIds(@Param("fileId") String fileId,
                                                                            @Param("includeDeletions") boolean includeDeletions,
                                                                            @Param("unprocessed") boolean unprocessed,
                                                                            @Param("includeDictChanges") boolean includeDictChanges,
                                                                            @Param("annotationIds") List<String> annotationIds);


    @Modifying
    @Query("update ManualRedactionEntryEntity m set m.softDeletedTime = :softDeletedTime where m.id.fileId in (:fileIds) and m.softDeletedTime is null")
    int softDeleteByFileIds(@Param("fileIds") List<String> fileIds, @Param("softDeletedTime") OffsetDateTime softDeletedTime);


    @Modifying
    @Query("update ManualRedactionEntryEntity m set m.softDeletedTime = null where m.id.fileId = :fileId and m.softDeletedTime >= :softDeletedTime")
    int undeleteByFileId(@Param("fileId") String fileId, @Param("softDeletedTime") OffsetDateTime softDeletedTime);


    @Modifying
    @Query("delete ManualRedactionEntryEntity m where m.id.fileId in (:fileIds)")
    int deleteByFileIds(@Param("fileIds") List<String> fileIds);


    @Modifying
    @Query("update ManualRedactionEntryEntity m set m.processedDate = :processedDate where m.id = :annotationEntityId")
    void markAsProcessed(@Param("annotationEntityId") AnnotationEntityId annotationEntityId, @Param("processedDate") OffsetDateTime processedDate);


    @Modifying
    @Query("update ManualRedactionEntryEntity e set e.requestDate = :requestDate where e.id = :annotationEntityId")
    int updateRequestDateById(@Param("annotationEntityId") AnnotationEntityId annotationEntityId, @Param("requestDate") OffsetDateTime requestDate);

}
