package com.ufund.api.ufundapi.controller;

import com.ufund.api.ufundapi.model.Need;
import com.ufund.api.ufundapi.persistence.CupboardFileDao;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.http.HttpStatus;

import java.io.IOException;

import static org.junit.jupiter.api.Assertions.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

public class CupboardControllerTest {
    private CupboardController cupboardController;
    private CupboardFileDao mockCupboardDAO;

    @BeforeEach
    public void setupCupboardDAO() {
        mockCupboardDAO = mock(CupboardFileDao.class);
        cupboardController = new CupboardController(mockCupboardDAO);
    }

    @Test
    public void createNeed() throws IOException {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.createNeed(need)).thenReturn(need);

        var res = cupboardController.createNeed(need);

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertEquals(need, res.getBody());
    }

    @Test
    public void getNeeds() {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.getNeeds()).thenReturn(new Need[]{need});

        var res = cupboardController.getNeeds();

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertArrayEquals(new Need[]{need}, res.getBody());
    }

    @Test
    public void getNeedsEmpty() {
        when(mockCupboardDAO.getNeeds()).thenReturn(new Need[]{});

        var res = cupboardController.getNeeds();

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertArrayEquals(new Need[]{}, res.getBody());
    }

    @Test
    public void searchNeeds() {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.findNeeds("Na")).thenReturn(new Need[]{need});

        var res = cupboardController.searchNeeds("Na");

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertArrayEquals(new Need[]{need}, res.getBody());
    }

    @Test
    public void searchNeedsEmpty() {
        when(mockCupboardDAO.findNeeds("Na")).thenReturn(new Need[]{});

        var res = cupboardController.searchNeeds("Na");

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertArrayEquals(new Need[]{}, res.getBody());
    }

    @Test
    public void getNeed() {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.getNeed(need.getId())).thenReturn(need);

        var res = cupboardController.getNeed(need.getId());

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertEquals(need, res.getBody());
    }

    @Test
    public void getNeedFail() {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.getNeed(need.getId())).thenReturn(null);

        var res = cupboardController.getNeed(need.getId());

        assertEquals(HttpStatus.NOT_FOUND, res.getStatusCode());
        assertNull(res.getBody());
    }

    @Test
    public void updateNeeds() throws IOException {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.updateNeed(need)).thenReturn(need);

        var res = cupboardController.updateNeed(need);

        assertEquals(HttpStatus.OK, res.getStatusCode());
        assertEquals(need, res.getBody());
    }

    @Test
    public void deleteNeed() throws IOException {
        var need = new Need("Name", 1, 100, Need.GoalType.MONETARY);
        when(mockCupboardDAO.getNeed(1)).thenReturn(need);
        when(mockCupboardDAO.deleteNeed(1)).thenReturn(true);

        var res = cupboardController.deleteNeed(1);

        assertEquals(HttpStatus.OK, res.getStatusCode());
    }

    @Test
    public void deleteNeedFail() throws IOException {
        when(mockCupboardDAO.getNeed(1)).thenReturn(null);
        when(mockCupboardDAO.deleteNeed(1)).thenReturn(false);

        var res = cupboardController.deleteNeed(1);

        assertEquals(HttpStatus.NOT_FOUND, res.getStatusCode());
    }
}