package ru.yandex.webmaster3.storage.turbo.service.settings;

import java.util.List;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Value;

import ru.yandex.autodoc.common.doc.annotation.Description;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.turbo.model.TurboHostSettingsBlock;
import ru.yandex.webmaster3.core.turbo.model.TurboPlatform;
import ru.yandex.webmaster3.core.turbo.model.advertising.AdvertisingPlacement;
import ru.yandex.webmaster3.core.turbo.model.advertising.AdvertisingSettings;
import ru.yandex.webmaster3.core.turbo.model.analytics.AnalyticsSettings;
import ru.yandex.webmaster3.storage.turbo.service.css.TurboCssErrorInfo;

/**
 * Created by Oleg Bazdyrev on 03/08/2017.
 */
public abstract class SetTurboSettingsResponse implements ActionResponse {

    public enum ErrorCode {
        SET_TURBO_SETTINGS__LOGO_NOT_SET,
        SET_TURBO_SETTINGS__INVALID_LOGO,
        SET_TURBO_SETTINGS__HEADER_NOT_SELECTED,
        SET_TURBO_SETTINGS__DUPLICATE_ALIAS,
        SET_TURBO_SETTINGS__YANDEX_AD_NOT_EXISTS,
        SET_TURBO_SETTINGS__YANDEX_AD_NON_TURBO,
        SET_TURBO_SETTINGS__ADFOX_INVALID_CODE,
        SET_TURBO_SETTINGS__INVALID_ANALYTICS_CODE,
        SET_TURBO_SETTINGS__INVALID_METRIKA_ID,
        SET_TURBO_SETTINGS__DUPLICATE_ANALYTICS_CODE,
        SET_TURBO_SETTINGS__INVALID_MENU_LABEL,
        SET_TURBO_SETTINGS__INVALID_MENU_URL,
        SET_TURBO_SETTINGS__INVALID_CART_URL,
        SET_TURBO_SETTINGS__DUPLICATE_COMMERCE_SECTION,
        SET_TURBO_SETTINGS__INVALID_CHECKOUT_EMAIL,
        SET_TURBO_SETTINGS__INVALID_TURBO_CART_EMAIL,
        SET_TURBO_SETTINGS__EMPTY_TURBO_CART_EMAIL,
        SET_TURBO_SETTINGS__NO_ORDER_METHOD_SELECTED,
        SET_TURBO_SETTINGS__INVALID_FEEDBACK_URL,
        SET_TURBO_SETTINGS__INVALID_FEEDBACK_EMAIL,
        SET_TURBO_SETTINGS__INVALID_USER_AGREEMENT,
        SET_TURBO_SETTINGS__INVALID_USER_AGREEMENT_URL,
        SET_TURBO_SETTINGS__YANDEX_INPAGE_INVALID_ID,
        SET_TURBO_SETTINGS__ADFOX_INPAGE_INVALID_CODE,
        SET_TURBO_SETTINGS__YANDEX_INSTREAM_INVALID_ID,
        SET_TURBO_SETTINGS__ADFOX_INSTREAM_INVALID_CODE,
        SET_TURBO_SETTINGS__ADFOX_INTERSCROLLER_INVALID_CODE,
        SET_TURBO_SETTINGS__LOT_OF_INPAGE_ADVERTISING_IN_ONE_PLACEMENT,
        SET_TURBO_SETTINGS__YANDEX_REC_WIDGET_INVALID_ID,
        SET_TURBO_SETTINGS__INVALID_SEARCH_URL,
        SET_TURBO_SETTINGS__INVALID_AUTH_ENDPOINT_URL,
        SET_TURBO_SETTINGS__INVALID_LOGIN_ENDPOINT_URL,
        SET_TURBO_SETTINGS__INVALID_LOGOUT_ENDPOINT_URL,
        SET_TURBO_SETTINGS__INVALID_GET_COMMENTS_ENDPOINT_URL,
        SET_TURBO_SETTINGS__INVALID_ADD_COMMENTS_ENDPOINT_URL,
        SET_TURBO_SETTINGS__DIFFERENT_AUTH_ENDPOINT_DOMAINS,
        SET_TURBO_SETTINGS__DIFFERENT_COMMENTS_ENDPOINT_DOMAINS,
        SET_TURBO_SETTINGS__PAYMENTS_TOKEN_NOT_FOUND,
        SET_TURBO_SETTINGS__PAYMENTS_TOKEN_NOT_CONFIRMED,
        SET_TURBO_SETTINGS__INVALID_BITRIX_API_BASE_URL,
        SET_TURBO_SETTINGS__INVALID_DELIVERY_SETTINGS_PARAMETER,
        SET_TURBO_SETTINGS__INVALID_CSS,
        SET_TURBO_SETTINGS__INVALID_COLOR,
        SET_TURBO_SETTINGS__INVALID_TITLE,
        SET_TURBO_SETTINGS__INVALID_DESCRIPTION,
    }

