package com.ffii.fpsms.modules.pickOrder.entity

import com.ffii.core.support.AbstractRepository
import jakarta.persistence.LockModeType
import org.springframework.data.jpa.repository.Lock
import org.springframework.data.jpa.repository.Query
import org.springframework.data.repository.query.Param
import org.springframework.stereotype.Repository
import java.time.LocalDateTime

@Repository
interface TruckLaneScheduleRepository : AbstractRepository<TruckLaneSchedule, Long> {
    fun findByIdAndDeletedFalse(id: Long): TruckLaneSchedule?

    @Lock(LockModeType.PESSIMISTIC_WRITE)
    @Query(
        """
        SELECT s FROM TruckLaneSchedule s
        WHERE s.id = :id AND s.deleted = false
        """,
    )
    fun findByIdAndDeletedFalseForUpdate(@Param("id") id: Long): TruckLaneSchedule?

    fun findAllByDeletedFalseAndStatusInOrderByExecuteAtDesc(
        statuses: Collection<TruckLaneScheduleStatus>,
    ): List<TruckLaneSchedule>

    @Query(
        """
        SELECT s FROM TruckLaneSchedule s
        WHERE s.deleted = false
          AND s.status = :pending
          AND s.executeAt <= :now
        ORDER BY s.executeAt ASC
        """,
    )
    fun findDuePending(
        @Param("now") now: LocalDateTime,
        @Param("pending") pending: TruckLaneScheduleStatus,
    ): List<TruckLaneSchedule>

    @Query(
        """
        SELECT COUNT(s) > 0 FROM TruckLaneSchedule s
        WHERE s.deleted = false
          AND s.status = :applying
          AND s.id <> :excludeId
        """,
    )
    fun existsOtherApplying(
        @Param("applying") applying: TruckLaneScheduleStatus,
        @Param("excludeId") excludeId: Long,
    ): Boolean

    @Query(
        """
        SELECT s FROM TruckLaneSchedule s
        WHERE s.deleted = false
          AND s.status = :applying
          AND s.modified < :staleBefore
        """,
    )
    fun findStaleApplying(
        @Param("applying") applying: TruckLaneScheduleStatus,
        @Param("staleBefore") staleBefore: LocalDateTime,
    ): List<TruckLaneSchedule>
}

