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

import java.net.MalformedURLException;
import java.net.URL;
import java.util.Map;

import com.datastax.driver.core.utils.UUIDs;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.fasterxml.jackson.databind.JsonNode;
import lombok.Builder;
import lombok.Data;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.http.ReadAction;
import ru.yandex.webmaster3.core.http.RequestQueryProperty;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.viewer.http.AbstractUserAction;
import ru.yandex.webmaster3.viewer.http.AbstractUserRequest;
import ru.yandex.webmaster3.viewer.microdata.semantic.SemanticValidation;

/**
 * ishalaru
 * 25.10.2019
 **/
@Slf4j
@ReadAction
@Description("Заросить валидацию микроразметки по урлу документа")
@Category("validation")
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
@Component("/microdata/semantic/byUrl")
public class MicrodataSemanticValidateByUrlAction extends
        AbstractUserAction<MicrodataSemanticValidateByUrlAction.Request, MicrodataSemanticValidateByUrlAction.Response> {
    private final SemanticValidation semanticValidation;


    @Override
    public Response process(Request request) {
        String reqId = UUIDs.timeBased().toString();
        try {

            Map<String, JsonNode> value = semanticValidation.validateByUrl(new URL(request.getUrl()), request.getLang(), reqId, request.onlyError);
            return createResponse(value, reqId);
        } catch (WebmasterException exp) {
            if (exp.getError().getClass().equals(WebmasterErrorResponse.SitaErrorResponse.class)) {
                WebmasterErrorResponse.SitaErrorResponse error = (WebmasterErrorResponse.SitaErrorResponse) exp.getError();
                return new Response.ErrorResponse(error.getHttpCode());
            }
            throw exp;
        } catch (MalformedURLException e) {
            throw new WebmasterException("Invalid url",
                    new WebmasterErrorResponse.IllegalParameterValueResponse(getClass(), "url", request.getUrl()));
        }
    }

    public static final Response.DataResponse createResponse(Map<String, JsonNode> jsonNode, String reqId) {
        return Response.DataResponse.builder().microdata(jsonNode.get("microdata"))
                .rdfa(jsonNode.get("rdfa"))
                .jsonLd(jsonNode.get("json-ld"))
                .microformat(jsonNode.get("microformat"))
                .id(reqId)
                .build();
    }


    @Data
    public static class Request extends AbstractUserRequest {
        @Setter(onMethod = @__({@Description("Адресс страницы для валидации"), @RequestQueryProperty(required = true)}))
        private String url;
        @Setter(onMethod = @__({@Description("Признак того что надо возврашать только ощибки"), @RequestQueryProperty(required = false)}))
        private boolean onlyError;
        @Setter(onMethod = @__({@Description("Язык"), @RequestQueryProperty(required = false)}))
        private String lang = "ru";

    }

    public static abstract class Response implements ActionResponse {
        @Value
        @Builder
        public static class DataResponse extends Response implements ActionResponse.NormalResponse {
            String id;
            JsonNode microdata;
            JsonNode rdfa;
            @JsonProperty("json-ld")
            JsonNode jsonLd;
            JsonNode microformat;
        }

        @Value
        public static class ErrorResponse extends Response implements ActionResponse.ErrorResponse {
            Integer httpCode;

            @Override
            public Enum<?> getCode() {
                return ErrorCode.DOCUMENT_DOWNLOADING_FAILED;
            }

            @Override
            public String getMessage() {
                return "Не удалось скачать документ.";
            }
        }

        public enum ErrorCode {
            DOCUMENT_DOWNLOADING_FAILED
        }
    }
}
