package ru.yandex.webmaster3.core.http;

import java.io.PrintWriter;
import java.io.StringWriter;

import org.apache.commons.lang3.StringUtils;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.WebmasterCommonErrorType;

/**
 * @author aherman
 */
public abstract class WebmasterErrorResponse implements ActionResponse.ErrorResponse {
    private final Class<?> clazz;
    private final String stackTrace;

    protected WebmasterErrorResponse(Class<?> clazz) {
        this.clazz = clazz;
        this.stackTrace = null;
    }

    protected WebmasterErrorResponse(Class<?> clazz, Exception e) {
        this.clazz = clazz;
        if (e != null) {
            StringWriter sw = new StringWriter(2*1024);
            PrintWriter pw = new PrintWriter(sw);
            e.printStackTrace(pw);
            pw.close();
            this.stackTrace = sw.toString();
        } else {
            this.stackTrace = null;
        }
    }

    @Override
    public Class<?> getClazz() {
        return clazz;
    }

    @Override
    public String getStackTrace() {
        return stackTrace;
    }

    @Description(value="Неправильное значение параметра: параметр отстутствует, неверный тип значения или значение не прошло проверку в ручке")
    public static class IllegalParameterValueResponse extends WebmasterErrorResponse {
        private final String parameterName;
        private final String parameterValue;
        private final String message;

        public IllegalParameterValueResponse(Class<?> clazz, String parameterName, String parameterValue) {
            this(clazz, parameterName, parameterValue, "Illegal parameter value: " + parameterName + "=" + String.valueOf(parameterValue));
        }
        public IllegalParameterValueResponse(Class<?> clazz, String parameterName, String parameterValue, String message) {
            super(clazz);
            this.parameterName = parameterName;
            this.parameterValue = parameterValue;
            this.message = message;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.REQUEST__ILLEGAL_PARAMETER_VALUE;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.REQUEST;}
        @Override public String getMessage() { return message;}
        public String getParameterName() {return parameterName;}
        public String getParameterValue() {return parameterValue;}
    }

    @Description(value="Не удалось прочитать фаил за запроса")
    public static class IllegalFileParameterResponse extends WebmasterErrorResponse {
        private final String parameterName;
        private final String message;
        public IllegalFileParameterResponse(Class<?> clazz, String parameterName, String message) {
            super(clazz);
            this.parameterName = parameterName;
            this.message = message;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.REQUEST__ILLEGAL_FILE_PARAMETER;}
        @Override public Enum<?> getSubsystem() { return WebmasterCommonErrorSystem.REQUEST;}
        @Override public String getMessage() {return "Illegal file parameter: " + StringUtils.trimToEmpty(message);}
        public String getParameterName() {return parameterName;}
    }

    @Description(value="\"Что-то пошло не так\"")
    public static class InternalUnknownErrorResponse extends WebmasterErrorResponse {
        private final String message;
        public InternalUnknownErrorResponse(Class<?> clazz, String message) {
            super(clazz);
            this.message = message;
        }
        public InternalUnknownErrorResponse(Class<?> clazz, String message, Exception e) {
            super(clazz, e);
            this.message = message;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__UNKNOWN;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Internal error: " + StringUtils.trimToEmpty(message);}
    }

    @Description(value="Запрос в ГоЗору затаймаутился")
    public static class GoZoraTimedOutResponse extends WebmasterErrorResponse {
        public GoZoraTimedOutResponse(Class<?> clazz) {
            super(clazz);
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__GO_ZORA_TIMED_OUT_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "GoZora timed out";}
    }

    @Description(value="Не распарсился запрос")
    public static class UnableToInstantateRequestResponse extends WebmasterErrorResponse {
        public UnableToInstantateRequestResponse(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__UNABLE_TO_INSTANTIATE_REQUEST;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Unable to instantiate request";}
    }

    @Description(value="Не распарсился json-запрос")
    public static class UnableToReadJsonRequestResponse extends WebmasterErrorResponse {
        public UnableToReadJsonRequestResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__UNABLE_TO_READ_JSON_REQUEST;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Unable to read json request";}
    }

