package space.nstart.pcp.slots_service.repository

import jakarta.transaction.Transactional
import org.springframework.data.jpa.repository.EntityGraph
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 space.nstart.pcp.slots_service.entity.BookedSlotEntity
import java.util.Optional

interface BookedSlotsRepository : JpaRepository<BookedSlotEntity, Long>{

        fun findByBookedSlotId(id : Long) : Optional<BookedSlotEntity>

        fun findBySlot_SlotIdAndCycle(id : Long, cycle : Long) : BookedSlotEntity?

        fun findBySlot_SatelliteIdAndCycleIn(id : Long, n : Iterable<Long>) : List<BookedSlotEntity>

        fun findBySlot_SatelliteIdAndCycleBetween(id: Long, cycleBegin: Long, cycleEnd: Long): List<BookedSlotEntity>

        fun findBySlot_SatelliteIdInAndCycleBetween(ids: Collection<Long>, cycleBegin: Long, cycleEnd: Long): List<BookedSlotEntity>

        fun countBySlot_SatelliteId(id: Long): Long

        @EntityGraph(attributePaths = ["slot"])
        fun findAllByBookedSlotIdIn(ids: Collection<Long>): List<BookedSlotEntity>

        @EntityGraph(attributePaths = ["slot"])
        fun findAllByStatus(status: String): List<BookedSlotEntity>

        @EntityGraph(attributePaths = ["slot", "requests"])
        @Query("""
                select distinct bookedSlot
                from BookedSlotEntity bookedSlot
                where bookedSlot.slot.satelliteId in :satelliteIds
                  and bookedSlot.cycle between :cycleBegin and :cycleEnd
        """)
        fun findBookingDetailsBySatelliteIdsAndCycleBetween(
                @Param("satelliteIds") satelliteIds: Collection<Long>,
                @Param("cycleBegin") cycleBegin: Long,
                @Param("cycleEnd") cycleEnd: Long
        ): List<BookedSlotEntity>

        @EntityGraph(attributePaths = ["slot", "requests"])
        @Query("""
                select distinct bookedSlot
                from BookedSlotEntity bookedSlot
                where bookedSlot.slot.satelliteId in :satelliteIds
        """)
        fun findBookingDetailsBySatelliteIds(
                @Param("satelliteIds") satelliteIds: Collection<Long>
        ): List<BookedSlotEntity>

        @Modifying
        @Transactional
        @Query("DELETE FROM  booked_slot WHERE booked_slot_id =:id", nativeQuery = true)
        fun deleteByBookedSlotId(@Param("id") id : Long) : Int
}
