package com.tourguide.modules.order.service; import com.tourguide.modules.order.entity.TourOrder; import com.tourguide.modules.order.mapper.TourOrderMapper; import com.tourguide.modules.user.entity.GuideReceivingSession; import com.tourguide.modules.user.mapper.GuideRealtimeStatusMapper; import com.tourguide.modules.user.mapper.GuideReceivingSessionMapper; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import java.time.LocalDateTime; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; class GuideSessionTransitionServiceTest { private GuideReceivingSessionMapper sessionMapper; private TourOrderMapper orderMapper; private GuideRealtimeStatusMapper realtimeStatusMapper; private GuideSessionTransitionService service; @BeforeEach void setUp() { sessionMapper = mock(GuideReceivingSessionMapper.class); orderMapper = mock(TourOrderMapper.class); realtimeStatusMapper = mock(GuideRealtimeStatusMapper.class); service = new GuideSessionTransitionService(sessionMapper, orderMapper, realtimeStatusMapper); } @Test void shouldReopenPrivateSessionAfterItsOrderIsCancelled() { TourOrder order = cancelledOrder(8L, 18L, 3); GuideReceivingSession session = session("PRIVATE", "ASSIGNED"); when(sessionMapper.selectForUpdate(18L, 8L)).thenReturn(session); when(orderMapper.countPendingMeetingBySession(18L, 8L)).thenReturn(0L); when(sessionMapper.reopenPrivateAfterOrderCancellation(18L, 8L)).thenReturn(1); service.restoreAfterOrderCancellation(order); verify(sessionMapper).reopenPrivateAfterOrderCancellation(18L, 8L); verify(realtimeStatusMapper).enableReceiving(8L); } @Test void shouldReleaseOnlyCancelledGroupCapacityWhenOtherOrdersRemain() { TourOrder order = cancelledOrder(8L, 18L, 3); GuideReceivingSession session = session("GROUP", "RECEIVING"); when(sessionMapper.selectForUpdate(18L, 8L)).thenReturn(session); when(orderMapper.countPendingMeetingBySession(18L, 8L)).thenReturn(1L); service.restoreAfterOrderCancellation(order); verify(sessionMapper).releaseGroupCapacity(18L, 8L, 3); verify(sessionMapper, never()).resetGroupAfterOrderCancellation(18L, 8L); } @Test void shouldResetGroupSessionWhenItsLastOrderIsCancelled() { TourOrder order = cancelledOrder(8L, 18L, 3); GuideReceivingSession session = session("GROUP", "RECEIVING"); when(sessionMapper.selectForUpdate(18L, 8L)).thenReturn(session); when(orderMapper.countPendingMeetingBySession(18L, 8L)).thenReturn(0L); service.restoreAfterOrderCancellation(order); verify(sessionMapper).resetGroupAfterOrderCancellation(18L, 8L); verify(sessionMapper, never()).releaseGroupCapacity(18L, 8L, 3); } @Test void shouldCompleteSessionAndDisableGuideAfterLectureEnds() { GuideReceivingSession session = session("GROUP", "IN_SERVICE"); LocalDateTime completedAt = LocalDateTime.of(2026, 9, 14, 12, 30); when(orderMapper.completeSessionOrders(8L, 18L, completedAt)).thenReturn(2); assertThat(service.completeSession(session, completedAt)).isTrue(); verify(orderMapper).completeSessionOrders(8L, 18L, completedAt); verify(sessionMapper).stopServiceSession(18L, 8L); verify(realtimeStatusMapper).stopGuide(8L); } @Test void shouldLeaveSessionOpenWhenNoActiveOrderCanBeCompleted() { GuideReceivingSession session = session("GROUP", "IN_SERVICE"); LocalDateTime completedAt = LocalDateTime.of(2026, 9, 14, 12, 30); when(orderMapper.completeSessionOrders(8L, 18L, completedAt)).thenReturn(0); assertThat(service.completeSession(session, completedAt)).isFalse(); verify(sessionMapper, never()).stopServiceSession(18L, 8L); verify(realtimeStatusMapper, never()).stopGuide(8L); } private TourOrder cancelledOrder(Long guideId, Long sessionId, int peopleCount) { TourOrder order = new TourOrder(); order.setGuideId(guideId); order.setReceivingSessionId(sessionId); order.setPeopleCount(peopleCount); return order; } private GuideReceivingSession session(String mode, String status) { GuideReceivingSession session = new GuideReceivingSession(); session.setId(18L); session.setGuideId(8L); session.setReceivingMode(mode); session.setStatus(status); return session; } }