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

import com.google.common.collect.Range;
import com.google.common.collect.RangeSet;
import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.LocalDate;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Required;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.searchquery.QueryGroupId;
import ru.yandex.webmaster3.core.searchquery.QueryIndicator;
import ru.yandex.webmaster3.core.searchquery.viewer.ViewerQueryGroup;
import ru.yandex.webmaster3.storage.http.searchquery.statistic.StatisticsHelper;
import ru.yandex.webmaster3.storage.searchquery.AccumulatorMap;
import ru.yandex.webmaster3.storage.searchquery.GroupStat;
import ru.yandex.webmaster3.storage.searchquery.GroupStatisticsService2;
import ru.yandex.webmaster3.storage.searchquery.QueryGroupService;
import ru.yandex.webmaster3.storage.searchquery.RangeFactory;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * @author aherman
 */
@ReadAction
@Category("searchquery")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Component("/searchquery/statistics/group/piechart")
public class GetGroupsPieChartAction extends AbstractUserVerifiedHostAction<GetGroupsPieChartRequest, GroupsStatisticResponse> {
    private static final Logger log = LoggerFactory.getLogger(GetGroupStatisticsAction.class);

    private final QueryGroupService queryGroupService;
    private final GroupStatisticsService2 groupStatisticsService2;

    @Override
    public GroupsStatisticResponse process(GetGroupsPieChartRequest request) throws WebmasterException {
        LocalDate queryDataFrom = request.getLocalDateFrom();
        LocalDate queryDataTo = request.getLocalDateTo();
        List<QueryIndicator> indicators = Collections.singletonList(request.getIndicator());

        final List<QueryGroupId> groupIds = StatisticsHelper.asGroupIds(7, request.getHostId(),
                request.getGroupId());
        final Set<Integer> regionIds = StatisticsHelper.asSet(10, request.getRegionId());

        Map<QueryGroupId, ViewerQueryGroup> groups = resolveQueryGroups(groupIds, queryGroupService);
        RangeSet<LocalDate> rangeSet = RangeFactory.singleRange(queryDataFrom, queryDataTo);
        Map<QueryGroupId, List<GroupStat>> stats = groupStatisticsService2.getStatistics(request.getHostId(),
                Pair.of(rangeSet.span().lowerEndpoint(), rangeSet.span().upperEndpoint()),
                request.getRegionInclusion(), regionIds,
                groups.keySet(), indicators, request.getDeviceType());

        List<GroupsStatisticResponse.GroupStat> result = new ArrayList<>();

        for (QueryGroupId groupId : groupIds) {
            ViewerQueryGroup viewerQueryGroup = groups.get(groupId);
            if (viewerQueryGroup == null) {
                continue;
            }
            List<GroupStat> s = stats.getOrDefault(groupId, Collections.emptyList());
            AccumulatorMap accumulatorMap = AccumulatorMap.create(indicators, rangeSet);
            s.forEach(accumulatorMap::apply);
            List<GroupsStatisticResponse.GroupStat> groupStats = new ArrayList<>();
            for (QueryIndicator indicator : indicators) {
                List<Pair<Range<LocalDate>, Double>> rangesStat = accumulatorMap.getIndicator(indicator);
                Pair<Range<LocalDate>, Double> stat = rangesStat.get(0);
                groupStats.add(new GroupsStatisticResponse.GroupStat(viewerQueryGroup,
                        new GroupsStatisticResponse.IndicatorStats(indicator,
                                Collections.singletonList(new AbstractQueryStatisticsResponse.RangeStat(
                                        stat.getKey().lowerEndpoint(), stat.getKey().upperEndpoint(), stat.getValue(), null
                                )))
                ));
            }
            result.addAll(groupStats);
        }

        return new GroupsStatisticResponse.NormalResponse(null, result);
    }
}
