package ru.yandex.webmaster3.worker.user;

import java.util.Optional;

import lombok.RequiredArgsConstructor;
import org.joda.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.blackbox.service.BlackboxUsersService;
import ru.yandex.webmaster3.core.data.L10nEnum;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.notification.LanguageEnum;
import ru.yandex.webmaster3.core.util.RetryUtils;
import ru.yandex.webmaster3.storage.events.data.WMCEvent;
import ru.yandex.webmaster3.storage.events.data.WMCEventContent;
import ru.yandex.webmaster3.storage.events.data.events.DelegationToNotUserEvent;
import ru.yandex.webmaster3.storage.events.service.WMCEventsObserver;
import ru.yandex.webmaster3.storage.notifications.NotificationChannel;
import ru.yandex.webmaster3.storage.notifications.dao.TokensForUnsubscribeYDao;
import ru.yandex.webmaster3.storage.notifications.service.UserNotificationSettingsService;
import ru.yandex.webmaster3.storage.user.UserPersonalInfo;
import ru.yandex.webmaster3.storage.user.message.content.MessageContent;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.worker.notifications.auto.AutoNotificationsSenderService;
import ru.yandex.webmaster3.worker.notifications.auto.NotificationInfo;

/**
 * Created by ifilippov5 on 01.03.18.
 */
@Component
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class DelegationToNotUserEventObserver implements WMCEventsObserver {
    private final AutoNotificationsSenderService autoNotificationsSenderService;
    private final BlackboxUsersService blackboxExternalYandexUsersService;
    private final UserNotificationSettingsService userNotificationSettingsService;
    private final TokensForUnsubscribeYDao tokensForUnsubscribeYDao;


    @Override
    public boolean observe(WMCEvent event) {
        WMCEventContent content = event.getContent();
        if (!(content instanceof DelegationToNotUserEvent)) {
            return false;
        }

        DelegationToNotUserEvent delegationToNotUserEvent = (DelegationToNotUserEvent) content;
        MessageContent.HostAccessDelegatedToNotUser messageContent =
                (MessageContent.HostAccessDelegatedToNotUser) delegationToNotUserEvent.getMessageContent();

        long userId = delegationToNotUserEvent.getUserId();

        String email = userNotificationSettingsService.getUserEmailOrDefaultIfEmpty(userId);
        if (email == null) {
            return false;
        }

        String token = messageContent.getToken();
        try {
            RetryUtils.execute(RetryUtils.linearBackoff(5, Duration.standardMinutes(2)), () -> {
                tokensForUnsubscribeYDao.insert(token, userId, event.getId());
            });
        } catch (WebmasterYdbException | InterruptedException e) {
            throw new WebmasterException("Failed to insert token",
                    new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
        }
        final NotificationInfo notificationInfo = NotificationInfo.builder()
                .id(event.getId())
                .email(email)
                .userId(userId)
                .personalInfo(getPersonalInfo(userId))
                .messageContent(messageContent)
                .channel(NotificationChannel.EMAIL)
                .critical(delegationToNotUserEvent.isCritical())
                .build();
        autoNotificationsSenderService.sendMessage(notificationInfo);

        return true;
    }

    private UserPersonalInfo getPersonalInfo(long userId) {
        String login = blackboxExternalYandexUsersService.getUserById(userId).getLogin();
        LanguageEnum language = LanguageEnum.RU;
        Optional<L10nEnum> langOpt = blackboxExternalYandexUsersService.getUserLanguage(userId);
        if (langOpt.isPresent()) {
            switch (langOpt.get()) {
                case RU:
                    break;
                case UK:
                    break;
                default:
                    language = LanguageEnum.EN;
            }
        }
        return new UserPersonalInfo(userId, login, login, language);
    }
}