    @Description(value="Проблемы при чтении бинарных данных из запроса")
    public static class UnableToReadRequestBinaryDataResponse extends WebmasterErrorResponse {
        public UnableToReadRequestBinaryDataResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__UNABLE_TO_READ_REQUEST_BINARY_DATA;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Unable to read request binary data";}
    }

    @Description(value="В объекте запросе обнаружен неизвестный тип параметра")
    public static class UnsupportedRequestParameterTypeResponse extends WebmasterErrorResponse {
        private final String parameterName;
        public UnsupportedRequestParameterTypeResponse(Class<?> clazz, String parameterName) {
            super(clazz);
            this.parameterName = parameterName;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__UNSUPPORTED_REQUEST_PARAMETER_TYPE;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Unsupported request parameter type: " + parameterName;}
        public String getParameterName() {return parameterName;}
    }

    @Description(value="Sita недоступна")
    public static class SitaErrorResponse extends WebmasterErrorResponse {
        private final Integer httpCode;
        private final String message;

        public SitaErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
            message = null;
            httpCode = null;
        }

        public SitaErrorResponse(Class<?> clazz, String message, Exception e) {
            super(clazz, e);
            this.message = message;
            httpCode = null;
        }

        public SitaErrorResponse(Class<?> clazz, String message, Integer httpCode, Exception e) {
            super(clazz, e);
            this.httpCode = httpCode;
            this.message = message;
        }

        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__SITA_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Sita error: " + StringUtils.trimToEmpty(message);}

        public Integer getHttpCode() {
            return httpCode;
        }
    }

    @Description(value="Проблемы с YDB")
    public static class YDBErrorResponse extends WebmasterErrorResponse{
        public YDBErrorResponse(Class<?> clazz, Exception e){
            super(clazz,e);
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__YDB_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Cassandra error";}
    }

    @Description(value="Проблемы с Logbroker")
    public static class LogbrokerErrorResponse extends WebmasterErrorResponse{
        public LogbrokerErrorResponse(Class<?> clazz, Exception e){
            super(clazz,e);
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__LOGRBROKER_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Logbroker error";}
    }

    @Description(value="Ошибка при выполнении SQL-запросе")
    public static class SQLErrorResponse extends WebmasterErrorResponse {
        private final String sqlQuery;
        public SQLErrorResponse(Class<?> clazz, String sqlQuery, Exception e) {
            super(clazz, e);
            this.sqlQuery = sqlQuery;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__SQL_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "SQL error: query=" + sqlQuery;}
        public String getSqlQuery() {return sqlQuery;}
    }

    @Description(value="Проблемы с zookeeper")
    public static class ZookeeperErrorResponse extends WebmasterErrorResponse {
        public ZookeeperErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__ZOOKEEPER_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Zookeeper error";}
    }

    @Description(value="Проблемы с worker-ом")
    public static class WorkerErrorResponse extends WebmasterErrorResponse {
        public WorkerErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__WORKER_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Worker error";}
    }

    @Description(value="Обнаружено расхождение данных")
    public static class DataConsistencyErrorResponse extends WebmasterErrorResponse {
        private final String message;

        public DataConsistencyErrorResponse(Class<?> clazz, String message) {
            super(clazz);
            this.message = message;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__DATA_CONSISTENCY;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Data consistency error: " + StringUtils.trimToEmpty(message);}
    }

    @Description(value="Проблемы с dispatcher")
    public static class DispatcherErrorResponse extends WebmasterErrorResponse {
        public DispatcherErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__DISPATCHER_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Dispatcher error";}
    }

    @Description(value="Проблемы с serp link сервисом ")
    public static class SerpLinksErrorResponse extends WebmasterErrorResponse {
        public SerpLinksErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__SERP_LINKS_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Serp links error";}
    }

