package ru.yandex.webmaster3.worker.notifications;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.UUID;

import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
import lombok.SneakyThrows;
import lombok.Value;
import org.joda.time.DateTime;

import ru.yandex.webmaster3.core.checklist.data.CompanyInfo;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemContent;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemSeverityEnum;
import ru.yandex.webmaster3.core.checklist.data.SiteProblemTypeEnum;
import ru.yandex.webmaster3.core.data.HttpCodeInfo;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.feeds.feed.FeedsErrorSeverity;
import ru.yandex.webmaster3.core.host.SlowUrlSampleInfo;
import ru.yandex.webmaster3.core.hoststat.HostStatisticsInfo.ContentAttrSampleInfo;
import ru.yandex.webmaster3.core.hoststat.HostStatisticsInfo.PageSampleInfo;
import ru.yandex.webmaster3.core.metrika.counters.CounterRequestTypeEnum;
import ru.yandex.webmaster3.core.notification.LanguageEnum;
import ru.yandex.webmaster3.core.sitemap.SitemapInfo;
import ru.yandex.webmaster3.core.sitestructure.SearchUrlStatusEnum;
import ru.yandex.webmaster3.core.turbo.model.TurboPlatform;
import ru.yandex.webmaster3.core.turbo.model.advertising.AdvertisingPlacement;
import ru.yandex.webmaster3.core.turbo.model.ban.TurboBanReason;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedInfo;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedItemStatistics;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedType;
import ru.yandex.webmaster3.core.turbo.model.statistics.TurboTotalStatistics;
import ru.yandex.webmaster3.core.util.IdUtils;
import ru.yandex.webmaster3.core.util.URLEncodeUtil;
import ru.yandex.webmaster3.core.util.json.JsonMapping;
import ru.yandex.webmaster3.storage.abt.model.ExperimentInfo;
import ru.yandex.webmaster3.storage.events.data.WMCEvent;
import ru.yandex.webmaster3.storage.events.data.WMCEventContent;
import ru.yandex.webmaster3.storage.events.data.events.UserHostMessageEvent;
import ru.yandex.webmaster3.storage.importanturls.data.ImportantUrlChange;
import ru.yandex.webmaster3.storage.importanturls.data.ImportantUrlStatus;
import ru.yandex.webmaster3.storage.importanturls.data.ImportantUrlsChange;
import ru.yandex.webmaster3.storage.searchurl.samples.data.UrlStatusInfo;
import ru.yandex.webmaster3.storage.user.UserPersonalInfo;
import ru.yandex.webmaster3.storage.user.message.MessageTypeEnum;
import ru.yandex.webmaster3.storage.user.message.content.MessageContent;
import ru.yandex.webmaster3.storage.user.message.iks.IksMessageContent;
import ru.yandex.webmaster3.storage.user.message.iks.IksMessageType;
import ru.yandex.webmaster3.storage.user.notification.NotificationType;
import ru.yandex.webmaster3.storage.video.OfferStatus;
import ru.yandex.webmaster3.worker.notifications.auto.NotificationInfo;
import ru.yandex.webmaster3.worker.notifications.auto.NotificationsTemplateUtil;
import ru.yandex.webmaster3.core.util.http.YandexMimeType;
import ru.yandex.wmtools.common.util.http.YandexHttpStatus;

import static ru.yandex.webmaster3.core.checklist.data.MobileAuditResolution.FAILED_TO_DOWNLOAD_BASE_URL;
import static ru.yandex.webmaster3.core.checklist.data.SiteProblemContent.YaBrowserBadAd.YaBrowserBadAdStatus.ACTIVE;
import static ru.yandex.webmaster3.core.checklist.data.YaBrowserBadAdFormat.DESKTOP_FULLSCR_ONLOAD_COUNT;

public class NotificationTestService {


    public static final Set<NotificationType> NOT_IMPLEMENTED_TYPES = Set.of(
            NotificationType.PERSONAL_SUPPORT,
            NotificationType.DIGEST,
            NotificationType.DIGEST_LITE,
            NotificationType.GLOBAL_NOTIFICATION,
            NotificationType.SITE_PROBLEM_FATAL,
            NotificationType.SITE_PROBLEM_CRITICAL,
            NotificationType.SITE_PROBLEM_POSSIBLE,
            NotificationType.SITE_PROBLEM_RECOMMENDATION,
            NotificationType.TRENDS,
            NotificationType.TURBO_ERROR,
            NotificationType.TURBO_WARNING,
            NotificationType.TURBO_BAN,
            NotificationType.POST_WELCOME_NOTIFICATION,
            // нужно разбираться
            NotificationType.URL_SEARCH_STATUS_CHANGE,
            NotificationType.SEARCH_BASE_UPDATE

    );
    public static final Set<NotificationType> IMPLEMENTED_TYPES = Sets.difference(Set.of(NotificationType.values()),
            NOT_IMPLEMENTED_TYPES);

