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

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;
import java.util.stream.Collectors;

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

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.sitemap.HostSitemap;
import ru.yandex.webmaster3.core.sitemap.UserSitemap;
import ru.yandex.webmaster3.core.sitemap.raw.HostRelatedSitemaps;
import ru.yandex.webmaster3.storage.sitemap.SitemapRecrawlRequestService;
import ru.yandex.webmaster3.storage.sitemap.UserSitemapService;
import ru.yandex.webmaster3.storage.sitemap.dao.SitemapsCHDao;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;
import ru.yandex.webmaster3.viewer.http.sitemap.data.RecrawlableHostSitemap;
import ru.yandex.webmaster3.viewer.http.sitemap.data.SitemapRecrawlInfo;

/**
 * @author aherman
 */
@ReadAction
@Description(value = "Получение списка обработанных сайтмапов для хоста")
@Category("sitemap")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ListHostSitemapsAction extends AbstractUserVerifiedHostAction<ListHostSitemapsRequest, ListHostSitemapsResponse> {
    private static final Logger log = LoggerFactory.getLogger(ListHostSitemapsAction.class);

    private final SitemapRecrawlRequestService sitemapRecrawlRequestService;
    private final SitemapsCHDao sitemapsCHDao;
    private final UserSitemapService userSitemapService;

    @Override
    public ListHostSitemapsResponse process(ListHostSitemapsRequest request) {
        List<HostSitemap> sitemaps = sitemapsCHDao.getSitemaps(request.getHostId(), null, null, 1_000);
        List<UserSitemap> userSitemaps = userSitemapService.listUserSitemaps(request.getHostId());
        Pair<Map<UUID, DateTime>, Boolean> lastRequestsInfo = sitemapRecrawlRequestService.getLastRequestsInfo(request.getHostId());
        Map<UUID, DateTime> uuidToLastRecrawlRequest = lastRequestsInfo.getLeft();

        Map<UUID, UserSitemap> uuidToUserSitemap = new HashMap<>(userSitemaps.size());
        userSitemaps.forEach(s -> uuidToUserSitemap.put(s.getSitemapId(), s));

        List<RecrawlableHostSitemap> userAddedSitemaps = new ArrayList<>();
        List<RecrawlableHostSitemap> robotSitemaps = new ArrayList<>();

        boolean newRequestForHostIsAllowed = lastRequestsInfo.getRight();
        for (HostSitemap sitemap : sitemaps) {
            UserSitemap userSitemap = uuidToUserSitemap.get(sitemap.getSitemapId());

            SitemapRecrawlInfo sitemapRecrawlInfo = SitemapRecrawlInfo.from(
                    sitemap.getInfo() == null ? null : sitemap.getInfo().getLastAccessDate(),
                    uuidToLastRecrawlRequest.get(sitemap.getSitemapId()),
                    newRequestForHostIsAllowed);

            //robot source
            if (sitemap.getInfo().getSources().contains(HostRelatedSitemaps.SitemapSource.ROBOTS_TXT)) {
                robotSitemaps.add(new RecrawlableHostSitemap(sitemap, sitemapRecrawlInfo));
            }

            //webmaster source
            if (sitemap.getInfo().getSources().contains(HostRelatedSitemaps.SitemapSource.WEBMASTER)) {
                if (userSitemap != null) {
                    HostSitemap changedSitemap = sitemap.copy();
                    changedSitemap.setDeletable(true);
                    changedSitemap.setDeleted(userSitemap.isDeleted());

                    userAddedSitemaps.add(new RecrawlableHostSitemap(changedSitemap, sitemapRecrawlInfo));
                    uuidToUserSitemap.remove(changedSitemap.getSitemapId());

                } else {
                    log.error("Unknown user sitemap " + sitemap.getSitemapUrl());
                }
            }
        }

        List<UserSitemap> otherUserSitemaps = uuidToUserSitemap.values().stream()
                .filter(s -> !s.isDeleted())
                .collect(Collectors.toList());

        otherUserSitemaps.sort((UserSitemap s1, UserSitemap s2) -> s2.getAddDate().compareTo(s1.getAddDate()));

        return new ListHostSitemapsResponse.NormalResponse(otherUserSitemaps, userAddedSitemaps, robotSitemaps);
    }
}