    public static class NormalResponse extends SetTurboSettingsResponse implements ActionResponse.NormalResponse {

    }

    public static abstract class ErrorResponse extends SetTurboSettingsResponse implements ActionResponse.ErrorResponse {

    }

    @Description("Заголовок помечен как активный, однако лого не установлено")
    public static class LogoNotSetErrorResponse extends ErrorResponse {

        private final TurboPlatform platform;

        public LogoNotSetErrorResponse(TurboPlatform platform) {
            this.platform = platform;
        }

        public TurboPlatform getPlatform() {
            return platform;
        }

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

    @Description("Некорректный формат логотипа (меньше 96х96 или не квадратный)")
    public static class InvalidLogoResponse extends ErrorResponse {

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

    @Description("Не выбран ни один тип заголовка")
    public static class HeaderNotSelectedErrorResponse extends ErrorResponse {

        private final TurboPlatform platform;

        public HeaderNotSelectedErrorResponse(TurboPlatform platform) {
            this.platform = platform;
        }

        public TurboPlatform getPlatform() {
            return platform;
        }

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

    public static abstract class AdvertisingErrorResponse extends ErrorResponse {
        private final int index;
        private final AdvertisingSettings advertisingSettings;
        private final TurboPlatform platform;

        public AdvertisingErrorResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            this.index = index;
            this.advertisingSettings = advertisingSettings;
            this.platform = platform;
        }

        @Description("Индекс некорректного рекламного блока")
        public int getIndex() {
            return index;
        }

        @Description("Где именно некорректный код")
        public AdvertisingSettings getAdvertisingSettings() {
            return advertisingSettings;
        }

        @Description("Платформа")
        public TurboPlatform getPlatform() {
            return platform;
        }
    }

    @Description("Дублирующийся алиас рекламного блока")
    public static class DuplicateAliasResponse extends AdvertisingErrorResponse {

        public DuplicateAliasResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Код рекламного блока Яндекс.Директ не найден")
    public static class YandexAdNotExistsResponse extends AdvertisingErrorResponse {

        public YandexAdNotExistsResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Рекламный блок Яндекс.Директ не является турбо-блоко ")
    public static class YandexAdNonTurboResponse extends AdvertisingErrorResponse {

        public YandexAdNonTurboResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Код рекламного блока Adfox некорректен")
    public static class AdfoxInvalidCodeResponse extends AdvertisingErrorResponse {

        public AdfoxInvalidCodeResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Идентификатор рекламного блока yandex inpage видеорекламы некорректен")
    public static class YandexInpageInvalidIdResponse extends AdvertisingErrorResponse {

        public YandexInpageInvalidIdResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Идентификатор рекламного блока yandex instream видеорекламы некорректен")
    public static class YandexInstreamInvalidIdResponse extends AdvertisingErrorResponse {

        public YandexInstreamInvalidIdResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Код рекламного блока Adfox InPage некорректен")
    public static class AdFoxInpageInvalidCodeResponse extends AdvertisingErrorResponse {

        public AdFoxInpageInvalidCodeResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Код рекламного блока Adfox InStream некорректен")
    public static class AdFoxInstreamInvalidCodeResponse extends AdvertisingErrorResponse {

        public AdFoxInstreamInvalidCodeResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Код рекламного блока Adfox InterScroller некорректен")
    public static class AdFoxInterscrollerInvalidCodeResponse extends AdvertisingErrorResponse {

        public AdFoxInterscrollerInvalidCodeResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Description("Код рекламного блока REC_WIDGET некорректен")
    public static class RecWidgetIdInvalidCodeResponse extends AdvertisingErrorResponse {

        public RecWidgetIdInvalidCodeResponse(int index, AdvertisingSettings advertisingSettings, TurboPlatform platform) {
            super(index, advertisingSettings, platform);
        }

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

    @Getter
    @RequiredArgsConstructor
    @Description("Код рекламного блока содержит 2 inpage рекламы")
    public static class LotOfInPageAdvertisingInOnePlacementResponse extends ErrorResponse {
        @Description("Где именно некорректный две inpage рекламы")
        private final AdvertisingPlacement advertisingPlacement;

        @Description("Платформа")
        private final TurboPlatform platform;

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

    public static abstract class AnalyticsErrorResponse extends ErrorResponse {

        private final int index;
        private final AnalyticsSettings analyticsSettings;

        public AnalyticsErrorResponse(int index, AnalyticsSettings analyticsSettings) {
            this.index = index;
            this.analyticsSettings = analyticsSettings;
        }

        @Description("Индекс некорректного счетчика")
        public int getIndex() {
            return index;
        }

        @Description("Где именно некорректный код")
        public AnalyticsSettings getAnalyticsSettings() {
            return analyticsSettings;
        }
    }

    @Description("Некорректный код системы аналитики")
    public static class InvalidAnalyticsCodeResponse extends AnalyticsErrorResponse {

        public InvalidAnalyticsCodeResponse(int index, AnalyticsSettings analyticsSettings) {
            super(index, analyticsSettings);
        }

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

    @Description("Дублирующийся код системы аналитики")
    public static class DuplicateAnalyticsCodeResponse extends AnalyticsErrorResponse {

        public DuplicateAnalyticsCodeResponse(int index, AnalyticsSettings analyticsSettings) {
            super(index, analyticsSettings);
        }

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

    @Description("Некорректный id метрики")
    public static class InvalidMetrikaIdResponse extends AnalyticsErrorResponse {

        public InvalidMetrikaIdResponse(int index, AnalyticsSettings analyticsSettings) {
            super(index, analyticsSettings);
        }

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

    @Value
    public static class InvalidMenuLabelResponse extends ErrorResponse {

        @Description("Индекс некорректного пункта меню")
        private final int index;
        @Description("Какое это меню - MENU или TOP_MENU")
        private final TurboHostSettingsBlock type;
        @Description("Путь до пункта меню с ошибкой - для многоуровневого меню")
        private final List<Integer> indexes;

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

    @Value
    public static class InvalidMenuUrlResponse extends ErrorResponse {

        @Description("Индекс некорректного пункта меню")
        private final int index;
        @Description("Какое это меню - MENU или TOP_MENU")
        private final TurboHostSettingsBlock type;
        @Description("Путь до пункта меню с ошибкой - для многоуровневого меню")
        private final List<Integer> indexes;

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

    @Description("Некорректный url корзины для e-commerce")
    public static class InvalidCartUrlResponse extends ErrorResponse {

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