    private static TurboFeedInfo createFeed(String url, TurboFeedType type) {
        return new TurboFeedInfo(url, null, type, true, TurboFeedInfo.TurboFeedInfoState.UPDATE_ERROR,
                DateTime.now(), DateTime.now(), DateTime.now(), Collections.emptyList(), Collections.emptyList(),
                TurboFeedItemStatistics.EMPTY, TurboTotalStatistics.EMPTY, "", false);
    }

    public String getHtml(NotificationType notificationType, SiteProblemTypeEnum siteProblemTypeEnum) {
        //String hostUrl1 = "https://ворота.рф";
        WebmasterHostId hostId = IdUtils.urlToHostId("http://khaliullin.info:80");
        long userId = 567768960;
        String email = "devnull@yandex-team.ru";
        UserPersonalInfo userPersonalInfo = new UserPersonalInfo(userId, "yndx-robot-webmaster", "robot-webmaster",
                LanguageEnum.DEFAULT_EMAIL_LANGUAGE);
        //SiteProblemContent content = SiteProblemContent;
        //TurboFeedType turboFeedType = TurboFeedType.API;

        return getEventHtml(userId, hostId, notificationType, siteProblemTypeEnum, null, 0, null, null, email,
                userPersonalInfo, null);
    }

    private WMCEvent createTurboEvent(NotificationType notificationType, WebmasterHostId hostId, long userId,
                                      SiteProblemTypeEnum problemType, SiteProblemContent content, boolean repeated) {
        return WMCEvent.create(UserHostMessageEvent.create(hostId, new MessageContent.ChecklistChanges(hostId,
                        problemType, DateTime.now(), DateTime.now(), content, repeated ? 1 : 0),
                notificationType, problemType.getSeverity() == SiteProblemSeverityEnum.CRITICAL ||
                        problemType.getSeverity() == SiteProblemSeverityEnum.FATAL).withUser(userId));
    }

    public WMCEvent getEvent(long userId,
                             WebmasterHostId hostId,
                             NotificationType notificationType,
                             SiteProblemTypeEnum problemType,
                             SearchUrlStatusEnum searchStatus,
                             int httpCode,
                             TurboFeedType feedType,
                             CounterRequestTypeEnum metrikaReqType,
                             ExperimentInfo experimentInfo
    ) {
        return getEvent(userId, hostId, notificationType, problemType, searchStatus, httpCode, feedType,
                metrikaReqType, null, experimentInfo, false);
    }

    public WMCEvent getEvent(long userId,
                             WebmasterHostId hostId,
                             NotificationType notificationType,
                             SiteProblemTypeEnum problemType,
                             SearchUrlStatusEnum searchStatus,
                             int httpCode,
                             TurboFeedType feedType,
                             CounterRequestTypeEnum metrikaReqType,
                             String data,
                             ExperimentInfo experimentInfo,
                             boolean repeated) {
        return getEvent(userId, hostId, notificationType, null, problemType, searchStatus, httpCode, feedType,
                metrikaReqType, data, experimentInfo, repeated);
    }


