package space.nstart.pcp.slots_service.service

import org.slf4j.LoggerFactory
import org.springframework.scheduling.annotation.Scheduled
import org.springframework.stereotype.Component
import space.nstart.pcp.pcp_types_lib.dto.requests.slots.BookedSlotStatus
import space.nstart.pcp.slots_service.configuration.BookedSlotsTimeoutProperties
import space.nstart.pcp.slots_service.repository.BookedSlotsRepository
import java.time.Clock
import java.time.LocalDateTime

@Component
class BookedSlotTimeoutScheduler(
    private val bookedSlotsRepository: BookedSlotsRepository,
    private val bookedSlotStatusService: BookedSlotStatusUpdater,
    private val bookedSlotTimeResolver: BookedSlotTimeResolver,
    private val properties: BookedSlotsTimeoutProperties,
    private val clock: Clock = Clock.systemDefaultZone()
) {

    private val logger = LoggerFactory.getLogger(this::class.java)

    @Scheduled(fixedDelayString = "#{@bookedSlotsTimeoutProperties.timeoutCheckInterval.toMillis()}")
    fun markTimedOutBookedSlots() {
        val thresholdTime = LocalDateTime.now(clock).minus(properties.timeoutThreshold)
        val staleBookedSlotIds = bookedSlotsRepository.findAllByStatus(BookedSlotStatus.BOOKED.name)
            .filter { bookedSlot ->
                val actualStart = bookedSlotTimeResolver.resolveBookedSlotStartTime(bookedSlot) ?: return@filter false
                actualStart.isBefore(thresholdTime)
            }
            .mapNotNull { it.bookedSlotId }

        if (staleBookedSlotIds.isEmpty()) {
            logger.debug("Booked slot timeout scheduler found no stale slots")
            return
        }

        val updated = bookedSlotStatusService.updateBookedSlotsStatus(
            bookedSlotIds = staleBookedSlotIds,
            targetStatus = BookedSlotStatus.FAILED_TIMEOUT,
            context = "timeout-scheduler"
        )
        logger.info(
            "Booked slot timeout scheduler marked stale slots: found={}, updated={}, thresholdTime={}",
            staleBookedSlotIds.size,
            updated,
            thresholdTime
        )
    }
}
