package ru.yandex.webmaster3.core.delurl;

import com.fasterxml.jackson.annotation.JsonIgnore;
import lombok.*;
import org.jetbrains.annotations.NotNull;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.util.IdUtils;

import java.net.URI;
import java.net.URISyntaxException;
import java.util.Comparator;
import java.util.UUID;

/**
 * @author aherman
 */

@Getter
@EqualsAndHashCode(onlyExplicitlyIncluded = true)
@ToString
public class DelUrlRequest {
    public static final Duration STALE_REQUEST_AGE = Duration.standardDays(3);

    @EqualsAndHashCode.Include
    private final UUID requestId;

    @EqualsAndHashCode.Include
    private final WebmasterHostId hostId;

    @NotNull
    private final String relativeUrl;

    private final DelurlState state;
    private final DelurlType type;
    private final DateTime addDate;
    private final DateTime updateDate;
    private final boolean allowedInRobotsTxt;
    private final int httpCode;
    private final boolean noindex;
    private final long userUid;
    private final String balancerRequestId;
    private final int retriesCount;
    private final String errorMessage;

    public DelUrlRequest(
            UUID requestId, WebmasterHostId hostId, @NotNull String relativeUrl,
            DelurlState state, DelurlType type, DateTime addDate, DateTime updateDate,
            boolean allowedInRobotsTxt, int httpCode, boolean noindex,
            long userUid, String balancerRequestId, int retriesCount, String errorMessage)
    {
        this.requestId = requestId;
        this.hostId = hostId;
        this.relativeUrl = relativeUrl;
        this.state = state;
        this.type = type == null ? DelurlType.URL : type;
        this.allowedInRobotsTxt = allowedInRobotsTxt;
        this.httpCode = httpCode;
        this.noindex = noindex;
        this.updateDate = updateDate;
        this.addDate = addDate;
        this.userUid = userUid;
        this.balancerRequestId = balancerRequestId;
        this.retriesCount = retriesCount;
        this.errorMessage = errorMessage;
    }

    public DelUrlRequest withState(DelurlState newState) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, newState, type, addDate, DateTime.now(),
                allowedInRobotsTxt, httpCode, noindex, userUid, balancerRequestId, retriesCount, errorMessage);
    }

    public DelUrlRequest withAllowedInRobotsTxt(boolean allowed) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, state, type, addDate, DateTime.now(),
                allowed, httpCode, noindex, userUid, balancerRequestId, retriesCount, errorMessage);
    }

    public DelUrlRequest withHttpCode(int newHttpCode) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, state, type, addDate, DateTime.now(),
                allowedInRobotsTxt, newHttpCode, noindex, userUid, balancerRequestId, retriesCount, errorMessage);
    }

    public DelUrlRequest withNoindex(boolean newNoindex) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, state, type, addDate, DateTime.now(),
                allowedInRobotsTxt, httpCode, newNoindex, userUid, balancerRequestId, retriesCount, errorMessage);
    }

    public DelUrlRequest withUpdateDate(DateTime updateDate) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, state, type, addDate, updateDate,
                allowedInRobotsTxt, httpCode, noindex, userUid, balancerRequestId, retriesCount, errorMessage);
    }

    public DelUrlRequest withRetriesCount(int retriesCount) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, state, type, addDate, updateDate,
                allowedInRobotsTxt, httpCode, noindex, userUid, balancerRequestId, retriesCount, errorMessage);
    }

    public DelUrlRequest withErrorMessage(String newErrorMessage) {
        return new DelUrlRequest(requestId, hostId, relativeUrl, state, type, addDate, updateDate,
                allowedInRobotsTxt, httpCode, noindex, userUid, balancerRequestId, retriesCount, newErrorMessage);
    }

    public DelUrlRequest withStaleCheck() {
        DelUrlRequest r;
        if (!state.isFinal() && addDate.isBefore(DateTime.now().minus(STALE_REQUEST_AGE))) {
            r = withState(DelurlState.ERROR).withUpdateDate(addDate.plus(STALE_REQUEST_AGE));
        } else {
            r = this;
        }

        return r;
    }

    @JsonIgnore
    public String getFullUrl() {
        return IdUtils.hostIdToReadableUrl(hostId) + relativeUrl;
    }

    @JsonIgnore
    public URI getEncodedUrl() throws URISyntaxException {
        String u = IdUtils.hostIdToUrl(hostId) + relativeUrl;
        return new URI(u);
    }

    public static final Comparator<DelUrlRequest> BY_ADD_DATE = Comparator.comparing(DelUrlRequest::getAddDate);

    public static final Comparator<DelUrlRequest> NEW_FIRST = (o1, o2) ->
            Boolean.compare(o1.getState() == DelurlState.NEW, o2.getState() == DelurlState.NEW);
}
