package ru.yandex.webmaster3.viewer.http.checklist.extras;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.AllArgsConstructor;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.NameValuePair;
import org.apache.http.client.utils.URIBuilder;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemTypeEnum;
import ru.yandex.webmaster3.core.host.service.HostOwnerService;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.util.PageUtils;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.storage.checklist.dao.ChecklistPageSamplesService;
import ru.yandex.webmaster3.storage.checklist.dao.ChecklistSamplesType;
import ru.yandex.webmaster3.storage.checklist.data.AbstractProblemInfo;
import ru.yandex.webmaster3.storage.checklist.data.TurboHostBanSample;
import ru.yandex.webmaster3.storage.checklist.service.SiteProblemsService;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;

/**
 * @author: ishalaru
 * DATE: 15.07.2019
 */
@Slf4j
@ReadAction
@Description("Получить примеры проблемных страниц с банами хостов турбо ")
@Category("checklist")
@Component("/checklist/extras/turboHostBanExtendedSamples")
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class TurboHostBanExtendedSamplesAction extends AbstractUserVerifiedHostAction<PageSamplesRequest, TurboHostBanExtendedSamplesAction.TurboBanSamplesResponse> {
    private static final ObjectMapper OM = new ObjectMapper().configure(JsonGenerator.Feature.ESCAPE_NON_ASCII, true);
    private final SiteProblemsService siteProblemsService;
    private final ChecklistPageSamplesService checklistPageSamplesService;
    private final HostOwnerService hostOwnerService;

    @Override
    public TurboBanSamplesResponse process(PageSamplesRequest request) {
        SiteProblemTypeEnum problemType = SiteProblemTypeEnum.TURBO_HOST_BAN;
        AbstractProblemInfo problemInfo = siteProblemsService.getRealTimeProblemInfo(request.getHostId(), problemType);

        if (problemInfo == null || problemInfo.getState() == problemType.getDefaultState()) {
            problemType = SiteProblemTypeEnum.TURBO_HOST_BAN_INFO;
            problemInfo = siteProblemsService.getRealTimeProblemInfo(request.getHostId(), problemType);
            if (problemInfo == null || problemInfo.getState() == problemType.getDefaultState()) {
                return new TurboBanSamplesResponse(Collections.emptyList(), 0);
            }
        }

        PageUtils.Pager pager = PageUtils.getPage(request.getP(), request.getPSize());
        final ChecklistSamplesType checklistSamplesType = ChecklistSamplesType.byProblemType(problemType);
        List<String> workValues = checklistPageSamplesService.getSamples(request.getHostId(), checklistSamplesType);
        List<TurboHostBanSample> samples = new ArrayList<>(workValues.size());
        for (String item : workValues) {
            TurboHostBanSample value = null;
            try {
                value = OM.readValue(item, TurboHostBanSample.class);
            } catch (IOException ignored) {
            }
            samples.add(value);
        }
        final String domain = WwwUtil.cutWWWAndM(request.getHostId());
        // отсортируем по близости к целевому домену (WMCSUPPORT-2223)
        // todo возморжно стоит перенести сортивровку в ImportTurboHostBansTask#getTurboHostBanSamples
        Comparator<TurboHostBanSample> comparator =
                Comparator.<TurboHostBanSample>comparingInt(o -> getDomainSortDistance(domain, o))
                        .thenComparingInt(x -> -x.getWeight())
                        .thenComparing(TurboHostBanSample::getProdUrl, Comparator.naturalOrder());

        List<TurboBanSample> turboBanSamples = samples.stream()
                .sorted(comparator)
                .skip(pager.toRangeStart())
                .limit(pager.getPageSize())
                .map(TurboBanSample::fromHostBanSample)
                .collect(Collectors.toList());
        return new TurboBanSamplesResponse(turboBanSamples, samples.size());
    }

    private int getDomainSortDistance(String domain, TurboHostBanSample sample) {
        // попытаемся откопать домен примера
        try {
            URIBuilder prodUriBuilder = new URIBuilder(sample.getProdUrl());
            String originalUrl = prodUriBuilder.getQueryParams().stream()
                    .filter(p -> p.getName().equalsIgnoreCase("text"))
                    .map(NameValuePair::getValue).findAny().orElse(null);
            if (originalUrl == null) {
                return 3;
            }
            URIBuilder origUriBuilder = new URIBuilder(originalUrl);
            String origUriDomain = WwwUtil.cutWWWAndM(origUriBuilder.getHost());
            if (domain.equalsIgnoreCase(origUriDomain)) {
                return 0;
            }
            if (hostOwnerService.getHostOwner(domain).equalsIgnoreCase(hostOwnerService.getHostOwner(origUriDomain))) {
                return 1;
            }
            return 2;
        } catch (Exception ignored) {
        }
        return 2;
    }

    @AllArgsConstructor
    @Getter
    public static class TurboBanSamplesResponse implements ActionResponse.NormalResponse {
        private final List<TurboBanSample> samples;
        private final int totalSamples;
    }

    @AllArgsConstructor
    @Getter
    // TODO может эта обертка и не нужна
    public static class TurboBanSample {
        private final String frozenTurboUrl;
        private final String prodTurboUrl;
        private final String originalUrl;
        private final List<String> reasons;

        public static TurboBanSample fromHostBanSample(TurboHostBanSample sample) {
            return new TurboBanSample(sample.getFrozenUrl(), sample.getProdUrl(), sample.getOriginalUrl(), sample.getReasons());
        }
    }
}
