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

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.concurrency.AsyncCtx;
import ru.yandex.webmaster3.core.host.service.HostOwnerService;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.link.DatePoint;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.storage.achievements.dao.HostAchievementsRivalsYDao;
import ru.yandex.webmaster3.storage.iks.IksService;
import ru.yandex.webmaster3.viewer.http.concurrency.AsyncAction;

@ReadAction
@Category("achievements")
@Description("Получение истории ИКС хоста и его конкурентов")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class GetHostAndRivalsSqiHistoryAction extends AsyncAction<GetHostAndRivalsSqiHistoryRequest, GetHostAndRivalsSqiHistoryResponse> {

    private static final String OWNER_NAME = "owner";

    private final IksService iksService;
    private final HostAchievementsRivalsYDao hostAchievementsRivalsYDao;
    private final HostOwnerService hostOwnerService;

    protected GetHostAndRivalsSqiHistoryResponse getResponse(Map<String, String> hostToOwnerMap, Map<String, List<DatePoint>> availHistories, String requestHost) {
        Map<String, List<DatePoint>> histories = hostToOwnerMap.entrySet().stream()
                .map(pair -> Pair.of(
                        pair.getKey(),
                        availHistories.getOrDefault(pair.getValue(), Collections.emptyList())
                )).collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));

        return new GetHostAndRivalsSqiHistoryResponse(histories
                .entrySet()
                .stream()
                .map(pair -> new GetHostAndRivalsSqiHistoryResponse.RivalSqiHistory(
                        pair.getKey().equals(requestHost) ? OWNER_NAME : pair.getKey(), pair.getValue())
                ).collect(Collectors.toList())
        );
    }

    @Override
    protected GetHostAndRivalsSqiHistoryResponse processAsync(AsyncCtx ctx, GetHostAndRivalsSqiHistoryRequest request) {
        String requestHost = request.getHostId().getPunycodeHostname();
        Set<String> allHostsSet = new HashSet<>(hostAchievementsRivalsYDao.getRivalsFiltered(request.getHostId()));
        allHostsSet.add(requestHost);

        Map<String, String> hostToOwnerMap = allHostsSet.stream()
                .map(host -> Pair.of(host, hostOwnerService.getMascotHostOwner(host)))
                .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
        List<String> allOwnersList = new ArrayList<>(new HashSet<>(hostToOwnerMap.values()));

        Optional<DateTime> optLastUpdateCurrentIks = iksService.getCurrentIksLastImportDate();
        if (optLastUpdateCurrentIks.isEmpty()) {
            return getResponse(hostToOwnerMap, Collections.emptyMap(), requestHost);
        }
        Map<String, List<DatePoint>> ownersHistories = iksService.getIksHistory(allOwnersList,
                request.getDateFrom() == null ? LocalDate.now().minusMonths(1) : request.getDateFrom().toLocalDate().minusMonths(1), // минус месяц, чтобы не было дырок в начале графика
                request.getDateTo() == null ? LocalDate.now() : request.getDateTo().toLocalDate());

        return getResponse(hostToOwnerMap, ownersHistories, requestHost);
    }

}
