package space.nstart.pcp_tgu_service.service

import org.junit.jupiter.api.Test
import org.mockito.Mockito.mock
import org.mockito.Mockito.times
import org.mockito.Mockito.verify
import org.mockito.Mockito.`when`
import space.nstart.pcp_tgu_service.dto.StationParamsChangedMessage
import space.nstart.pcp_tgu_service.entity.SpacecraftSnapshotEntity
import space.nstart.pcp_tgu_service.repository.ProcessedPlanDecisionEventRepository
import space.nstart.pcp_tgu_service.repository.SpacecraftSnapshotRepository
import java.time.LocalDateTime
import java.util.UUID

class HandleStationParamsChangedUseCaseTest {

    @Test
    fun `enqueues visibility refresh for every active spacecraft once per event`() {
        val processedRepository = mock(ProcessedPlanDecisionEventRepository::class.java)
        `when`(processedRepository.insertIfAbsent(anyNonNull(), anyNonNull())).thenReturn(1).thenReturn(0)
        val snapshotRepository = mock(SpacecraftSnapshotRepository::class.java)
        `when`(snapshotRepository.findAllByActiveTrue()).thenReturn(
            listOf(
                SpacecraftSnapshotEntity(spacecraftId = "1", noradId = 100L),
                SpacecraftSnapshotEntity(spacecraftId = "2", noradId = 200L)
            )
        )
        val refreshJobService = mock(VisibilityRefreshJobService::class.java)
        val useCase = HandleStationParamsChangedUseCase(processedRepository, snapshotRepository, refreshJobService)
        val message = message()

        useCase.handle(message)
        useCase.handle(message)

        verify(refreshJobService, times(1)).enqueue("1", 100L, "STATION_PARAMS_CHANGED")
        verify(refreshJobService, times(1)).enqueue("2", 200L, "STATION_PARAMS_CHANGED")
    }

    private fun message(): StationParamsChangedMessage =
        StationParamsChangedMessage(
            eventId = UUID.randomUUID(),
            stationId = "ST-7",
            occurredAt = LocalDateTime.now(),
            reason = "OUT_OF_SERVICE"
        )

    @Suppress("UNCHECKED_CAST")
    private fun <T> anyNonNull(): T {
        org.mockito.ArgumentMatchers.any<T>()
        return null as T
    }
}