    public static class DuplicateCommerceSectionResponse extends SetTurboSettingsResponse
            implements ActionResponse.ErrorResponse {

        private final int index;

        public DuplicateCommerceSectionResponse(int index) {
            this.index = index;
        }

        @Description("Индекс дублирующейся секции")
        public int getIndex() {
            return index;
        }

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

    @Description("Некорректный адрес электронной почты для покупок в один клик")
    public static class InvalidCheckoutEmailResponse extends ErrorResponse {

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

    @Description("Некорректный адрес электронной почты для турбо-корзины")
    public static class InvalidTurboCartEmailResponse extends ErrorResponse {

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

    @Description("адрес электронной почты для турбо-корзины не задан")
    public static class EmptyTurboCartEmailResponse extends ErrorResponse {

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


    @Description("Не выбран метод заказа")
    public static class NoOrderMethodSelectedResponse extends ErrorResponse {

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

    @Description("Кривая ссылка в кнопке блока обратной связи")
    public static class InvalidFeedbackUrlResponse extends ErrorResponse {

        private final int index;

        public InvalidFeedbackUrlResponse(int index) {
            this.index = index;
        }

        @Description("Индекс некорректной кнопки блока обратной связи")
        public int getIndex() {
            return index;
        }

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

    @Description("Кривой емейл в кнопке блока обратной связи")
    public static class InvalidFeedbackEmailResponse extends ErrorResponse {

        private final int index;

        public InvalidFeedbackEmailResponse(int index) {
            this.index = index;
        }

        @Description("Индекс некорректной кнопки блока обратной связи")
        public int getIndex() {
            return index;
        }

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

    @Description("Заполнено только название компании для соглашения, либо ссылка на соглашение. А должны быть заполнены оба поля")
    public static class InvalidUserAgreementResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_USER_AGREEMENT;
        }
    }

    @Description("Кривая ссылка на соглашение")
    public static class InvalidUserAgreementUrlResponse extends ErrorResponse {

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

    @Description("Кривой урл для поиска")
    public static class InvalidSearchUrlResponse extends ErrorResponse {

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

    public static class InvalidAuthEndpointUrlResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_AUTH_ENDPOINT_URL;
        }
    }

    public static class InvalidLoginEndpointUrlResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_LOGIN_ENDPOINT_URL;
        }
    }

    public static class InvalidLogoutEndpointUrlResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_LOGOUT_ENDPOINT_URL;
        }
    }

    public static class InvalidGetCommentsEndpointUrlResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_GET_COMMENTS_ENDPOINT_URL;
        }
    }

    public static class InvalidAddCommentsEndpointUrlResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_ADD_COMMENTS_ENDPOINT_URL;
        }
    }

    @Description("Отличающиеся домены в ручках авторизации")
    public static class DifferentAuthEndpointDomainsResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__DIFFERENT_AUTH_ENDPOINT_DOMAINS;
        }
    }

    @Description("Отличающиеся домены в ручках комментов")
    public static class DifferentCommentsEndpointDomainsResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__DIFFERENT_COMMENTS_ENDPOINT_DOMAINS;
        }
    }

    @Description("Токен для оплат не найден")
    public static class PaymentsTokenNotFoundResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__PAYMENTS_TOKEN_NOT_FOUND;
        }
    }

    @Description("Токен для оплат не подтвержден")
    public static class PaymentsTokenNotConfirmedResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__PAYMENTS_TOKEN_NOT_CONFIRMED;
        }
    }

    @Description("Некорретный URL API Bitrix")
    public static class InvalidBitrixApiBaseUrlResponse extends ErrorResponse {
        @Override
        public Enum<?> getCode() {
            return ErrorCode.SET_TURBO_SETTINGS__INVALID_BITRIX_API_BASE_URL;
        }
    }

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

        public IllegalParameterValueResponse(String parameterName, String parameterValue) {
            this(parameterName, parameterValue, "Illegal parameter value: " + parameterName + "=" + parameterValue);
        }
        public IllegalParameterValueResponse(String parameterName, String parameterValue, String message) {
            this.parameterName = parameterName;
            this.parameterValue = parameterValue;
            this.message = message;
        }
        @Override public Enum<?> getCode() {return ErrorCode.SET_TURBO_SETTINGS__INVALID_DELIVERY_SETTINGS_PARAMETER;}
        @Override public String getMessage() { return message;}
        public String getParameterName() {return parameterName;}
        public String getParameterValue() {return parameterValue;}
    }

    @Description("Невалидный CSS")
    public static class InvalidCssResponse extends ErrorResponse {

        private final List<TurboCssErrorInfo> cssErrors;

        public InvalidCssResponse(List<TurboCssErrorInfo> cssErrors) {
            this.cssErrors = cssErrors;
        }

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

        @Description("Ошибки валидации CSS. Если список пуст - все ок")
        public List<TurboCssErrorInfo> getCssErrors() {
            return cssErrors;
        }
    }

    @Value
    @Description("Некорректное значение цвета (должно быть 6 шестнадтеричных цифр)")
    public static class InvalidColorResponse extends ErrorResponse {

        String field;

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

    @Value
    @Description("Некорректный заголовок (пустой или слишком длинный)")
    public static class InvalidTitleResponse extends ErrorResponse {

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

    @Value
    @Description("Некорректное описание (пустое или слишком длинное)")
    public static class InvalidDescriptionResponse extends ErrorResponse {

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