package eu.dnetlib.repo.manager.service;

import eu.dnetlib.usagestats.sushilite.domain.ReportItem;
import eu.dnetlib.usagestats.sushilite.domain.ReportResponseWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.ParameterizedTypeReference;
import org.springframework.http.HttpMethod;
import org.springframework.http.ResponseEntity;
import org.springframework.http.converter.json.MappingJackson2HttpMessageConverter;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import org.springframework.web.util.UriComponentsBuilder;

import java.util.ArrayList;
import java.util.List;

@Service("sushiliteService")
public class SushiliteServiceImpl implements SushiliteService {


    @Value("${services.repomanager.usagestats.sushiliteEndpoint}")
    private String usagestatsSushiliteEndpoint;

    @Autowired
    private EmailUtils emailUtils;

    private static final org.apache.log4j.Logger LOGGER = org.apache.log4j.Logger.getLogger(SushiliteServiceImpl.class);


    @Override
    @PreAuthorize("hasRole('ROLE_USER')")
    public ReportResponseWrapper getReportResults(@PathVariable("page") String page,
                                                  @PathVariable("pageSize") String pageSize,
                                                  @RequestParam(value = "Report") String Report,
                                                  @RequestParam(value = "Release",defaultValue="4") String Release,
                                                  @RequestParam(value = "RequestorID",required=false,defaultValue="anonymous") String RequestorID,
                                                  @RequestParam(value = "BeginDate",required=false,defaultValue="") String BeginDate,
                                                  @RequestParam(value = "EndDate",required=false,defaultValue="") String EndDate,
                                                  @RequestParam(value = "RepositoryIdentifier") String RepositoryIdentifier,
                                                  @RequestParam(value = "ItemIdentifier",required=false,defaultValue="") String ItemIdentifier,
                                                  @RequestParam(value = "ItemDataType",required=false,defaultValue="") String ItemDataType,
                                                  @RequestParam(value = "Granularity") String Granularity,
                                                  @RequestParam(value = "Pretty",required=false,defaultValue="") String Pretty) {

            //build the uri params
            UriComponentsBuilder builder = UriComponentsBuilder.fromHttpUrl(this.usagestatsSushiliteEndpoint + "GetReport/")
                                                                .queryParam("Report", Report)
                                                                .queryParam("Release", Release)
                                                                .queryParam("RequestorID", RequestorID)
                                                                .queryParam("BeginDate", BeginDate)
                                                                .queryParam("EndDate", EndDate)
                                                                .queryParam("RepositoryIdentifier", RepositoryIdentifier)
                                                                .queryParam("ItemIdentifier", ItemIdentifier)
                                                                .queryParam("ItemDataType", ItemDataType)
                                                                .queryParam("Granularity", Granularity)
                                                                .queryParam("Pretty", Pretty);

            //create new template engine
            RestTemplate template = new RestTemplate();
            template.getMessageConverters().add(new MappingJackson2HttpMessageConverter());

            ResponseEntity<ReportResponseWrapper> resp;
            try {
                //communicate with endpoint
                resp = template.exchange(
                        builder.build().encode().toUri(),
                        HttpMethod.GET,
                        null,
                        new ParameterizedTypeReference<ReportResponseWrapper>() {
                        });
            } catch (RestClientException e) {
                LOGGER.debug("Exception on getReportResults" , e);
                emailUtils.reportException(e);
                throw e;
            }

            // check remote api's response
            System.out.println("sushi responded status " + resp.getStatusCode());

            // get the items corresponding to the requested page
            List<ReportItem> requestedItemList = new ArrayList<>();
            if (resp.getBody().getReportResponse().getReportWrapper().getReport().getCustomer().getReportItems() != null) {
                try {
                    int totalItems = resp.getBody().getReportResponse().getReportWrapper().getReport().getCustomer().getReportItems().size();
                    int size = Integer.parseInt(pageSize);
                    int offset = Integer.parseInt(page)*size;

                    if (offset < totalItems ) {
                        int upperIndex = offset+size;
                        if (upperIndex > totalItems) {
                            upperIndex = totalItems;
                        }
                        requestedItemList = resp.getBody().getReportResponse().getReportWrapper().getReport().getCustomer().getReportItems().subList(offset,upperIndex);
                    }

                } catch (NumberFormatException e) {
                    LOGGER.debug("Exception on getReportResults - trying to cast strings to integers", e);
                    //emailUtils.reportException(e);
                    throw e;
                }

            }

            ReportResponseWrapper newReportResponse = resp.getBody();
            newReportResponse.getReportResponse().getReportWrapper().getReport().getCustomer().setReportItems(requestedItemList);


            return newReportResponse;
    }

}
