package com.unicorn.hgzero.notification.repository;

import com.unicorn.hgzero.notification.domain.Notification;
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;
import java.util.Optional;

/**
 * 알림 Repository
 *
 * 알림 이력 조회 및 저장을 담당
 * 이벤트 ID 기반 중복 방지, 상태별 조회, 기간별 조회 지원
 *
 * @author 준호 (Backend Developer)
 * @version 1.0
 * @since 2025-10-23
 */
@Repository
public interface NotificationRepository extends JpaRepository<Notification, String> {

    /**
     * 이벤트 ID로 알림 조회 (중복 발송 방지용)
     *
     * @param eventId 이벤트 고유 ID
     * @return 알림 정보
     */
    Optional<Notification> findByEventId(String eventId);

    /**
     * 참조 대상으로 알림 목록 조회
     *
     * @param referenceId 참조 대상 ID (meetingId 또는 todoId)
     * @param referenceType 참조 유형 (MEETING, TODO)
     * @return 알림 목록
     */
    List<Notification> findByReferenceIdAndReferenceType(
        String referenceId,
        Notification.ReferenceType referenceType
    );

    /**
     * 상태별 알림 목록 조회 (배치 처리용)
     *
     * @param statuses 조회할 상태 목록
     * @return 알림 목록
     */
    List<Notification> findByStatusIn(List<Notification.NotificationStatus> statuses);

    /**
     * 기간별 알림 목록 조회
     *
     * @param startDate 시작 일시
     * @param endDate 종료 일시
     * @return 알림 목록
     */
    List<Notification> findByCreatedAtBetween(LocalDateTime startDate, LocalDateTime endDate);

    /**
     * 알림 유형별 알림 목록 조회
     *
     * @param notificationType 알림 유형
     * @return 알림 목록
     */
    List<Notification> findByNotificationType(Notification.NotificationType notificationType);

    /**
     * 채널별 알림 목록 조회
     *
     * @param channel 발송 채널
     * @return 알림 목록
     */
    List<Notification> findByChannel(Notification.NotificationChannel channel);

    /**
     * 발송 실패 건수가 특정 수 이상인 알림 조회 (모니터링용)
     *
     * @param minFailedCount 최소 실패 건수
     * @return 알림 목록
     */
    @Query("SELECT n FROM Notification n WHERE n.failedCount >= :minFailedCount")
    List<Notification> findNotificationsWithHighFailureRate(@Param("minFailedCount") int minFailedCount);

    /**
     * 이벤트 ID 존재 여부 확인 (중복 발송 방지용)
     *
     * @param eventId 이벤트 고유 ID
     * @return 존재 여부
     */
    boolean existsByEventId(String eventId);

    /**
     * 특정 상태이고 특정 기간 내 생성된 알림 개수 조회 (통계용)
     *
     * @param status 알림 상태
     * @param startDate 시작 일시
     * @param endDate 종료 일시
     * @return 알림 개수
     */
    @Query("SELECT COUNT(n) FROM Notification n WHERE n.status = :status AND n.createdAt BETWEEN :startDate AND :endDate")
    long countByStatusAndCreatedAtBetween(
        @Param("status") Notification.NotificationStatus status,
        @Param("startDate") LocalDateTime startDate,
        @Param("endDate") LocalDateTime endDate
    );
}
