package ru.yandex.webmaster3.worker.notifications.sending;

import java.util.List;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.TimeUnit;

import com.datastax.driver.core.utils.UUIDs;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.Duration;
import org.springframework.beans.factory.annotation.Required;

import ru.yandex.webmaster3.storage.notifications.NotificationChannel;
import ru.yandex.webmaster3.storage.notifications.NotificationRecListId;
import ru.yandex.webmaster3.storage.notifications.SearchBaseNotificationInfo;
import ru.yandex.webmaster3.storage.notifications.dao.PreparedGlobalMessageInfo;
import ru.yandex.webmaster3.storage.notifications.dao.SearchBaseNotificationListCHDao;
import ru.yandex.webmaster3.storage.notifications.dao.SearchBaseNotificationsYDao;
import ru.yandex.webmaster3.storage.user.UserPersonalInfo;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseException;
import ru.yandex.webmaster3.worker.notifications.auto.AutoNotificationsSenderService;
import ru.yandex.webmaster3.worker.notifications.auto.NotificationInfo;

/**
 * @author avhaliullin
 */
@Slf4j
@Setter
public class SendSearchBaseNotificationTask extends AbstractSendNotificationsTask<SearchBaseNotificationInfo, PreparedGlobalMessageInfo> {
    private static final Duration TTL = Duration.standardDays(7);
    private static final long ZK_RECORD_MAX_AGE = TimeUnit.DAYS.toMillis(1L);

    private SearchBaseNotificationListCHDao searchBaseNotificationListCHDao;
    private SearchBaseNotificationsYDao searchBaseNotificationsYDao;
    private AutoNotificationsSenderService autoNotificationsSenderService;

    public SendSearchBaseNotificationTask() {
        super("base-notify");
    }

    @Override
    protected SearchBaseNotificationInfo getNotificationMarkStarted(UUID notificationId, int revisionId) {
        SearchBaseNotificationInfo result = searchBaseNotificationsYDao.getNotificationInfo(notificationId);
        if (result == null) {
            throw new RuntimeException("Should never happen: auto notification not found for " + notificationId);
        }
        if (!result.isSending()) {
                searchBaseNotificationsYDao.updateNotification(result.withSending(true), TTL);
        }
        return result;
    }

    @Override
    protected boolean canBeDeleted(UUID notificationId) {
        SearchBaseNotificationInfo result = searchBaseNotificationsYDao.getNotificationInfo(notificationId);
        if (result == null) {
            // TTL - removing from zk
            return true;
        }
        if (result.getRecListId() != null && result.isSending()) {
            return (System.currentTimeMillis() - UUIDs.unixTimestamp(result.getRecListId())) > ZK_RECORD_MAX_AGE;
        }
        return false;
    }

    @Override
    protected UUID getRecListId(SearchBaseNotificationInfo searchBaseNotificationInfo) {
        return searchBaseNotificationInfo.getRecListId();
    }

    @Override
    protected boolean sendToTargetByChannel(SearchBaseNotificationInfo searchBaseNotificationInfo, PreparedGlobalMessageInfo preparedSearchBaseMessageInfo, NotificationChannel channel) {
        final NotificationInfo buildNotificationInfo = NotificationInfo.builder()
                .id(searchBaseNotificationInfo.getNotificationId())
                .email(preparedSearchBaseMessageInfo.getEmail())
                .hostId(preparedSearchBaseMessageInfo.getHostId())
                .userId(preparedSearchBaseMessageInfo.getUserId())
                .personalInfo(new UserPersonalInfo(
                        preparedSearchBaseMessageInfo.getUserId(),
                        preparedSearchBaseMessageInfo.getLogin(),
                        preparedSearchBaseMessageInfo.getFio(),
                        preparedSearchBaseMessageInfo.getLang()
                ))
                .messageContent(preparedSearchBaseMessageInfo.getMessage())
                .channel(channel)
                .critical(false)
                .build();
        return autoNotificationsSenderService.sendMessage(buildNotificationInfo);
    }

    @Override
    protected void finishNotification(UUID notificationId) {
    }

    @Override
    protected List<PreparedGlobalMessageInfo> listTargets(NotificationRecListId listId, int fromOffset, int limit) throws ClickhouseException {
        return searchBaseNotificationListCHDao.getMessages(listId, fromOffset, limit);
    }

    @Override
    protected String extractTargetId(PreparedGlobalMessageInfo target) {
        return String.format("%d;%s;%s;%d", target.getUserId(), target.getHostId(), target.getPath(), target.getMessage().getType().value());
    }

    @Override
    protected Set<NotificationChannel> extractTargetChannels(PreparedGlobalMessageInfo target) {
        return target.getChannels();
    }

    @Required
    public void setWorkerThreads(int workerThreads) {
        this.workerThreads = workerThreads;
    }
}
