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

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

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.notification.NotificationEntity;

public interface NotificationRepository extends JpaRepository<NotificationEntity, Long> {

    @Query("select count(n) from NotificationEntity n  where "
           + " (exists (select e from NotificationPreferencesEntity e where e.userId = :userId) and n.notificationType in ( select apn from NotificationPreferencesEntity p join p.inAppNotifications apn  where p.userId = :userId and p.inAppNotificationsEnabled = true )) "
           + " and n.softDeleted is null and n.userId = :userId and n.creationDate > :since")
    int hasInAppNotificationForUser(@Param("userId") String userId, @Param("since") OffsetDateTime since);


    @Query("""
            select n from NotificationEntity n  where
            (exists (select e from NotificationPreferencesEntity e where e.userId = :userId) and n.notificationType in
                (select apn from NotificationPreferencesEntity p join p.inAppNotifications apn  where p.userId = :userId and p.inAppNotificationsEnabled = true))
            and n.softDeleted is null and n.userId = :userId order by n.creationDate desc""")
    List<NotificationEntity> findAppNotificationsForUser(@Param("userId") String userId);


    @Query("""
            select n from NotificationEntity n where
            (exists (select e from NotificationPreferencesEntity e where e.userId = :userId) and n.notificationType in
                (select apn from NotificationPreferencesEntity p join p.inAppNotifications apn  where p.userId = :userId and p.inAppNotificationsEnabled = true))
            and n.seenDate is null and n.softDeleted is null and n.userId = :userId order by n.creationDate desc""")
    List<NotificationEntity> findUnseenNotificationsForUser(@Param("userId") String userId);


    @Modifying
    @Query("update NotificationEntity n set n.seenDate = :seenDate where n.id = :notificationId and n.userId = :userId")
    int setSeenDate(@Param("userId") String userId, @Param("notificationId") long notificationId, @Param("seenDate") OffsetDateTime seenDate);


    @Modifying
    @Query("update NotificationEntity n set n.readDate = :readDate where n.id = :notificationId and n.userId = :userId")
    int setReadDate(@Param("userId") String userId, @Param("notificationId") long notificationId, @Param("readDate") OffsetDateTime readDate);


    @Modifying
    @Query("update NotificationEntity n set n.softDeleted = :softDeleted where n.id = :notificationId and n.userId = :userId")
    int softDelete(@Param("userId") String userId, @Param("notificationId") long notificationId, @Param("softDeleted") OffsetDateTime softDeleted);


    @Modifying
    @Query("update NotificationEntity n set n.softDeleted = :softDeleted where n.userId = :userId")
    void deleteAllByUserId(@Param("userId") String userId, @Param("softDeleted") OffsetDateTime softDeleted);


    @Modifying
    @Query("update NotificationEntity n set n.softDeleted = :softDeleted where n.userId = :userId and n.notificationType in :removedNotificationTypes")
    void deleteAllByUserIdAndNotificationTypeIn(@Param("userId") String userId,
                                                @Param("removedNotificationTypes") List<String> removedNotificationTypes,
                                                @Param("softDeleted") OffsetDateTime softDeleted);


    @Query("select n from NotificationEntity n  where "
           + " (exists (select e from NotificationPreferencesEntity e where e.userId = :userId) and n.notificationType in ( select apn from NotificationPreferencesEntity p join p.emailNotifications apn  where p.userId = :userId and p.emailNotificationsEnabled = true )) "
           + " and n.userId = :userId and n.creationDate  >= :from and n.creationDate <= :to order by n.creationDate desc")
    List<NotificationEntity> findEmailNotificationsForUserId(@Param("userId") String userId, @Param("from") OffsetDateTime from, @Param("to") OffsetDateTime to);

}
