package ru.yandex.webmaster3.storage.sitemap.service;

import java.net.URL;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import ru.yandex.webmaster3.core.zora.ZoraRedirectService;
import ru.yandex.webmaster3.core.zora.data.response.ZoraUrlFetchResponse;
import ru.yandex.webmaster3.core.zora.go_data.request.GoZoraRequest;
import ru.yandex.wmtools.common.error.InternalException;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.util.http.YandexHttpStatus;

/**
 * @author aherman
 * @author azakharov
 */
@Slf4j
@Service
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class SitemapValidatorService {
    public static final int MAX_SITEMAP_LENGTH = 50 * 1024 * 1024;

    private final ZoraRedirectService zoraRedirectService;

    public SitemapDownloadResult downloadSitemapAndCheck(URL sitemapUrl) {

        ZoraUrlFetchResponse sitaUrlFetchResponse = null;
        try {
            sitaUrlFetchResponse = zoraRedirectService.followRedirectsExtended(GoZoraRequest.of(sitemapUrl.toString()));
        } catch (UserException | InternalException e) {
            log.error("UserException in sitaRedirectService", e);
            return new SitemapDownloadResult(SitemapDownloadError.UNABLE_TO_DOWNLOAD_SITEMAP, null);
        }

        if (sitaUrlFetchResponse.getExtendedHttpStatus() == YandexHttpStatus.HTTP_1002_BODY_TOO_LARGE) {
            return new SitemapDownloadResult(SitemapDownloadError.SITEMAP_TOO_LONG, null);
        }
        if (sitaUrlFetchResponse.hasDocument()) {
            HttpResponse parsedHttpHeaders = sitaUrlFetchResponse.getHttpResponse();
            Header firstHeader = parsedHttpHeaders.getFirstHeader("Content-Length");
            if (firstHeader != null) {
                long contentLength = 0;
                try {
                    contentLength = Long.parseLong(firstHeader.getValue());
                } catch (NumberFormatException e) {
                }
                if (contentLength > MAX_SITEMAP_LENGTH) {
                    return new SitemapDownloadResult(SitemapDownloadError.SITEMAP_TOO_LONG, null);
                }
            }
        }

        if (YandexHttpStatus.isExtErrors(sitaUrlFetchResponse.getExtendedHttpStatus())) {
            return new SitemapDownloadResult(SitemapDownloadError.UNABLE_TO_DOWNLOAD_SITEMAP, null);
        }

        if (YandexHttpStatus.is200Or2XXX(sitaUrlFetchResponse.getExtendedHttpStatus())) {
            if (!sitaUrlFetchResponse.hasDocument()) {
                return new SitemapDownloadResult(SitemapDownloadError.UNABLE_TO_DOWNLOAD_SITEMAP, null);
            } else {
                return new SitemapDownloadResult(SitemapDownloadError.NO_ERROR, sitaUrlFetchResponse);
            }
        }

        return new SitemapDownloadResult(SitemapDownloadError.ILLEGAL_HTTP_CODE, sitaUrlFetchResponse);
    }

    public enum SitemapDownloadError {
        NO_ERROR,
        UNABLE_TO_DOWNLOAD_SITEMAP,
        SITEMAP_IS_FORBIDDEN_IN_ROBOTS_TXT,
        ILLEGAL_HTTP_CODE,
        SITEMAP_TOO_LONG,
    }

    public static class SitemapDownloadResult {
        private final SitemapDownloadError error;
        private final ZoraUrlFetchResponse urlFetchResponse;

        public SitemapDownloadResult(SitemapDownloadError error,
                                     ZoraUrlFetchResponse urlFetchResponse) {
            this.error = error;
            this.urlFetchResponse = urlFetchResponse;
        }

        public SitemapDownloadError getError() {
            return error;
        }

        public ZoraUrlFetchResponse getUrlFetchResponse() {
            return urlFetchResponse;
        }
    }
}

