package ch.unisg.executorpool;

import java.util.Optional;

import ch.unisg.executorpool.application.port.out.LoadExecutorPort;
import org.bson.json.JsonObject;
import org.junit.jupiter.api.Test;
import org.mockito.Mockito;
import static org.mockito.BDDMockito.eq;
import static org.mockito.BDDMockito.then;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.autoconfigure.web.servlet.WebMvcTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.web.servlet.MockMvc;
import static org.springframework.test.web.servlet.request.MockMvcRequestBuilders.post;
import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status;

import ch.unisg.executorpool.adapter.common.formats.ExecutorJsonRepresentation;
import ch.unisg.executorpool.adapter.in.web.AddNewExecutorToExecutorPoolWebController;
import ch.unisg.executorpool.adapter.out.persistence.mongodb.ExecutorRepository;
import ch.unisg.executorpool.application.port.in.AddNewExecutorToExecutorPoolCommand;
import ch.unisg.executorpool.application.port.in.AddNewExecutorToExecutorPoolUseCase;
import ch.unisg.executorpool.domain.ExecutorClass;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorTaskType;
import ch.unisg.executorpool.domain.ExecutorClass.ExecutorUri;
import org.json.JSONObject;


@WebMvcTest(controllers = AddNewExecutorToExecutorPoolWebController.class)
public class AddNewExecutorToExecutorPoolWebControllerTest {

    @Autowired
    private MockMvc mockMvc;

    @MockBean
    private AddNewExecutorToExecutorPoolUseCase addNewExecutorToExecutorPoolUseCase;

    @MockBean
    ExecutorRepository executorRepository;

    @MockBean
    LoadExecutorPort loadExecutorPort;

    @Test
    void testAddNewExecutorToExecutorPool() throws Exception {

        String executorTaskType = "test-request-type";
        String executorUri = "example.org";

        String jsonPayLoad = new JSONObject().put("executorTaskType", executorTaskType).put("executorUri", executorUri).toString();

        ExecutorClass executorStub = ExecutorClass.createExecutorClass(new ExecutorUri(java.net.URI.create(executorUri)),
        new ExecutorClass.ExecutorTaskType(executorTaskType));

        AddNewExecutorToExecutorPoolCommand addNewExecutorToExecutorPoolCommand = new AddNewExecutorToExecutorPoolCommand(
            new ExecutorUri(java.net.URI.create(executorUri)), new ExecutorTaskType(executorTaskType));

        Mockito.when(addNewExecutorToExecutorPoolUseCase
        .addNewExecutorToExecutorPool(addNewExecutorToExecutorPoolCommand))
        .thenReturn(executorStub);

        mockMvc.perform(post("/executor-pool/AddExecutor")
        .contentType(ExecutorJsonRepresentation.EXECUTOR_MEDIA_TYPE)
        .content(jsonPayLoad))
        .andExpect(status().isCreated());

        then(addNewExecutorToExecutorPoolUseCase).should()
        .addNewExecutorToExecutorPool(eq(new AddNewExecutorToExecutorPoolCommand(
            new ExecutorUri(java.net.URI.create(executorUri)), new ExecutorTaskType(executorTaskType))));


    }


}
