package cz.senslog.connector.fetch.alapans;

import com.google.gson.reflect.TypeToken;
import cz.senslog.connector.fetch.api.ConnectorFetcher;
import cz.senslog.connector.fetch.api.FetchProxySession;
import cz.senslog.connector.model.alapans.AlapansModel;
import cz.senslog.connector.tools.http.*;
import cz.senslog.connector.tools.senslog.auth.SensLogAuthService;
import cz.senslog.connector.tools.util.Tuple;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

import java.lang.reflect.Type;
import java.time.LocalDate;
import java.time.OffsetDateTime;
import java.util.Collection;
import java.util.List;
import java.util.Optional;

import static cz.senslog.connector.tools.json.BasicJson.jsonToObject;
import static java.time.OffsetDateTime.parse;
import static java.time.format.DateTimeFormatter.ofPattern;

public class AlapansProxySession extends FetchProxySession<AlapansSession, AlapansModel> {

    private static final Logger logger = LogManager.getLogger(AlapansProxySession.class);

    protected static class ObservationInfo { OffsetDateTime timeStamp; }

    private static final int ALAPANS_API_INTERVAL_DAYS = 1;

    private final HttpClient httpClient;

    private final AlapansSessionProxyConfig config;

    private final SensLogAuthService sensLogAuthService;

    public AlapansProxySession(
            ConnectorFetcher<AlapansSession, AlapansModel> fetcher,
            AlapansSessionProxyConfig config,
            HttpClient httpClient
    ) {
        super(fetcher);
        this.httpClient = httpClient;
        this.config = config;
        this.sensLogAuthService = SensLogAuthService.getInstance(config.getBaseUrl());
    }

    @Override
    protected AlapansSession preProcessing(Optional<AlapansSession> previousSession) {
        AlapansSession session = previousSession.orElseGet(() -> new AlapansSession(true));
        if (session.isNotInitialized()) {

            HttpCookie authCookie = sensLogAuthService.getAuthCookie(
                    config.getSenslogAuth().getUsername(),
                    config.getSenslogAuth().getPassword()
            );

            if (authCookie.isNotSecure()) {
                logger.warn("Auth cookie is not valid to be used.");
                return session;
            }

            HttpRequest request = HttpRequest.newBuilder().GET()
                    .url(URLBuilder.newBuilder(config.getBaseUrl(), "SensorService")
                            .addParam("Operation", "GetLastObservations")
                            .addParam("group", config.getGroup())
                            .addParam("user", config.getUser())
                            .build())
                    .addCookie(authCookie)
                    .build();
            HttpResponse response = httpClient.send(request);
            if (response.isOk()) {
                Type lastObsType = new TypeToken<Collection<ObservationInfo>>() {}.getType();
                List<ObservationInfo> lastObservations = jsonToObject(response.getBody(), lastObsType,
                        Tuple.of(OffsetDateTime.class, el -> parse(el, ofPattern("yyyy-MM-dd HH:mm:ssX")))
                );

                if (!lastObservations.isEmpty()) {
                    LocalDate lastDate = LocalDate.MIN;
                    for (ObservationInfo info : lastObservations) {
                        LocalDate tempDate = info.timeStamp.toLocalDate();
                        if (tempDate.isAfter(lastDate)) {
                            lastDate = tempDate;
                        }
                    }
                    session.setFromDate(lastDate.plusDays(ALAPANS_API_INTERVAL_DAYS));
                }
            } else {
                logger.error("Can not get data from the server {}. Error {} {}",
                        config.getBaseUrl(), response.getStatus(), response.getBody());
            }
        }
        return session;
    }

    @Override
    protected void postProcessing(Optional<AlapansModel> model, Optional<AlapansSession> session) {}
}
