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

import java.net.MalformedURLException;
import java.net.URL;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Required;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.events2.client.HostEventLogClient;
import ru.yandex.webmaster3.core.events2.events.tools.MobileAuditForUrlRequestedEvent;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.http.WriteAction;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.util.WwwUtil;
import ru.yandex.webmaster3.core.host.service.HostOwnerService;
import ru.yandex.webmaster3.storage.mobile.MobileAuditRequestsService;
import ru.yandex.webmaster3.core.mobile.data.ScreenshotResolution;
import ru.yandex.webmaster3.viewer.http.AbstractUserVerifiedHostAction;
import ru.yandex.webmaster3.viewer.util.ViewerEventUtil;
import ru.yandex.wmtools.common.error.UserException;
import ru.yandex.wmtools.common.util.uri.WebmasterUriUtils;

/**
 * @author avhaliullin
 */

@Description("Запросить проверку урла на мобилопригодность")
@WriteAction
@Category("mobile")
@Slf4j
public class StartMobileAuditAction extends AbstractUserVerifiedHostAction<StartMobileAuditRequest, StartMobileAuditResponse> {
    private MobileAuditRequestsService mobileAuditRequestsService;
    private HostOwnerService hostOwnerService;
    private HostEventLogClient hostEventLogClient;

    private boolean compareHosts(WebmasterHostId expected, WebmasterHostId actual) {
        if (expected.equals(actual)) {
            return true;
        }
        String expectedHostPart = expected.getPunycodeHostname();
        String actualHostPart = actual.getPunycodeHostname();
        return WwwUtil.equalsIgnoreWww(actualHostPart, expectedHostPart);
    }

    @Override
    public StartMobileAuditResponse process(StartMobileAuditRequest request) {
        log.info("Got request: {}", request);

        URL url;
        String urlS = request.getUrl();

        try {
            if (urlS.startsWith("/")) {
                url = WebmasterUriUtils.toOldUri(IdUtils.hostIdToUrl(request.getHostId()) + urlS).toURL();
            } else {
                url = WebmasterUriUtils.toOldUri(urlS).toURL();
                WebmasterHostId hostOfUrl = IdUtils.urlToHostId(url);
                if (!compareHosts(request.getHostId(), hostOfUrl) &&
                    !hostOwnerService.isSameOwner(request.getHostId(), hostOfUrl)) {

                    return new StartMobileAuditResponse.UrlFromAnotherHostResponse();
                }
            }
        } catch (UserException | MalformedURLException e) {
            log.error("Invalid url {}", urlS, e);
            return new StartMobileAuditResponse.InvalidUrlResponse();
        }

        var resolution = new ScreenshotResolution(request.getWidth(), request.getHeight());
        var result = mobileAuditRequestsService.createRequest(request.getUserId(), request.getHostId(), url, resolution);
        switch (result.getType()) {
            case OK: {
                hostEventLogClient.log(ViewerEventUtil.create(request, new MobileAuditForUrlRequestedEvent(url, result.getRequestId())));
                log.info("Created request {}", result);
                return new StartMobileAuditResponse.NormalResponse(url, result.getRequestId());
            }

            case HOST_LIMIT_REACHED: {
                log.info("Host limit reached");
                return new StartMobileAuditResponse.HostLimitReachedResponse();
            }

            default: {
                log.error("Unknown request creation result {}", result);
                throw new RuntimeException("Unknown request creation result " + result);
            }
        }
    }

    @Required
    public void setMobileAuditRequestsService(MobileAuditRequestsService mobileAuditRequestsService) {
        this.mobileAuditRequestsService = mobileAuditRequestsService;
    }

    @Required
    public void setHostOwnerService(HostOwnerService hostOwnerService) {
        this.hostOwnerService = hostOwnerService;
    }

    @Required
    public void setHostEventLogClient(HostEventLogClient hostEventLogClient) {
        this.hostEventLogClient = hostEventLogClient;
    }
}
