package de.votian.services.controller;

import de.votian.services.dto.TrackingDashboardDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.TrackingService;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.security.core.Authentication;

import java.time.LocalDate;
import java.util.List;

import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.when;

class TrackingControllerTest {

    private TrackingService trackingService;
    private AccessControlService accessControlService;
    private TrackingController controller;
    private Authentication authentication;
    private UserSessionDto user;

    @BeforeEach
    void setUp() {
        trackingService = mock(TrackingService.class);
        accessControlService = mock(AccessControlService.class);
        controller = new TrackingController(trackingService, accessControlService);
        authentication = mock(Authentication.class);
        user = new UserSessionDto();
        user.setUserType(1);
        user.setHeadquartersId(1L);

        when(accessControlService.sessionUser(authentication)).thenReturn(user);
        when(accessControlService.canViewTracking(user)).thenReturn(true);
        when(accessControlService.canAccessHeadquarters(user, 1L)).thenReturn(true);
    }

    @Test
    void getDashboardDelegatesForHeadquartersUser() {
        TrackingDashboardDto dto = new TrackingDashboardDto();
        when(trackingService.getDashboard(1L, LocalDate.of(2026, 3, 28), true, 8L, null)).thenReturn(dto);

        ResponseEntity<TrackingDashboardDto> response = controller.getDashboard(
                1L,
                LocalDate.of(2026, 3, 28),
                true,
                8L,
                authentication
        );

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isSameAs(dto);
        verify(trackingService).getDashboard(1L, LocalDate.of(2026, 3, 28), true, 8L, null);
    }

    @Test
    void getDashboardForCustomerUserForcesOwnCustomerScope() {
        user.setUserType(2);
        user.setCustomerId(18L);
        user.setAccessibleCostCenterIds(List.of(7L, 8L));

        when(accessControlService.isCustomerUser(user)).thenReturn(true);
        when(trackingService.getDashboard(1L, LocalDate.of(2026, 3, 28), false, 18L, List.of(7L, 8L)))
                .thenReturn(new TrackingDashboardDto());

        ResponseEntity<TrackingDashboardDto> response = controller.getDashboard(
                1L,
                LocalDate.of(2026, 3, 28),
                false,
                null,
                authentication
        );

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        verify(trackingService).getDashboard(1L, LocalDate.of(2026, 3, 28), false, 18L, List.of(7L, 8L));
    }

    @Test
    void getDashboardRejectsForeignCustomerFilterForCustomerUser() {
        user.setUserType(2);
        user.setCustomerId(18L);

        when(accessControlService.isCustomerUser(user)).thenReturn(true);

        ResponseEntity<TrackingDashboardDto> response = controller.getDashboard(
                1L,
                LocalDate.of(2026, 3, 28),
                false,
                99L,
                authentication
        );

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.FORBIDDEN);
    }
}
