package ru.soune.nocopy.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;
import ru.soune.nocopy.entity.file.FileEntity;
import ru.soune.nocopy.entity.violation.Violation;

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

@Repository
public interface ViolationRepository extends JpaRepository<Violation, Long> {

    Page<Violation> findByFileEntity(FileEntity file, Pageable pageable);

    Page<Violation> findByFileEntityAndStatus(FileEntity file, String status, Pageable pageable);

    Page<Violation> findByFileEntityAndCreatedDateBetween(FileEntity file, LocalDateTime startDate,
                                                          LocalDateTime endDate, Pageable pageable);

    List<Violation> findByFileEntity(FileEntity file);

    List<Violation> findByFileEntityAndStatus(FileEntity file, String status);

    List<Violation> findByFileEntityAndCreatedDateBetween(FileEntity file, LocalDateTime startDate,
                                                          LocalDateTime endDate);

    List<Violation> findByFileEntityAndStatusAndCreatedDateBetween(FileEntity file, String status,
                                                                   LocalDateTime startDate, LocalDateTime endDate);

    boolean existsByUrlHash(String urlHash);

    Optional<Violation> findById(Long id);

    void deleteByFileEntity(FileEntity file);

    List<Violation> findByFileEntityIn(List<FileEntity> files);

    List<Violation> findByFileEntityInAndStatusNot(List<FileEntity> files, String excludeStatus);

    Page<Violation> findByFileEntityIn(List<FileEntity> files, Pageable pageable);

    Page<Violation> findByFileEntityInAndStatus(List<FileEntity> files, String status, Pageable pageable);

    List<Violation> findByFileEntityInAndStatus(List<FileEntity> files, String status);

    Page<Violation> findByFileEntityInAndCreatedDateBetween(List<FileEntity> files, LocalDateTime startDate,
                                                            LocalDateTime endDate, Pageable pageable);

    List<Violation> findByFileEntityInAndStatusAndCreatedDateBetween(List<FileEntity> files, String status,
                                                                     LocalDateTime startDate, LocalDateTime endDate);

    List<Violation> findByFileEntityInAndCreatedDateBetween(List<FileEntity> files,
                                                            LocalDateTime startDate,
                                                            LocalDateTime endDate);

    List<Violation> findByFileEntityInAndCreatedDateBetweenAndStatusNot(List<FileEntity> files,
                                                            LocalDateTime startDate,
                                                            LocalDateTime endDate, String excludeStatus);

    Page<Violation> findByFileEntityInAndStatusNot(List<FileEntity> files, String excludeStatus, Pageable pageable);

    Page<Violation> findByFileEntityInAndStatusNotAndStatus(List<FileEntity> files, String excludeStatus,
                                                            String includeStatus, Pageable pageable);

    Page<Violation> findByFileEntityInAndStatusNotAndCreatedDateBetween(List<FileEntity> files, String excludeStatus,
                                                                        LocalDateTime startDate, LocalDateTime endDate,
                                                                        Pageable pageable);

    @Query("SELECT COUNT(v) FROM Violation v WHERE v.fileEntity.id IN :fileIds")
    long countByFileEntityIdIn(@Param("fileIds") List<String> fileIds);

    @Query("SELECT COUNT(v) FROM Violation v WHERE v.globalSearchResult.taskId = :taskId")
    long countByGlobalSearchResultTaskId(@Param("taskId") String taskId);

    List<Violation> findByFileEntityIn(List<FileEntity> files, Sort sort);

    List<Violation> findByFileEntityInAndStatus(List<FileEntity> files, String status, Sort sort);

    List<Violation> findByFileEntityInAndCreatedDateBetween(List<FileEntity> files, LocalDateTime startDate,
                                                            LocalDateTime endDate, Sort sort);

    List<Violation> findByFileEntityInAndStatusAndCreatedDateBetween(List<FileEntity> files, String status,
                                                                     LocalDateTime startDate, LocalDateTime endDate,
                                                                     Sort sort);

    @Query("SELECT COUNT(v.id) FROM Violation v")
    Long getTotalViolationsCount();

    @Query("SELECT COUNT(DISTINCT c.violation.id) FROM ComplaintEntity c WHERE c.violation IS NOT NULL")
    Long getViolationsWithComplaintCount();
}