package com.kt.event.participation.domain.participant;

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 java.util.List;
import java.util.Optional;

/**
 * 참여자 리포지토리
 *
 * @author Digital Garage Team
 * @since 2025-01-24
 */
@Repository
public interface ParticipantRepository extends JpaRepository<Participant, Long> {

    /**
     * 참여자 ID로 조회
     *
     * @param participantId 참여자 ID
     * @return 참여자 Optional
     */
    Optional<Participant> findByParticipantId(String participantId);

    /**
     * 이벤트 ID와 전화번호로 중복 참여 체크
     *
     * @param eventId 이벤트 ID
     * @param phoneNumber 전화번호
     * @return 참여 여부
     */
    boolean existsByEventIdAndPhoneNumber(String eventId, String phoneNumber);

    /**
     * 이벤트 ID로 참여자 목록 조회 (페이징)
     *
     * @param eventId 이벤트 ID
     * @param pageable 페이징 정보
     * @return 참여자 페이지
     */
    Page<Participant> findByEventIdOrderByCreatedAtDesc(String eventId, Pageable pageable);

    /**
     * 이벤트 ID와 매장 방문 여부로 참여자 목록 조회 (페이징)
     *
     * @param eventId 이벤트 ID
     * @param storeVisited 매장 방문 여부
     * @param pageable 페이징 정보
     * @return 참여자 페이지
     */
    Page<Participant> findByEventIdAndStoreVisitedOrderByCreatedAtDesc(
        String eventId, Boolean storeVisited, Pageable pageable);

    /**
     * 이벤트 ID로 전체 참여자 수 조회
     *
     * @param eventId 이벤트 ID
     * @return 참여자 수
     */
    long countByEventId(String eventId);

    /**
     * 이벤트 ID로 당첨자 목록 조회 (페이징)
     *
     * @param eventId 이벤트 ID
     * @param pageable 페이징 정보
     * @return 당첨자 페이지
     */
    Page<Participant> findByEventIdAndIsWinnerTrueOrderByWinnerRankAsc(String eventId, Pageable pageable);

    /**
     * 이벤트 ID로 당첨자 수 조회
     *
     * @param eventId 이벤트 ID
     * @return 당첨자 수
     */
    long countByEventIdAndIsWinnerTrue(String eventId);

    /**
     * 이벤트 ID로 참여자 ID 최대값 조회 (순번 생성용)
     *
     * @param eventId 이벤트 ID
     * @return 최대 ID
     */
    @Query("SELECT MAX(p.id) FROM Participant p WHERE p.eventId = :eventId")
    Optional<Long> findMaxIdByEventId(@Param("eventId") String eventId);

    /**
     * 이벤트 ID로 비당첨자 목록 조회 (추첨용)
     *
     * @param eventId 이벤트 ID
     * @return 비당첨자 목록
     */
    List<Participant> findByEventIdAndIsWinnerFalse(String eventId);

    /**
     * 이벤트 ID와 참여자 ID로 조회
     *
     * @param eventId 이벤트 ID
     * @param participantId 참여자 ID
     * @return 참여자 Optional
     */
    Optional<Participant> findByEventIdAndParticipantId(String eventId, String participantId);

    /**
     * 특정 날짜 패턴의 참여자 ID 중 최대 순번 조회
     *
     * @param datePrefix 날짜 접두사 (예: "prt_20251028_")
     * @return 최대 순번
     */
    @Query(value = "SELECT COALESCE(MAX(CAST(SUBSTRING(participant_id FROM LENGTH(?1) + 1) AS INTEGER)), 0) " +
                  "FROM participants " +
                  "WHERE participant_id LIKE CONCAT(?1, '%')",
           nativeQuery = true)
    Integer findMaxSequenceByDatePrefix(@Param("datePrefix") String datePrefix);
}
