package cz.senslog.connector.fetch.fieldclimate;

import cz.senslog.connector.model.config.DefaultConfig;
import cz.senslog.connector.fetch.gfs.ExecutableFetcher;
import cz.senslog.connector.tools.http.HttpClient;
import cz.senslog.connector.tools.http.HttpRequest;
import cz.senslog.connector.tools.http.HttpResponse;
import cz.senslog.connector.model.fieldclimate.FieldClimateModel;
import cz.senslog.connector.model.fieldclimate.StationData;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.stubbing.Answer;

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;

import static cz.senslog.connector.tools.http.HttpCode.OK;
import static cz.senslog.connector.tools.http.HttpCode.SERVER_ERROR;
import static cz.senslog.connector.tools.json.BasicJson.objectToJson;
import static cz.senslog.connector.model.converter.FieldClimateUnitConverter.convertIdToFieldClimateId;
import static java.time.ZoneOffset.UTC;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.jupiter.api.Assertions.assertNull;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;

class FieldClimateProxySessionTest {

    @BeforeEach
    void setUp() {

    }

    @Test
    void preProcessing_serverError_nullModel() throws Exception {

        DefaultConfig propertyConfig = new DefaultConfig("proxySession", null);
        propertyConfig.setProperty("lastObservationHost", new HashMap<String, String>(){{
            put("domain", "http://127.0.0.1");
            put("path", "SensorService");
        }});
        propertyConfig.setProperty("user", "<user>");
        propertyConfig.setProperty("group", "<group>");

        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock ->
                HttpResponse.newBuilder()
                    .status(SERVER_ERROR).body("")
                    .build()
        );


        FieldClimateSessionProxyConfig sessionProxyConfig = new FieldClimateSessionProxyConfig(propertyConfig);
        FieldClimateFetcher fetcher = mock(FieldClimateFetcher.class);
        FieldClimateProxySession proxy = new FieldClimateProxySession(fetcher, sessionProxyConfig, httpClient);
        ExecutableFetcher<FieldClimateModel> executableFetcher = ExecutableFetcher.createWithProxySession(proxy);

        FieldClimateModel model = executableFetcher.execute();

        assertNull(model);
    }

    @Test
    void preProcessing_true() throws Exception {

        DefaultConfig propertyConfig = new DefaultConfig("proxySession", null);
        propertyConfig.setProperty("lastObservationHost", new HashMap<String, String>(){{
            put("domain", "http://127.0.0.1");
            put("path", "SensorService");
        }});
        propertyConfig.setProperty("user", "<user>");
        propertyConfig.setProperty("group", "<group>");

        OffsetDateTime timestamp = OffsetDateTime.of(LocalDateTime.of(2020, 1, 1, 1, 1, 0, 0), UTC);
        Long unitId = 1234L;
        String stationId = convertIdToFieldClimateId(unitId);

        HttpClient httpClient = mock(HttpClient.class);
        when(httpClient.send(any(HttpRequest.class))).thenAnswer((Answer<HttpResponse>) invocationOnMock -> {
            HttpRequest request = invocationOnMock.getArgument(0, HttpRequest.class);
            String path = request.getUrl().getPath();
            if (path.contains("SensorService")) {
                Map<String, Object> mapJson = new HashMap<>();
                mapJson.put("timeStamp", "2020-01-01 01:01:00+00");
                mapJson.put("unitId", unitId);
                String stationsJson = objectToJson(singletonList(mapJson));
                return HttpResponse.newBuilder()
                        .status(OK).body(stationsJson).build();
            }
            return HttpResponse.newBuilder()
                    .status(SERVER_ERROR).body("")
                    .build();
        });

        FieldClimateFetcher fetcher = mock(FieldClimateFetcher.class);
        when(fetcher.fetch(any(Optional.class))).then(a -> {
            FieldClimateSession session = (FieldClimateSession) a.getArgument(0, Optional.class).get();
            OffsetDateTime dateTime = session.getLastUnitTime(stationId, OffsetDateTime.MIN);
            StationData stationData = new StationData();
            stationData.setId(stationId);
            return new FieldClimateModel(singletonList(stationData), dateTime, dateTime);
        });

        FieldClimateSessionProxyConfig sessionProxyConfig = new FieldClimateSessionProxyConfig(propertyConfig);
        FieldClimateProxySession proxySession = new FieldClimateProxySession(fetcher, sessionProxyConfig, httpClient);
        ExecutableFetcher<FieldClimateModel> executableFetcher = ExecutableFetcher.createWithProxySession(proxySession);

        FieldClimateModel model = executableFetcher.execute();

        assertEquals(1, model.getStations().size());
        assertEquals(stationId, model.getStations().get(0).getId());
        assertEquals(timestamp, model.getFrom());
    }
}