package com.unicorn.hgzero.notification.repository;

import com.unicorn.hgzero.notification.domain.NotificationRecipient;
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 java.time.LocalDateTime;
import java.util.List;

/**
 * 알림 수신자 Repository
 *
 * 수신자별 알림 상태 관리 및 재시도 대상 조회
 * 발송 성공/실패 추적, 재시도 스케줄링 지원
 *
 * @author 준호 (Backend Developer)
 * @version 1.0
 * @since 2025-10-23
 */
@Repository
public interface NotificationRecipientRepository extends JpaRepository<NotificationRecipient, String> {

    /**
     * 알림별 수신자 목록 조회
     *
     * @param notificationId 알림 ID
     * @return 수신자 목록
     */
    @Query("SELECT nr FROM NotificationRecipient nr WHERE nr.notification.notificationId = :notificationId")
    List<NotificationRecipient> findByNotificationId(@Param("notificationId") String notificationId);

    /**
     * 재시도 대상 수신자 조회
     *
     * 상태가 RETRY이고 재시도 시간이 현재 시각 이전인 수신자 조회
     *
     * @param status 수신자 상태 (RETRY)
     * @param now 현재 시각
     * @return 재시도 대상 수신자 목록
     */
    List<NotificationRecipient> findByStatusAndNextRetryAtBefore(
        NotificationRecipient.RecipientStatus status,
        LocalDateTime now
    );

    /**
     * 이메일 주소로 수신자 히스토리 조회
     *
     * @param recipientEmail 수신자 이메일
     * @return 수신자 목록
     */
    List<NotificationRecipient> findByRecipientEmail(String recipientEmail);

    /**
     * 사용자 ID로 수신자 히스토리 조회
     *
     * @param recipientUserId 수신자 사용자 ID
     * @return 수신자 목록
     */
    List<NotificationRecipient> findByRecipientUserId(String recipientUserId);

    /**
     * 상태별 수신자 목록 조회
     *
     * @param status 수신자 상태
     * @return 수신자 목록
     */
    List<NotificationRecipient> findByStatus(NotificationRecipient.RecipientStatus status);

    /**
     * 특정 재시도 횟수 이상인 수신자 조회 (모니터링용)
     *
     * @param minRetryCount 최소 재시도 횟수
     * @return 수신자 목록
     */
    @Query("SELECT nr FROM NotificationRecipient nr WHERE nr.retryCount >= :minRetryCount")
    List<NotificationRecipient> findRecipientsWithHighRetryCount(@Param("minRetryCount") int minRetryCount);

    /**
     * 발송 실패 수신자 목록 조회 (기간별)
     *
     * @param status 수신자 상태 (FAILED)
     * @param startDate 시작 일시
     * @param endDate 종료 일시
     * @return 수신자 목록
     */
    @Query("SELECT nr FROM NotificationRecipient nr WHERE nr.status = :status AND nr.createdAt BETWEEN :startDate AND :endDate")
    List<NotificationRecipient> findFailedRecipientsByPeriod(
        @Param("status") NotificationRecipient.RecipientStatus status,
        @Param("startDate") LocalDateTime startDate,
        @Param("endDate") LocalDateTime endDate
    );

    /**
     * 알림별 상태별 수신자 개수 조회
     *
     * @param notificationId 알림 ID
     * @param status 수신자 상태
     * @return 수신자 개수
     */
    @Query("SELECT COUNT(nr) FROM NotificationRecipient nr WHERE nr.notification.notificationId = :notificationId AND nr.status = :status")
    long countByNotificationIdAndStatus(
        @Param("notificationId") String notificationId,
        @Param("status") NotificationRecipient.RecipientStatus status
    );

    /**
     * 사용자별 발송 성공 알림 개수 조회 (통계용)
     *
     * @param recipientUserId 수신자 사용자 ID
     * @param status 수신자 상태 (SENT)
     * @return 발송 성공 개수
     */
    long countByRecipientUserIdAndStatus(
        String recipientUserId,
        NotificationRecipient.RecipientStatus status
    );
}
