package ru.yandex.webmaster3.viewer.http.links2;

import org.apache.commons.lang3.mutable.MutableLong;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.link.HostLinkStatistics;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.storage.host.service.HostService;
import ru.yandex.webmaster3.storage.links.LinksService;
import ru.yandex.webmaster3.storage.user.service.UserHostsService;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;

import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by ifilippov5 on 10.08.18.
 */
@ReadAction
@Description("Ручка для графиков истории по количеству внутренних ссылок и хостов")
@Category("links")
public class GetExternalLinkSqiAndTldAction extends AbstractUserVerifiedHostAction<GetExternalLinkSqiAndTldRequest, GetExternalLinkSqiAndTldResponse> {
    private static final Logger log = LoggerFactory.getLogger(GetExternalLinkSqiAndTldAction.class);
    private HostService hostService;
    private LinksService linksService;
    public static final String OTHER_INDICATOR = "OTHER";

    @Override
    public GetExternalLinkSqiAndTldResponse process(GetExternalLinkSqiAndTldRequest request) {

        List<HostLinkStatistics> linkStatisticsList = linksService.getLatestLinkStatisticsGeneration(request.getHostId(), 1);
        if (linkStatisticsList.isEmpty()) {
            return new GetExternalLinkSqiAndTldResponse.OrdinaryResponse(Collections.emptyList(), Collections.emptyList());
        }
        HostLinkStatistics linkStatistics = linkStatisticsList.get(0);

        List<GetExternalLinkSqiAndTldResponse.SqiData> SqiData = Collections.emptyList();
        List<GetExternalLinkSqiAndTldResponse.TldData> tldData = Collections.emptyList();


        if (!linkStatistics.getExternalDetailedSqiInfo().isEmpty()) {
            Map<GetExternalLinkSqiAndTldResponse.SqiRange, MutableLong> SqiGroups = new HashMap<>();
            for (GetExternalLinkSqiAndTldResponse.SqiRange SqiRange : GetExternalLinkSqiAndTldResponse.SqiRange.values()) {
                if (SqiRange != GetExternalLinkSqiAndTldResponse.SqiRange.UNKNOWN) {
                    SqiGroups.put(SqiRange, new MutableLong());
                }
            }
            linkStatistics.getExternalDetailedSqiInfo().entrySet().forEach(e -> {
                GetExternalLinkSqiAndTldResponse.SqiRange SqiRange =
                        GetExternalLinkSqiAndTldResponse.SqiRange.findBy(e.getKey());
                if (SqiRange != GetExternalLinkSqiAndTldResponse.SqiRange.UNKNOWN) {
                    SqiGroups.computeIfAbsent(SqiRange, k -> new MutableLong()).add(e.getValue());
                }
            });
            SqiData = SqiGroups.entrySet().stream()
                    .map(e -> new GetExternalLinkSqiAndTldResponse.SqiData(e.getKey(), e.getValue().longValue()))
                    .collect(Collectors.toList());
        } else if (!linkStatistics.getExternalLinksHostsSqiGroups().isEmpty()) {
            Map<GetExternalLinkSqiAndTldResponse.SqiRange, MutableLong> SqiGroups = new HashMap<>();
            for (GetExternalLinkSqiAndTldResponse.SqiRange SqiRange : GetExternalLinkSqiAndTldResponse.SqiRange.values()) {
                if (SqiRange != GetExternalLinkSqiAndTldResponse.SqiRange.UNKNOWN) {
                    SqiGroups.put(SqiRange, new MutableLong());
                }
            }
            linkStatistics.getExternalLinksHostsSqiGroups().entrySet().forEach(e -> {
                GetExternalLinkSqiAndTldResponse.SqiRange SqiRange =
                        GetExternalLinkSqiAndTldResponse.SqiRange.findBy(e.getKey().getFrom());
                if (SqiRange != GetExternalLinkSqiAndTldResponse.SqiRange.UNKNOWN) {
                    SqiGroups.computeIfAbsent(SqiRange, k -> new MutableLong()).add(e.getValue());
                }
            });
            SqiData = SqiGroups.entrySet().stream()
                    .map(e -> new GetExternalLinkSqiAndTldResponse.SqiData(e.getKey(), e.getValue().longValue()))
                    .collect(Collectors.toList());
        }

        SqiData.sort((a,b) -> Integer.compare(a.getName().getFrom(), b.getName().getFrom()));

        //
        if (!linkStatistics.getExternalLinksTldCount().isEmpty()) {
            tldData = linkStatistics.getExternalLinksTldCount().entrySet().stream()
                    .map(e -> new GetExternalLinkSqiAndTldResponse.TldData(e.getKey(), e.getValue()))
                    .collect(Collectors.toList());
        }

        tldData.sort((a,b) -> -Long.compare(a.getCurrent(), b.getCurrent()));

        if (request.getMaxTLDomains() != null) {
            List<GetExternalLinkSqiAndTldResponse.TldData> firstFiveTld = tldData.subList(0, Math.min(tldData.size(), request.getMaxTLDomains()));
            List<GetExternalLinkSqiAndTldResponse.TldData> otherTlds =
                    tldData.size() > request.getMaxTLDomains() ?
                            tldData.subList(request.getMaxTLDomains(), tldData.size()) : null;

            if (otherTlds != null) {
                LongSummaryStatistics value = otherTlds.stream().collect(Collectors.summarizingLong(t -> t.getCurrent()));
                firstFiveTld.add(new GetExternalLinkSqiAndTldResponse.TldData(OTHER_INDICATOR, value.getSum()));
            }

            tldData = firstFiveTld;
        }

        return new GetExternalLinkSqiAndTldResponse.OrdinaryResponse(SqiData, tldData);
    }

    @Required
    public void setHostService(HostService hostService) {
        this.hostService = hostService;
    }

    @Required
    public void setLinksService(LinksService linksService) {
        this.linksService = linksService;
    }
}