    @SneakyThrows
    public WMCEvent getEvent(long userId,
                             WebmasterHostId hostId,
                             NotificationType notificationType,
                             MessageTypeEnum messageType,
                             SiteProblemTypeEnum problemType,
                             SearchUrlStatusEnum searchStatus,
                             int httpCode,
                             TurboFeedType feedType,
                             CounterRequestTypeEnum metrikaReqType,
                             String data,
                             ExperimentInfo experimentInfo,
                             boolean repeated
    ) {
        WMCEvent event = null;
        switch (notificationType) {
            case IKS_UPDATE:
                final IksData iksData = JsonMapping.readValue(data, IksData.class);
                if (iksData.messageType == IksMessageType.UPDATE) {
                    event = WMCEvent.create(new UserHostMessageEvent<>(
                            hostId,
                            userId,
                            new MessageContent.IksNewInfo(List.of(hostId, IdUtils.urlToHostId("https://lenta.ru")),
                                    List.of(234L, 444L),
                                    hostId,
                                    new IksMessageContent.IksUpdate(List.of(hostId, IdUtils.urlToHostId("https" +
                                            "://lenta.ru")), List.of(234L, 444L)), IksMessageType.UPDATE, iksData.type),
                            notificationType,
                            false,
                            experimentInfo
                    ));
                } else {
                    event = WMCEvent.create(new UserHostMessageEvent<>(
                            hostId,
                            userId,
                            new MessageContent.IksNewInfo(List.of(hostId, IdUtils.urlToHostId("https://lenta.ru")),
                                    List.of(234L, 444L),
                                    hostId,
                                    new IksMessageContent.IksRival(userId, List.of(hostId.toStringId(),
                                            IdUtils.urlToHostId("https://lenta.ru").toStringId())),
                                    IksMessageType.RIVAL_UPDATE, iksData.type),
                            notificationType,
                            false,
                            experimentInfo
                    ));
                }
                break;
            case UNVERIFIED_HOST_REMOVAL_AFTER_WEEK:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.UnverifiedHostRemovalAfterWeek(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case UNVERIFIED_HOST_REMOVAL_AFTER_THREE_WEEK:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.UnverifiedHostRemovalAfterThreeWeek(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case TURBO_SCC_FAILED:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboSccFailed(hostId),
                        notificationType,
                        true,
                        experimentInfo)
                );
                break;
            case TURBO_SCC_BANNED:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboSccBanned(hostId),
                        notificationType,
                        true,
                        experimentInfo)
                );
                break;
            case TURBO_SCC_PASS:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboSccPass(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case NO_MAIN_MIRROR:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.NoMainMirrors(hostId, IdUtils.urlToHostId("http://a.ru")),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case SITE_REGIONS:
                //todo
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.HostRegionChanged(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case SITE_DISPLAY_NAME:
                //todo
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.HostDisplayNameChanged(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case MAIN_MIRROR_AUTO_ADD:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.AutoAddMainMirror(hostId, hostId, IdUtils.urlToHostId("new.mirror")),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case TURBO_SCC_UNBANNED:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboSccUnbanned(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case RECOMMENDED_QUERIES:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.HostRecommendedOpened(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case SITE_PROBLEM_RECOMMENDATION:
            case SITE_PROBLEM_FATAL:
            case SITE_PROBLEM_CRITICAL:
            case SITE_PROBLEM_POSSIBLE:
            case TURBO_ERROR:
            case TURBO_WARNING:
                if (problemType == null) {
                    throw new RuntimeException("No problem type provided");
                }
                SiteProblemContent content = null;
                switch (problemType) {

                    case DUPLICATE_CONTENT_ATTRS:
                        content = new SiteProblemContent.DuplicateContentAttrs(
                                2454L, 0.156, 3232L, 0.223,
                                feedType == TurboFeedType.RSS ? Collections.emptyList() :
                                        Arrays.asList(
                                                new ContentAttrSampleInfo("Этот заголовок слишком частый", 300L,
                                                        Arrays.asList(
                                                                new PageSampleInfo("/path1", null), new PageSampleInfo(
                                                                        "/path2", null), new PageSampleInfo("/path3",
                                                                        null))),
                                                new ContentAttrSampleInfo("Этот заголовок имеет огромную длину (более" +
                                                        " 500 символов) Ну очень очень очень очень" +
                                                        " очень очень очень очень очень очень очень очень очень очень" +
                                                        " очень очень очень очень очень очень" +
                                                        " очень очень очень очень очень очень очень очень очень очень" +
                                                        " очень очень очень очень очень очень" +
                                                        " очень очень очень очень очень очень очень очень очень очень" +
                                                        " очень очень очень очень очень очень" +
                                                        " большой заголовок", 222L, Arrays.asList(
                                                        new PageSampleInfo("/path4", null), new PageSampleInfo(
                                                                "/path5", null), new PageSampleInfo("/path6", null))),
                                                new ContentAttrSampleInfo("Этот заголовок довольно редкий", 100L,
                                                        Arrays.asList(
                                                                new PageSampleInfo("/path7", null), new PageSampleInfo(
                                                                        "/path8", null), new PageSampleInfo("/path9",
                                                                        null)))
                                        ),
                                feedType == TurboFeedType.YML ? Collections.emptyList() :
                                        Arrays.asList(
                                                new ContentAttrSampleInfo("Этот description слишком частый", 400L,
                                                        Arrays.asList(
                                                                new PageSampleInfo("/path1_d", null),
                                                                new PageSampleInfo(
                                                                        "/path2_d", null), new PageSampleInfo(
                                                                                "/path3_d",
                                                                        null))),
                                                new ContentAttrSampleInfo("Этот description менее частый", 322L,
                                                        Arrays.asList(
                                                                new PageSampleInfo("/path4_d", null),
                                                                new PageSampleInfo(
                                                                        "/path5_d", null), new PageSampleInfo(
                                                                                "/path6_d",
                                                                        null))),
                                                new ContentAttrSampleInfo("Этот description довольно редкий", 111L,
                                                        Arrays.asList(
                                                                new PageSampleInfo("/path7_d", null),
                                                                new PageSampleInfo(
                                                                        "/path8_d", null), new PageSampleInfo(
                                                                                "/path9_d",
                                                                        null)))
                                        )
                        );
                        break;
                    case MORDA_ERROR:
                        content = new SiteProblemContent.MordaError(null,
                                SiteProblemContent.MordaError.ExtendedStatus.DEFAULT,
                                YandexHttpStatus.parseCode(httpCode), false);
                        break;
                    case TURBO_ERROR:
                        content = new SiteProblemContent.TurboError(Lists.newArrayList(
                                createFeed("http://example.com/some-turbo-feed-1", feedType),
                                createFeed("http://khaliullin.info/rss/lint.xml", feedType)
                        ));
                        break;
                    case TURBO_RSS_ERROR:
                        content = new SiteProblemContent.TurboRssError(Lists.newArrayList(
                                createFeed("http://example.com/some-turbo-feed-1", TurboFeedType.RSS),
                                createFeed("http://khaliullin.info/rss/lint.xml", TurboFeedType.RSS)
                        ));
                        break;
                    case TURBO_YML_ERROR:
                        content = new SiteProblemContent.TurboYmlError(Lists.newArrayList(
                                createFeed("http://example.com/some-turbo-feed-1", TurboFeedType.YML),
                                createFeed("http://khaliullin.info/yml/lint.xml", TurboFeedType.YML)
                        ));
                        break;
                    case TURBO_WARNING:
                        content = new SiteProblemContent.TurboWarning(Lists.newArrayList(
                                createFeed("http://example.com/some-turbo-feed-1", feedType),
                                createFeed("http://example.com/some-turbo-feed-2", feedType),
                                createFeed("http://khaliullin.info/rss/lint.xml", feedType)
                        ));
                        break;
                    case TURBO_RSS_WARNING:
                        content = new SiteProblemContent.TurboRssWarning(Lists.newArrayList(
                                createFeed("http://example.com/some-turbo-feed-1", TurboFeedType.RSS),
                                createFeed("http://example.com/some-turbo-feed-2", TurboFeedType.RSS),
                                createFeed("http://khaliullin.info/rss/lint.xml", TurboFeedType.RSS)
                        ));
                        break;
                    case TURBO_YML_WARNING:
                        content = new SiteProblemContent.TurboYmlWarning(Lists.newArrayList(
                                createFeed("http://example.com/some-turbo-feed-1", TurboFeedType.YML),
                                createFeed("http://example.com/some-turbo-feed-2", TurboFeedType.YML),
                                createFeed("http://khaliullin.info/rss/lint.xml", TurboFeedType.YML)
                        ));
                        break;
                    case TURBO_FEED_BAN:
                        content = new SiteProblemContent.TurboFeedBan(false,
                                Collections.singleton(TurboBanReason.ADULT),
                                DateTime.now(), Arrays.asList("http://example.com/some-turbo-feed-2"));
                        break;
                    case TURBO_DOCUMENT_BAN:
                        content = new SiteProblemContent.TurboDocumentBan(true,
                                Collections.singleton(TurboBanReason.BADCONTENT),
                                DateTime.now(), 222, Collections.emptyList());
                        break;
                    case TURBO_HOST_BAN:
                        SiteProblemContent.TurboHostBan.TurboHostBanSeverity severity;
                        if (httpCode == 200) {
                            severity = SiteProblemContent.TurboHostBan.TurboHostBanSeverity.WARNING;
                        } else {
                            severity = SiteProblemContent.TurboHostBan.TurboHostBanSeverity.BAN;
                        }
                        content = new SiteProblemContent.TurboHostBan(severity, 0L);
                        break;
                    case TURBO_HOST_BAN_INFO:
                        content =
                                new SiteProblemContent.TurboHostBanInfo(SiteProblemContent.TurboHostBan.TurboHostBanSeverity.INFO, null);
                        break;
                    case TURBO_INSUFFICIENT_CLICKS_SHARE:
                        content = new SiteProblemContent.TurboInsufficientClicksShare(73);
                        break;
                    case HOST_COMPANY_PROFILE_NOT_FILLED: {
                        //WebmasterHostId hostId = new WebmasterHostId(WebmasterHostId.Schema.HTTP, "lenta.ru", 80);
                        List<CompanyInfo> companyInfos = new ArrayList<>();
                        companyInfos.add(new CompanyInfo(123, "Company1", "Россия, Москва, ул.Льва Толстого д.16"));
                        companyInfos.add(new CompanyInfo(1234, "Company2", "Россия, Санкт-Петербург, Пискаревский " +
                                "пр-т, д.2к2 Щ"));
                        companyInfos.add(new CompanyInfo(12345, "Company3", "Россия, Омская область, на деревню " +
                                "дедушке"));
                        companyInfos.add(new CompanyInfo(123456, "Company4", "Россия, Омская область, на деревню " +
                                "бабушке"));
                        content = new SiteProblemContent.HostCompanyProfileNotFilled(hostId, companyInfos);
                        break;
                    }
                    case TOO_MANY_DOMAINS_ON_SEARCH: {
                        List<String> subdomains = Arrays.asList(
                                "m.lenta.ru",
                                "0.m.lenta.ru",
                                "m.www.lenta.ru",
                                "foo.bar.lenta.ru"
                        );
                        content = new SiteProblemContent.TooManyDomainsOnSearch(subdomains);
                        break;
                    }
                    case HOST_COMPANY_PROFILE_CREATED:
                        content = new SiteProblemContent.HostCompanyProfileCreated("https://yandex" +
                                ".ru/sprav/1611673/edit?utm_source=webmaster_not_active");
                        break;
                    case TURBO_URL_ERRORS:
                        content = new SiteProblemContent.TurboUrlErrors(10, 1000);
                        break;
                    case TURBO_INVALID_CART_URL:
                        content =
                                new SiteProblemContent.TurboInvalidCartUrl(SiteProblemContent.TurboInvalidCartUrl.CartUrlStatus.ERROR_NOT_CART);
                        break;

                    case INSIGNIFICANT_CGI_PARAMETER:
                        content = new SiteProblemContent.InsignificantCGIParameter(
                                Map.of(
                                        "test", List.of("/exp1?test=123", "/exp2?test=333"),
                                        "test_2", List.of("/exp3?test_2=-1")
                                )
                        );
                        break;

                    case SLOW_AVG_RESPONSE:
                        content = new SiteProblemContent.SlowResponse(4000);
                        break;
                    case SLOW_AVG_RESPONSE_WITH_EXAMPLES:
                        content = new SiteProblemContent.SlowResponseWithExamples(4000,
                                List.of(new SlowUrlSampleInfo("/123", DateTime.now().getMillis(), 4000L)));
                        break;
                    case DOMAIN_EXPIRES:
                        content = new SiteProblemContent.DomainNameExpires(DateTime.now(), DateTime.now());
                        break;
                    case MORDA_REDIRECTS:
                        content = new SiteProblemContent.MordaRedirects(DateTime.now(), IdUtils.urlToHostId("lenta" +
                                ".ru").getPunycodeHostname());
                        break;
                    case NO_SITEMAP_MODIFICATIONS:
                        content = new SiteProblemContent.NoSitemapModifications(DateTime.now());
                        break;
                    case NOT_MOBILE_FRIENDLY:
                        int state = JsonMapping.readValue(data, NotMobileFriendlyState.class).state;
                        content = new SiteProblemContent.NotMobileFriendly(FAILED_TO_DOWNLOAD_BASE_URL, state);
                        break;
                    case SANCTIONS:
                        content = new SiteProblemContent.SanctionsProblem(hostId);
                        break;
                    case TOO_MANY_URL_DUPLICATES:
                        content = new SiteProblemContent.TooManyUrlDuplicates(DateTime.now(), 20);
                        break;
                    case YABROWSER_BADAD:
                        content = new SiteProblemContent.YaBrowserBadAd(DateTime.now(), 1L, DateTime.now(), ACTIVE,
                                EnumSet.of(DESKTOP_FULLSCR_ONLOAD_COUNT));
                        break;
                    case DUPLICATE_PAGES:
                        content = new SiteProblemContent.DuplicatePages(100, 0.4, Arrays.asList(
                                new PageSampleInfo("/path1_d", null, "https://examples.com/123"),
                                new PageSampleInfo("/path2_d", null, "https://examples.com/234"),
                                new PageSampleInfo("/path3_d", null, "https://examples.com/345")
                        ));
                        break;
                    case URL_ALERT_4XX:
                        content = new SiteProblemContent.UrlAlert4xx(1000);
                        break;
                    case URL_ALERT_5XX:
                        content = new SiteProblemContent.UrlAlert5xx(1000);
                        break;
                    case ERRORS_IN_SITEMAPS:
                        content = new SiteProblemContent.ErrorsInSitemaps(Arrays.asList(
                                SitemapInfo.builder().id(UUID.randomUUID()).parentId(UUID.randomUUID()).url("https" +
                                        "://example.com/sitemap.xml").build()
                        ));
                        break;
                    case VIDEOHOST_OFFER_IS_NEEDED:
                        content = new SiteProblemContent.VideohostOfferIsNeeded();
                        break;
                    case VIDEOHOST_OFFER_FAILED:
                        content = new SiteProblemContent.VideohostOfferFailed("https://example.com/offer");
                        break;
                    case VIDEOHOST_OFFER_NEED_PAPER:
                        content = new SiteProblemContent.VideohostOfferNeedPaper();
                        break;
                    default:
                        // Проблемы у которых контент с пустым конструктором строятся тут, рефлексия все такое ...
                        content = problemType.getDataClass().getConstructor().newInstance();
                }

                event = WMCEvent.create(
                        UserHostMessageEvent.create(hostId,
                                        new MessageContent.ChecklistChanges(hostId,
                                                problemType,
                                                DateTime.now(), DateTime.now().minusDays(3),
                                                content, repeated ? 1 : 0),
                                        notificationType, problemType.isCriticalSeverity())
                                .withUser(userId));
                break;

            //todo
            case SEARCH_BASE_UPDATE:
                String hostUrl1 = "https://ворота.рф";
                String hostUrl2 = IdUtils.hostIdToReadableUrl(hostId);
                MessageContent messageContent = null;
                if (problemType == null) {
                    // костыль для отправки уведомления в сервисе
                    messageContent = /*new MessageContent.SearchBaseUpdateNewAllUserHosts(DateTime.now(),
                            Arrays.asList(*/
                            new MessageContent.SearchBaseUpdateNew(DateTime.now(),
                                    hostId, 423, 7, 123,
                                    Lists.newArrayList(hostUrl2, hostUrl2 + URLEncodeUtil.prettifyUrl("/some-test-url"
                                    )),
                                    Lists.newArrayList(hostUrl2, hostUrl2 + URLEncodeUtil.prettifyUrl("/some?param" +
                                            "=[xx]")))
                    //)
                    //);
                    ;
                } else {
                    messageContent = new MessageContent.SearchBaseUpdateNewAllUserHosts(DateTime.now(),
                            Arrays.asList(
                                    new MessageContent.SearchBaseUpdateNew(DateTime.now(),
                                            IdUtils.urlToHostId(hostUrl1), 100, 10, 11,
                                            Lists.newArrayList(hostUrl1, hostUrl1 + URLEncodeUtil.prettifyUrl("/%D0" +
                                                    "%BB%D1%8E%D0%B4%D0%B8/2464429-%D0%B1%D0%B0%D0%B8%D1%80%D0%BE%D0" +
                                                    "%B2_%D0%B0%D0%BB%D0%B5%D0%BA%D1%81%D0%B0%D0%BD%D0%B4%D1%80_%D1" +
                                                    "%81%D0%B5%D1%80%D0%B3%D0%B5%D0%B5%D0%B2%D0%B8%D1%87/")),
                                            Lists.newArrayList(hostUrl1, hostUrl1 + URLEncodeUtil.prettifyUrl(
                                                    "/вылщсыщ"))
                                    ),
                                    new MessageContent.SearchBaseUpdateNew(DateTime.now(),
                                            hostId, 423, 7, 123,
                                            Lists.newArrayList(hostUrl2, hostUrl2 + URLEncodeUtil.prettifyUrl("/some" +
                                                    "-test-url")),
                                            Lists.newArrayList(hostUrl2, hostUrl2 + URLEncodeUtil.prettifyUrl("/some" +
                                                    "?param=[xx]"))
                                    )
                            ));
                }

                event = WMCEvent.create(UserHostMessageEvent.create(hostId, messageContent, notificationType, false).withUser(userId));
                break;

            case SERP_LINKS_UPDATE:
                event = WMCEvent.create(UserHostMessageEvent.create(
                        hostId,
                        new MessageContent.SerpLinksUpdate("section1",
                                true,
                                Lists.newArrayList("https://lenta.ru/1", "https://lenta.ru/2"),
                                Lists.newArrayList("https://lenta.ru/3", "https://lenta.ru/4"),
                                Collections.emptyList()
                        ),
                        notificationType,
                        false
                ).withUser(userId));
                break;

            case IMPORTANT_URLS_AUTO_ADD:
                event = WMCEvent.create(UserHostMessageEvent.create(
                        hostId,
                        new MessageContent.AutoAddedImportantUrls(hostId, List.of("/", "/2", "/ping")),
                        notificationType,
                        false
                ).withUser(userId));
                break;

            case URL_TITLE_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.TitleChangeAllHostPages(
                                hostId,
                                Arrays.asList(
                                        new ImportantUrlChange.TitleChange(
                                                hostId,
                                                "/some-test-page",
                                                "Some old title",
                                                "Some new title"
                                        ),
                                        new ImportantUrlChange.TitleChange(
                                                hostId,
                                                "/some-other-test-page",
                                                "Some old title 2",
                                                "Some new title 2"
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case URL_DESCRIPTION_CHANGE: {
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.DescriptionChangeAllHostPages(
                                hostId,
                                Arrays.asList(
                                        new ImportantUrlChange.DescriptionChange(
                                                hostId,
                                                "/some-test-page",
                                                "Some old description",
                                                "Some new description"
                                        ),
                                        new ImportantUrlChange.DescriptionChange(
                                                hostId,
                                                "/some-other-test-page",
                                                "Some old description 2",
                                                "Some new description 2"
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            }
            case URL_REL_CANONICAL_TARGET_CHANGE: {
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.RelCanonicalTargetChangeAllHostPages(
                                hostId,
                                Arrays.asList(
                                        new ImportantUrlChange.RelCanonicalTargetChange(
                                                hostId,
                                                "/some-test-page",
                                                IdUtils.hostIdToUrl(hostId) + "/old-canonical1",
                                                IdUtils.hostIdToUrl(hostId) + "/new-canonical1"
                                        ),
                                        new ImportantUrlChange.RelCanonicalTargetChange(
                                                hostId,
                                                "/some-other-test-page",
                                                IdUtils.hostIdToUrl(hostId) + "/old-canonical2",
                                                IdUtils.hostIdToUrl(hostId) + "/new-canonical2"
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            }
            case URL_INDEXING_LAST_ACCESS_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.IndexingLastAccessChangeAllHostPages(
                                hostId,
                                DateTime.now().minusHours(1),
                                Arrays.asList(
                                        new ImportantUrlChange.IndexingLastAccessChange(
                                                hostId,
                                                "/some-test-page",
                                                DateTime.now().minusHours(33),
                                                DateTime.now().minusHours(1)
                                        ),
                                        new ImportantUrlChange.IndexingLastAccessChange(
                                                hostId,
                                                "/some-other-test-page",
                                                DateTime.now().minusHours(33),
                                                DateTime.now().minusHours(1)
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;

            case URL_INDEXING_STATUS_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.HttpCodeChangeAllHostPages(
                                hostId,
                                Arrays.asList(
                                        new ImportantUrlChange.HttpCodeChange(
                                                hostId,
                                                "/some-test-page",
                                                HttpCodeInfo.fromHttpStatus(YandexHttpStatus.HTTP_404_NOT_FOUND),
                                                HttpCodeInfo.fromHttpStatus(YandexHttpStatus.HTTP_200_OK)
                                        ),
                                        new ImportantUrlChange.HttpCodeChange(
                                                hostId,
                                                "/some-other-test-page",
                                                HttpCodeInfo.fromHttpStatus(YandexHttpStatus.HTTP_500_INTERNAL_SERVER_ERROR),
                                                HttpCodeInfo.fromHttpStatus(YandexHttpStatus.HTTP_200_OK)
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;

            case URL_SEARCH_LAST_ACCESS_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.SearchLastAccessChangeAllHostPages(
                                hostId,
                                DateTime.now().minusHours(1),
                                Arrays.asList(
                                        new ImportantUrlChange.SearchLastAccessChange(
                                                hostId,
                                                "/some-test-page",
                                                DateTime.now().minusDays(1),
                                                DateTime.now().minusHours(1)
                                        ),
                                        new ImportantUrlChange.SearchLastAccessChange(
                                                hostId,
                                                "/some-other-test-page",
                                                null,
                                                DateTime.now().minusHours(1)
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;

            //todo
            case URL_SEARCH_STATUS_CHANGE: {
                UrlStatusInfo oldStatusInfo = new UrlStatusInfo(
                        SearchUrlStatusEnum.INDEXED_SEARCHABLE, DateTime.now().minusDays(1), "/beauty/url",
                        300, null, null,
                        "/redirect/target", "/rel/canonical", "Some description",
                        false, false, false, false, false);
                UrlStatusInfo newStatusInfo = new UrlStatusInfo(
                        searchStatus, DateTime.now().minusDays(1), "/beauty/url",
                        300, null, null,
                        "/redirect/target", "/rel/canonical", "Some description",
                        false, false, false, false, false);
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new ImportantUrlsChange.SearchUrlStatusChangeAllHostPages(
                                hostId,
                                Arrays.asList(
                                        new ImportantUrlChange.SearchUrlStatusChange(
                                                hostId,
                                                "/some-test-page",
                                                new ImportantUrlStatus.SearchInfo(200, DateTime.now().minusDays(10),
                                                        YandexMimeType.MIME_HTML, oldStatusInfo),
                                                new ImportantUrlStatus.SearchInfo(300, DateTime.now().minusDays(1),
                                                        YandexMimeType.UNKNOWN, newStatusInfo)
                                        ),
                                        new ImportantUrlChange.SearchUrlStatusChange(
                                                hostId,
                                                "/some-other-test-page-с-русскими-буквами",
                                                new ImportantUrlStatus.SearchInfo(200, DateTime.now().minusDays(10),
                                                        YandexMimeType.MIME_HTML, oldStatusInfo),
                                                new ImportantUrlStatus.SearchInfo(300, DateTime.now().minusDays(1),
                                                        YandexMimeType.UNKNOWN, newStatusInfo)
                                        )
                                )
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            }
            case SITE_ACCESS:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.HostAccessLost(
                                hostId
                        ),
                        notificationType,
                        false,
                        experimentInfo
                ));
                break;
            case TURBO_NEW:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboAutoparsedPagesAppeared(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case TURBO_LISTINGS_NEW:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboListingsAvailable(hostId),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case ROBOTS_TXT_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.RobotsTxtChange(hostId, DateTime.now()),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case NEW_DOMAINS_NOTIFICATION:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.NewDomainsNotification(hostId, Arrays.asList(
                                "http://abc.example.com", "http://foo.example.com",
                                "http://bar.example.com", "http://foobar.example.com"
                        )),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            //todo
            case METRIKA_COUNTERS:
                switch (metrikaReqType) {
                    case CREATE:
                        event = WMCEvent.create(new UserHostMessageEvent<>(
                                hostId,
                                userId,
                                new MessageContent.HostMetrikaCounterBindingRequest(
                                        hostId,
                                        123456L
                                ),
                                notificationType,
                                false,
                                experimentInfo)
                        );
                        break;
                    case CANCEL:
                        event = WMCEvent.create(new UserHostMessageEvent<>(
                                hostId,
                                userId,
                                new MessageContent.HostMetrikaCounterBindingRequestCancelled(
                                        hostId,
                                        123456L
                                ),
                                notificationType,
                                false,
                                experimentInfo)
                        );
                        break;
                    case DISMISS:
                        event = WMCEvent.create(new UserHostMessageEvent<>(
                                hostId,
                                userId,
                                new MessageContent.HostMetrikaCounterBindingDeleted(
                                        hostId,
                                        123456L,
                                        "andreyhaliullin"
                                ),
                                notificationType,
                                false,
                                experimentInfo)
                        );
                        break;
                }

                break;

            case METRIKA_COUNTER_CRAWL:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.HostMetrikaCounterCrawlSuspended(
                                hostId,
                                123456L
                        ),
                        notificationType,
                        false,
                        experimentInfo)
                );

                break;
            case TURBO_ADV_SETTINGS_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboAdvSettingsChanged(
                                hostId,
                                TurboPlatform.MOBILE, AdvertisingPlacement.TOP),
                        notificationType,
                        false,
                        experimentInfo)
                );
                break;
            case TURBO_COMMERCE_SETTINGS_CHANGE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.TurboCommerceSettingsChanged(hostId),
                        notificationType,
                        false)
                );
                break;
            case MAIN_MIRROR_UPDATE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.MainMirrorChanged(hostId, IdUtils.urlToHostId("https://test.net"), hostId),
                        notificationType,
                        false,
                        experimentInfo
                ));
                break;
            case NEW_REVIEW_AVAILABLE:
                event = WMCEvent.create(new UserHostMessageEvent<>(
                        hostId,
                        userId,
                        new MessageContent.NewReviewAvailable(
                                hostId,
                                Arrays.asList("test1", "test2"),
                                4,
                                10,
                                data
                        ),
                        notificationType,
                        false,
                        experimentInfo
                ));
                break;
            case VIDEOHOST_OFFER:
                OfferStatus offerStatus = JsonMapping.readValue(data, OfferData.class).offerStatus;
                switch (offerStatus) {
                    case CONFIRMED -> event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.VideohostOfferConfirmed(
                                    hostId,
                                    "https://example.com/offer"
                            ),
                            notificationType,
                            false
                    ).withUser(userId));
                    case HAS_PAPER -> event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.VideohostOfferHasPaper(hostId),
                            notificationType,
                            false
                    ).withUser(userId));
                    case REDUNDANT -> event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.VideohostOfferRedundant(hostId),
                            notificationType,
                            false
                    ).withUser(userId));
                }
            case FEEDS_INFO:
                if (messageType == MessageTypeEnum.FEEDS_SCC_BANNED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsSccBanned(hostId, "http://abc.com/feed.yml"),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_SCC_FAILED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsSccFailed(hostId, List.of("http://abc.com/feed.yml", "http://abc.com/feed2.yml"), repeated ? 1 : 0),
                            notificationType,
                            false
                    ).withUser(userId));
                }else if (messageType == MessageTypeEnum.FEEDS_PINGER_DISABLE) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsPingerDisable(hostId, "http://abc.com/feed.yml"),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_PINGER_ENABLE) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsPingerEnable(hostId, "http://abc.com/feed.yml"),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_VALIDATION_FAILED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsValidationFailed(hostId, List.of("http://abc.com/feed.yml", "http://abc.com/feed2.yml"), repeated ? 1 : 0),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_DEFECT_RATE_FAILED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsDefectRateFailed(hostId, repeated ? FeedsErrorSeverity.FATAL : FeedsErrorSeverity.WARNING),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_SCC_PASSED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsSccPassed(hostId, List.of("http://abc.com/feed.yml")),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_VALIDATION_FAILED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsValidationFailed(hostId, List.of("http://abc.com/feed.yml", "http://abc.com/feed2.yml"), repeated ? 1 : 0),
                            notificationType,
                            false
                    ).withUser(userId));
                } else if (messageType == MessageTypeEnum.FEEDS_DEFECT_RATE_FAILED) {
                    event = WMCEvent.create(UserHostMessageEvent.create(
                            hostId,
                            new MessageContent.FeedsDefectRateFailed(hostId, repeated ? FeedsErrorSeverity.FATAL : FeedsErrorSeverity.WARNING),
                            notificationType,
                            false
                    ).withUser(userId));
                }
                break;
            case NCA_CERTIFICATE:
                event = WMCEvent.create(UserHostMessageEvent.create(
                        new WebmasterHostId(WebmasterHostId.Schema.HTTPS, "sberbank.ru", 443),
                        new MessageContent.NcaCtlogCertificate(hostId, "ct-agate.yandex.net/2023/", 21),
                        notificationType,
                        false
                ).withUser(userId));
                break;
        }

        return event;
    }

    public String getEventHtml(long userId,
                               WebmasterHostId hostId,
                               NotificationType notificationType,
                               SiteProblemTypeEnum problemType,
                               SearchUrlStatusEnum searchStatus,
                               int httpCode,
                               TurboFeedType feedType,
                               CounterRequestTypeEnum metrikaReqType,
                               String email,
                               UserPersonalInfo userPersonalInfo,
                               ExperimentInfo experimentInfo

    ) {
        WMCEvent event = getEvent(userId, hostId, notificationType, problemType, searchStatus, httpCode, feedType,
                metrikaReqType, experimentInfo);
        WMCEventContent eventContent = event.getContent();
        if (!(eventContent instanceof UserHostMessageEvent)) {
            return "Not implemented";
        }

        UserHostMessageEvent userHostMessageEvent = (UserHostMessageEvent) eventContent;
        NotificationInfo notificationInfo = NotificationInfo.builder()
                .email(email)
                .hostId(hostId)
                .userId(userId)
                .personalInfo(userPersonalInfo)
                .messageContent(userHostMessageEvent.getMessageContent())
                .build();
        NotificationsTemplateUtil.EmailContent emailContent =
                NotificationsTemplateUtil.createEmailContent(notificationInfo);
        return emailContent.getBody();
    }

    @Value
    public static class IksData {
        @JsonProperty("messageType")
        IksMessageType messageType;
        @JsonProperty("type")
        String type;
    }

    private record OfferData(@JsonProperty("offerStatus") OfferStatus offerStatus) {
    }

    private record NotMobileFriendlyState(@JsonProperty("state") int state) { }
}
