package ru.yandex.webmaster3.viewer.http.sitemap.analyze;

import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.joda.time.Duration;
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.ReadAction;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.metrics.Category;
import ru.yandex.webmaster3.core.util.json.JsonMapping;
import ru.yandex.webmaster3.storage.async.AsyncRequestTaskService;
import ru.yandex.webmaster3.storage.async.model.AsyncOperationRequestInfo;
import ru.yandex.webmaster3.storage.async.model.HttpAsyncRequestInfoRequestState;
import ru.yandex.webmaster3.storage.async.model.HttpAsyncRequestInfoResultType;
import ru.yandex.webmaster3.storage.sitemap.service.model.AnalyzeSitemapErrorTransfer;
import ru.yandex.webmaster3.storage.sitemap.service.model.AnalyzeSitemapErrorType;
import ru.yandex.webmaster3.storage.sitemap.service.model.AnalyzeSitemapResponseType;
import ru.yandex.webmaster3.storage.sitemap.service.model.SitemapAnalysisExtendedResult;
import ru.yandex.webmaster3.viewer.http.BaseWebmaster3Action;
import ru.yandex.webmaster3.viewer.http.async.model.AsyncInfoRequest;
import ru.yandex.webmaster3.viewer.http.sitemap.analyze.model.AnalyzeSitemapInfoResponse;

/**
 * @author: ishalaru
 * DATE: 16.05.2019
 */
@ReadAction
@Description(value = "Информация о заявке на валидацию файлов sitemap")
@Category("sitemap")
@Slf4j
@Component("/sitemap/analyzeInfo")
public class AnalyzeSitemapRequstInfoAction extends BaseWebmaster3Action<AsyncInfoRequest, AnalyzeSitemapInfoResponse> {
    private static final Duration ANSWER_WAITING_TIMEOUT = Duration.standardMinutes(1);

    private final AsyncRequestTaskService asyncRequestTaskService;

    @Autowired
    public AnalyzeSitemapRequstInfoAction(AsyncRequestTaskService asyncRequestTaskService) {
        this.asyncRequestTaskService = asyncRequestTaskService;
    }

    @Override
    public AnalyzeSitemapInfoResponse process(AsyncInfoRequest request) {
        AsyncOperationRequestInfo responseInfo = asyncRequestTaskService.getResponseInfo(request.getRequestId());
        if (responseInfo == null) {
            return new AnalyzeSitemapInfoResponse.RequestIdNotFound(this.getClass());
        }
        if (responseInfo.getState() == HttpAsyncRequestInfoRequestState.NEW &&
                responseInfo.getLastUpdate().plus(ANSWER_WAITING_TIMEOUT).isBefore(DateTime.now())) {
            log.error("Worker failed to start request in {}", ANSWER_WAITING_TIMEOUT);
            throw new WebmasterException("TimeoutError", new WebmasterErrorResponse.AsyncZoraErrorResponse(getClass()));
//            return new AnalyzeSitemapInfoResponse.RequestFailed(this.getClass());
        }
        if (responseInfo.getState() != HttpAsyncRequestInfoRequestState.TASK_FINISHED) {
            return AnalyzeSitemapInfoResponse.NormalResponse.stillInProgress();
//            return new AnalyzeSitemapInfoResponse.RequestStillInProgress(this.getClass());
        }
        if (responseInfo.getResult() != HttpAsyncRequestInfoResultType.OK) {
            if (responseInfo.getResult() == HttpAsyncRequestInfoResultType.INTERNAL_ERROR) {
                throw new WebmasterException("InternalError", new WebmasterErrorResponse.AsyncZoraErrorResponse(getClass()));
            } else {
                return new AnalyzeSitemapInfoResponse.RequestFailed(this.getClass());
            }
        }
        if (responseInfo.getResponseObjectTypeId() == AnalyzeSitemapResponseType.NORMAL.getValue()) {
            SitemapAnalysisExtendedResult result = convertData(responseInfo, SitemapAnalysisExtendedResult.class);
            if (result == null) {
                return new AnalyzeSitemapInfoResponse.ResponseDataCorrupted(this.getClass());
            }
            return new AnalyzeSitemapInfoResponse.NormalResponse(result.getSitemapAnalysisResult(),
                    result.getSitemapFileSize(), result.getSitemapFileName());
        } else if (responseInfo.getResponseObjectTypeId() == AnalyzeSitemapResponseType.HTTP_PROBLEM.getValue()) {
            AnalyzeSitemapErrorTransfer result = convertData(responseInfo, AnalyzeSitemapErrorTransfer.class);
            return new AnalyzeSitemapInfoResponse.SitemapAnalyzeIsEmptyResponse(this.getClass(),
                    result.getAnalyzeSitemapErrorType(), result.getHttpResponsePart());
        } else {
            AnalyzeSitemapErrorType analyzeSitemapErrorType = convertData(responseInfo, AnalyzeSitemapErrorType.class);
            return new AnalyzeSitemapInfoResponse.SitemapAnalyzeErrorResponse(this.getClass(), analyzeSitemapErrorType);
        }

    }

    protected <WorkClass> WorkClass convertData(AsyncOperationRequestInfo info, Class<WorkClass> clazz) {
        WorkClass result = null;
        try {

            result = JsonMapping.readValue(info.getResponse(), clazz);
        } catch (Exception exp) {
            log.error(exp.getMessage(), exp);
        }
        return result;
    }
}