    @Description(value = "Ошибка при работе с геобазой")
    public static class GeobaseErrorResponse extends WebmasterErrorResponse {
        public GeobaseErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__GEOBASE_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Geobase error";}
    }

    public static class GeodataServiceErrorResponse extends WebmasterErrorResponse {
        public GeodataServiceErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__GEODATA_SERVICE_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Geodata service error";}
    }

    public static class YTServiceErrorResponse extends WebmasterErrorResponse {
        public YTServiceErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__YTSERVICE_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "YT service error";}
    }

    public static class YqlServiceErrorResponse extends WebmasterErrorResponse {
        public YqlServiceErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__YTSERVICE_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "YQL service error";}
    }

    public static class UserSitemapUploadErrorResponse extends WebmasterErrorResponse{
        public UserSitemapUploadErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__USER_SITEMAP_UPLOAD_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "User sitemap upload service error";}
    }

    public static class GeminiProxyErrorResponse extends WebmasterErrorResponse{
        public GeminiProxyErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__GEMINI_PROXY_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Gemini service error";}
    }

    public static class BlackboxErrorResponse extends WebmasterErrorResponse{
        public BlackboxErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__BLACKBOX_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Blackbox service error";}
    }

    public static class CmntErrorResponse extends WebmasterErrorResponse{
        public CmntErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__CMNT_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Commentator service error";}
    }

    public static class MicrodataServiceErrorResponse extends WebmasterErrorResponse {
        public MicrodataServiceErrorResponse(Class<?> clazz) {super(clazz);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__MICRODATA_SERVICE_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Microdata service error";}
    }

    public static class ClickhouseErrorResponse extends WebmasterErrorResponse {
        private final String query;
        public ClickhouseErrorResponse(Class<?> clazz, String query) {super(clazz); this.query = query; }
        public ClickhouseErrorResponse(Class<?> clazz, String query, Exception e) {
            super(clazz, e);
            this.query = query;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__CLICKHOUSE_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Clickhouse service error";}
    }

    public static class NannyErrorResponse extends WebmasterErrorResponse {
        public NannyErrorResponse(Class<?> clazz) {super(clazz);}
        public NannyErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__NANNY_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Nanny service error";}
    }

    public static class AsyncZoraErrorResponse extends WebmasterErrorResponse {
        public AsyncZoraErrorResponse(Class<?> clazz) {super(clazz);}
        public AsyncZoraErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__ASYNC_ZORA_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Async execution zora request error";}
    }

    public static class AsyncAddFeedErrorResponse extends WebmasterErrorResponse {
        public AsyncAddFeedErrorResponse(Class<?> clazz) {super(clazz);}
        public AsyncAddFeedErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__ASYNC_ADD_FEED_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Async execution add feed request error";}
    }

    public static class OriginalsErrorResponse extends WebmasterErrorResponse {
        private final int httpCode;

        public OriginalsErrorResponse(Class<?> clazz, int httpCode) {super(clazz); this.httpCode = httpCode;}
        public OriginalsErrorResponse(Class<?> clazz, int httpCode, Exception e) {super(clazz, e);this.httpCode = httpCode;}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__ORIGINALS_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Original text service error";}
        public int getHttpCode() {return httpCode;}
    }

    @Description(value = "Проблемы с MDS стораджем")
    public static class MdsErrorResponse extends WebmasterErrorResponse {
        public MdsErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }

        @Override
        public Enum<?> getCode() {
            return WebmasterCommonErrorType.INTERNAL__MDS_ERROR;
        }

        @Override
        public Enum<?> getSubsystem() {
            return WebmasterCommonErrorSystem.INTERNAL;
        }

        @Override
        public String getMessage() {
            return "MDS error";
        }
    }

    @Description(value = "Проблемы с экспортом данных в xlsx/csv файл")
    public static class ExportErrorResponse extends WebmasterErrorResponse {
        public ExportErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }

