package ru.yandex.webmaster3.viewer.http.url.checker2;

import java.net.MalformedURLException;
import java.net.URI;
import java.net.URL;
import java.util.Optional;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.http.UserContext;
import ru.yandex.webmaster3.core.http.WriteAction;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.user.UserVerifiedHost;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.storage.host.moderation.camelcase.service.DisplayNameService2;
import ru.yandex.webmaster3.storage.host.service.HostService;
import ru.yandex.webmaster3.storage.url.checker2.UrlCheckRequestService;
import ru.yandex.webmaster3.storage.url.checker2.UrlCheckService;
import ru.yandex.webmaster3.storage.url.checker2.data.UrlCheckInfo;
import ru.yandex.webmaster3.storage.url.common.data.UrlCheckRequestData;
import ru.yandex.webmaster3.storage.user.service.UserHostsService;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;
import ru.yandex.webmaster3.viewer.http.common.response.CommonHostInfo;
import ru.yandex.webmaster3.viewer.http.url.checker2.data.UrlCheckReport;
import ru.yandex.webmaster3.viewer.http.url.checker2.data.UrlCheckRequest;
import ru.yandex.webmaster3.viewer.http.url.checker2.data.UrlCheckRequestStatus;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.util.uri.WebmasterUriUtils;

/**
 * Created by leonidrom on 01/03/2017.
 */
@Description("Запросить проверку урла")
@WriteAction
@Category("checkurl")
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class AddUrlCheckAction extends AbstractUserVerifiedHostAction<AddUrlCheckRequest, AddUrlCheckResponse> {
    private final UrlCheckRequestService urlCheckRequestService;
    private final UrlCheckService urlCheckService;
    private final UserHostsService userHostsService;
    private final HostService hostService;
    private final DisplayNameService2 displayNameService2;

    @Override
    public AddUrlCheckResponse process(AddUrlCheckRequest request) {
        int requestsLeft = urlCheckRequestService.getRequestsLeftForHostToday(request.getHostId());
        if (requestsLeft == 0) {
            return new AddUrlCheckResponse.HostLimitReachedResponse();
        }
        UserContext.setUserId(request.getUserId());
        URI uri;
        try {
            uri = processUrl(request.getHostId(), request.getUrl());
        } catch (Exception e) {
            return new AddUrlCheckResponse.InvalidUrlResponse();
        }

        WebmasterHostId hostOfUrl = IdUtils.urlToHostId(uri);
        if (!compareHosts(request.getHostId(), hostOfUrl)) {
            UserVerifiedHost userHost = userHostsService.getVerifiedHost(request.getWebmasterUser(), hostOfUrl);
            if (userHost != null) {
                // another host is verified by user
                CommonHostInfo anotherHostInfo = getCommonHostInfo(hostOfUrl);
                return new AddUrlCheckResponse.AddToAnotherHostResponse(anotherHostInfo);
            } else {
                // another host is not verified by user
                return new AddUrlCheckResponse.UrlIsNotFromHostResponse();
            }
        }

        URL url;
        try {
            url = uri.toURL();
        } catch (MalformedURLException e) {
            return new AddUrlCheckResponse.InvalidUrlResponse();
        }

        UrlCheckRequest r = createRequest(request.getHostId(), url);
        return new AddUrlCheckResponse.NormalResponse(r);
    }

    private URI processUrl(WebmasterHostId hostId, String urlS)
            throws UserException, MalformedURLException {

        URI uri;
        if (urlS.startsWith("/")) {
            uri = WebmasterUriUtils.toOldUri(IdUtils.hostIdToUrl(hostId) + urlS);
        } else {
            uri = WebmasterUriUtils.toOldUri(urlS);
        }

        if (StringUtils.isEmpty(uri.getPath())) {
            uri = uri.resolve("/");
        }

        return uri;
    }

    private boolean compareHosts(WebmasterHostId expected, WebmasterHostId actual) {
        if (expected.equals(actual)) {
            return true;
        }

        String expectedHostPart = expected.getPunycodeHostname();
        String actualHostPart = actual.getPunycodeHostname();

        return expected.getPort() == actual.getPort() && WwwUtil.equalsIgnoreWww(actualHostPart, expectedHostPart);
    }

    private CommonHostInfo getCommonHostInfo(WebmasterHostId hostId) {
        String hostUrlWithDisplayName = displayNameService2.getHostUrlWithDisplayName(hostId);

        return new CommonHostInfo(hostId, hostUrlWithDisplayName, false, null);
    }

    private UrlCheckRequest createRequest(WebmasterHostId hostId, URL url) {
        UrlCheckRequestData requestData = urlCheckRequestService.createRequest(hostId, url);

        UrlCheckReport report = null;
        Optional<UrlCheckInfo> urlInfoOpt = urlCheckService.tryGetUrlCheckInfoFromCH(requestData);
        if (urlInfoOpt.isPresent()) {
            report = UrlCheckReport.from(url, urlInfoOpt.get());
        }

        return new UrlCheckRequest(requestData.getRequestId(), url,
                requestData.getCreatedTime(),
                report == null? UrlCheckRequestStatus.IN_PROGRESS : UrlCheckRequestStatus.COMPLETED,
                report);
    }
}

