package de.votian.services.controller;

import de.votian.services.dto.LonghaulDashboardDto;
import de.votian.services.dto.LonghaulJobDetailDto;
import de.votian.services.dto.UserSessionDto;
import de.votian.services.security.AccessControlService;
import de.votian.services.service.LonghaulRemoteDbService;
import de.votian.services.service.LonghaulService;
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.util.Objects;

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 LonghaulControllerTest {

    private LonghaulService longhaulService;
    private LonghaulRemoteDbService longhaulRemoteDbService;
    private AccessControlService accessControlService;
    private LonghaulController controller;
    private Authentication authentication;
    private UserSessionDto user;

    @BeforeEach
    void setUp() {
        longhaulService = mock(LonghaulService.class);
        longhaulRemoteDbService = mock(LonghaulRemoteDbService.class);
        accessControlService = mock(AccessControlService.class);
        controller = new LonghaulController(longhaulService, longhaulRemoteDbService, accessControlService);
        authentication = mock(Authentication.class);
        user = new UserSessionDto();
        user.setUserType(1);
        user.setHeadquartersId(1L);
        user.setEmployeeId(23L);

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

    @Test
    void getDashboardRejectsUnavailableRemoteDbRequest() {
        when(accessControlService.canUseLonghaulRemoteDb(user)).thenReturn(false);

        ResponseEntity<LonghaulDashboardDto> response = controller.getDashboard(1L, true, authentication);

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

    @Test
    void getDashboardMarksRemoteDbAvailabilityAndDelegatesRemoteFlag() {
        LonghaulDashboardDto dto = new LonghaulDashboardDto();
        dto.setRemoteDbActive(true);

        when(accessControlService.canUseLonghaulRemoteDb(user)).thenReturn(true);
        when(longhaulRemoteDbService.isConfigured()).thenReturn(true);
        when(longhaulService.getDashboard(1L, true)).thenReturn(dto);

        ResponseEntity<LonghaulDashboardDto> response = controller.getDashboard(1L, true, authentication);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isNotNull();
        assertThat(Objects.requireNonNull(response.getBody()).isRemoteDbAvailable()).isTrue();
        verify(longhaulService).getDashboard(1L, true);
    }

    @Test
    void returnToHeadquartersPassesRemoteFlagToService() {
        when(accessControlService.canUseLonghaulRemoteDb(user)).thenReturn(true);
        when(longhaulRemoteDbService.isConfigured()).thenReturn(true);

        ResponseEntity<Void> response = controller.returnToHeadquarters(15L, 1L, true, authentication);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        verify(longhaulService).returnJobToHeadquarters(1L, 15L, true);
    }

    @Test
    void getJobDetailRejectsUnavailableRemoteDbRequest() {
        when(accessControlService.canUseLonghaulRemoteDb(user)).thenReturn(false);

        ResponseEntity<LonghaulJobDetailDto> response = controller.getJobDetail(15L, 1L, true, authentication);

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

    @Test
    void getJobDetailDelegatesRemoteFlagToService() {
        LonghaulJobDetailDto dto = new LonghaulJobDetailDto();
        dto.setRemoteDbActive(true);

        when(accessControlService.canUseLonghaulRemoteDb(user)).thenReturn(true);
        when(longhaulRemoteDbService.isConfigured()).thenReturn(true);
        when(longhaulService.getJobDetail(1L, 15L, true)).thenReturn(dto);

        ResponseEntity<LonghaulJobDetailDto> response = controller.getJobDetail(15L, 1L, true, authentication);

        assertThat(response.getStatusCode()).isEqualTo(HttpStatus.OK);
        assertThat(response.getBody()).isNotNull();
        assertThat(Objects.requireNonNull(response.getBody()).isRemoteDbActive()).isTrue();
        verify(longhaulService).getJobDetail(1L, 15L, true);
    }
}