        @Override
        public Enum<?> getCode() {
            return WebmasterCommonErrorType.INTERNAL__EXPORT_ERROR;
        }

        @Override
        public Enum<?> getSubsystem() {
            return WebmasterCommonErrorSystem.INTERNAL;
        }

        @Override
        public String getMessage() {
            return "Export error";
        }
    }

    @Description(value = "Не распарсились xml данные")
    public static class UnableToParseXMlDataResponse extends WebmasterErrorResponse {
        public UnableToParseXMlDataResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }

        @Override
        public Enum<?> getCode() {
            return WebmasterCommonErrorType.INTERNAL__UNABLE_TO_PARSE_XML_DATA;
        }

        @Override
        public Enum<?> getSubsystem() {
            return WebmasterCommonErrorSystem.INTERNAL;
        }

        @Override
        public String getMessage() {
            return "Unable to parse xml data";
        }
    }

    @Description(value="Проблемы с редисом")
    public static class RedisErrorResponse extends WebmasterErrorResponse {
        private final String redisQuery;
        public RedisErrorResponse(Class<?> clazz, String redisQuery, Exception e) {
            super(clazz, e);
            this.redisQuery = redisQuery;
        }
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__REDIS_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Redis error: query=" + StringUtils.trimToEmpty(redisQuery);}
        public String getRedisQuery() {return redisQuery;}
    }

    @Description(value = "Проблемы с mds стораджем - аватарницей")
    public static class AvatarsErrorResponse extends WebmasterErrorResponse {
        private String message;
        public AvatarsErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }

        public AvatarsErrorResponse(Class<?> clazz, Exception e, String message) {
            super(clazz, e);
            this.message = message;
        }

        @Override
        public Enum<?> getCode() {
            return WebmasterCommonErrorType.INTERNAL__AVATARS_ERROR;
        }

        @Override
        public Enum<?> getSubsystem() {
            return WebmasterCommonErrorSystem.INTERNAL;
        }

        @Override
        public String getMessage() {
            return "Avatarnica error: " + StringUtils.trimToEmpty(message);
        }
    }

    @Description("Проблемы связи с сервисами турбо")
    public static class TurboErrorResponse extends WebmasterErrorResponse {

        private String message;

        public TurboErrorResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }

        public TurboErrorResponse(Class<?> clazz, Exception e, String message) {
            super(clazz, e);
            this.message = message;
        }

        @Override
        public Enum<?> getCode() {
            return WebmasterCommonErrorType.INTERNAL__TURBO_ERROR;
        }

        @Override
        public Enum<?> getSubsystem() {
            return WebmasterCommonErrorSystem.INTERNAL;
        }

        @Override
        public String getMessage() {
            return "Turbo error: " + StringUtils.trimToEmpty(message);
        }

    }

    @Description("Сайт не участвует в топе радара")
    public static class HostNotParticipateInTopRadarResponse extends WebmasterErrorResponse {

        public HostNotParticipateInTopRadarResponse(Class<?> clazz, Exception e) {
            super(clazz, e);
        }

        @Override
        public Enum<?> getCode() {
            return WebmasterCommonErrorType.INTERNAL__HOST_NOT_PARTICIPATE_IN_TOP_RADAR;
        }

        @Override
        public Enum<?> getSubsystem() {
            return WebmasterCommonErrorSystem.INTERNAL;
        }

        @Override
        public String getMessage() {
            return "Metrika radar error: host not participate in top radar";
        }

    }

    public static class VanadiumErrorResponse extends WebmasterErrorResponse{
        public VanadiumErrorResponse(Class<?> clazz) {super(clazz);}
        public VanadiumErrorResponse(Class<?> clazz, Exception e) {super(clazz, e);}
        @Override public Enum<?> getCode() {return WebmasterCommonErrorType.INTERNAL__VANADIUM_ERROR;}
        @Override public Enum<?> getSubsystem() {return WebmasterCommonErrorSystem.INTERNAL;}
        @Override public String getMessage() {return "Commentator service error";}
    }

}
