package ru.soune.nocopy.repository;

import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
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.docviewer.DockView;

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

@Repository
public interface DockViewRepository extends JpaRepository<DockView, Long> {

    List<DockView> findAllByFileId(String fileId);

    @Query("SELECT d.viewerIp FROM DockView d WHERE d.fileId IN :fileIds")
    List<String> findAllViewerIps(@Param("fileIds") List<String> fileIds);

    List<DockView> findAllByViewerId(Long viewerId);

    Optional<DockView> findByFileIdAndViewerId(String fileId, Long viewerId);

    List<DockView> findAllByViewerIp(String viewerIp);

    Page<DockView> findAllByFileIdOrderByCreatedAtDesc(String fileId, Pageable pageable);

    @Query("SELECT dv FROM DockView dv WHERE dv.fileId IN :fileIds")
    Page<DockView> findAllByFileIds(@Param("fileIds") List<String> fileIds, Pageable pageable);

    @Query("SELECT " +
            "COUNT(dv) as totalViews, " +
            "COUNT(DISTINCT dv.viewerIp) as uniqueIps, " +
            "COUNT(DISTINCT dv.viewerId) as uniqueUsers, " +
            "MAX(dv.createdAt) as lastViewDate, " +
            "MIN(dv.createdAt) as firstViewDate " +
            "FROM DockView dv " +
            "WHERE dv.fileId IN :fileIds")
    List<Object[]> findTotalViewsStatsByFileIds(@Param("fileIds") List<String> fileIds);

    Page<DockView> findAllByViewerIdOrderByCreatedAtDesc(Long viewerId, Pageable pageable);

    long countByFileId(String fileId);

    @Query("SELECT COUNT(DISTINCT dv.viewerIp) FROM DockView dv WHERE dv.fileId = :fileId")
    long countUniqueIpsByFileId(@Param("fileId") String fileId);

    @Query("SELECT COUNT(DISTINCT dv.viewerId) FROM DockView dv WHERE dv.fileId = :fileId")
    long countUniqueViewersByFileId(@Param("fileId") String fileId);

    @Query("SELECT MAX(dv.createdAt) FROM DockView dv WHERE dv.fileId = :fileId")
    Optional<LocalDateTime> findLastViewDateByFileId(@Param("fileId") String fileId);


    @Query("SELECT dv.fileId, " +
            "COUNT(dv) as totalViews, " +
            "COUNT(DISTINCT dv.viewerIp) as uniqueIps, " +
            "MAX(dv.createdAt) as lastViewDate " +
            "FROM DockView dv " +
            "GROUP BY dv.fileId " +
            "ORDER BY lastViewDate DESC")
    Page<Object[]> findViewsStatsPaginated(Pageable pageable);

    @Query("SELECT dv.fileId, " +
            "COUNT(dv) as totalViews, " +
            "COUNT(DISTINCT dv.viewerIp) as uniqueIps, " +
            "COUNT(DISTINCT dv.viewerId) as uniqueUsers, " +
            "MAX(dv.createdAt) as lastViewDate, " +
            "MIN(dv.createdAt) as firstViewDate " +
            "FROM DockView dv " +
            "WHERE dv.fileId = :fileId " +
            "GROUP BY dv.fileId")
    Optional<Object[]> findViewsStatsByFileId(@Param("fileId") String fileId);

    @Query("SELECT dv.fileId, " +
            "COUNT(dv) as totalViews, " +
            "COUNT(DISTINCT dv.viewerIp) as uniqueIps, " +
            "COUNT(DISTINCT dv.viewerId) as uniqueUsers, " +
            "MAX(dv.createdAt) as lastViewDate, " +
            "MIN(dv.createdAt) as firstViewDate " +
            "FROM DockView dv " +
            "WHERE dv.fileId IN :fileIds " +
            "GROUP BY dv.fileId")
    List<Object[]> findViewsStatsByFileIds(@Param("fileIds") List<String> fileIds);


    void deleteAllByFileId(String fileId);

    void deleteAllByCreatedAtBefore(LocalDateTime date);

    List<DockView> findAllByFileIdAndCreatedAtBetween(
            String fileId,
            LocalDateTime startDate,
            LocalDateTime endDate
    );

    boolean existsByFileIdAndViewerIp(String fileId, String viewerIp);

    List<DockView> findTop10ByFileIdOrderByCreatedAtDesc(String fileId);
}