package ru.yandex.webmaster3.viewer.http.searchquery.statistic;

import java.util.List;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.*;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.searchquery.MissingDataPeriod;
import ru.yandex.webmaster3.storage.searchquery.dao.MissingDataPeriodsYDao;

/**
 * @author aherman
 */
@ReadAction
@Category("searchquery")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class GetMissingPeriodsAction extends Action<GetMissingPeriodsAction.Request, GetMissingPeriodsAction.Response> {
    private final MissingDataPeriodsYDao missingDataPeriodsYDao;

    @Override
    public Response process(Request request) throws WebmasterException {
        try {
            List<MissingDataPeriod> periods = missingDataPeriodsYDao.getPeriods();
            periods = filterPeriods(request, periods);
            return new Response(periods);
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Unable to get periods",
                    new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
        }
    }

    static List<MissingDataPeriod> filterPeriods(Request request, List<MissingDataPeriod> periods) {
        if (request.getDateFrom() != null) {
            LocalDate dateFrom = request.getDateFrom().toLocalDate();
            periods = periods.stream()
                    .filter(p -> {
                        LocalDate dt = p.getDateTo().toLocalDate();
                        return !dateFrom.isAfter(dt);
                    })
                    .collect(Collectors.toList());
        }
        if (request.getDateTo() != null) {
            LocalDate dateTo = request.getDateTo().toLocalDate();
            periods = periods.stream()
                    .filter(p -> {
                        LocalDate df = p.getDateFrom().toLocalDate();
                        return !dateTo.isBefore(df);
                    })
                    .collect(Collectors.toList());
        }
        return periods;
    }

    public static class Request implements ActionRequest {
        private DateTime dateFrom;
        private DateTime dateTo;

        @RequestQueryProperty
        public void setDateFrom(DateTime dateFrom) {
            this.dateFrom = dateFrom;
        }

        public DateTime getDateFrom() {
            return dateFrom;
        }

        @RequestQueryProperty
        public void setDateTo(DateTime dateTo) {
            this.dateTo = dateTo;
        }

        public DateTime getDateTo() {
            return dateTo;
        }
    }

    public static class Response implements ActionResponse.NormalResponse {
        private final List<MissingDataPeriod> periods;

        public Response(List<MissingDataPeriod> periods) {
            this.periods = periods;
        }

        public List<MissingDataPeriod> getPeriods() {
            return periods;
        }
    }
}
