package ru.yandex.webmaster3.worker.recommendedquery;

import lombok.RequiredArgsConstructor;
import org.apache.commons.lang3.mutable.Mutable;
import org.apache.commons.lang3.mutable.MutableObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskState;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskType;
import ru.yandex.webmaster3.core.worker.task.TaskResult;
import ru.yandex.webmaster3.storage.events.data.WMCEventContent;
import ru.yandex.webmaster3.storage.events.data.events.RetranslateToUsersEvent;
import ru.yandex.webmaster3.storage.events.data.events.UserHostMessageEvent;
import ru.yandex.webmaster3.storage.events.service.WMCEventsService;
import ru.yandex.webmaster3.storage.recommendedquery.dao.HostsWaitFirstRecommendedYDao;
import ru.yandex.webmaster3.storage.recommendedquery.dao.RecommendedQueriesCHDao;
import ru.yandex.webmaster3.storage.user.message.content.MessageContent;
import ru.yandex.webmaster3.storage.user.notification.NotificationType;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseException;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

/**
 * Created by ifilippov5 on 28.12.17.
 */
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class SendNotificationsAboutOpenRecommendedPeriodicTask extends PeriodicTask<SendNotificationsAboutOpenRecommendedPeriodicTask.TaskState> {
    private static final Logger log = LoggerFactory.getLogger(SendNotificationsAboutOpenRecommendedPeriodicTask.class);

    private final HostsWaitFirstRecommendedYDao hostsWaitFirstRecommendedYDao;
    private final RecommendedQueriesCHDao mdbRecommendedQueriesCHDao;
    private final WMCEventsService wmcEventsService;

    @Override
    public Result run(UUID runId) throws Exception {
        List<WebmasterHostId> hostsSent = new ArrayList<>();
        Mutable<ClickhouseException> chEx = new MutableObject<>(null);
        List<WMCEventContent> events = new ArrayList<>();

        hostsWaitFirstRecommendedYDao.forEachHost(hostId -> {
            boolean queriesExist = false;
            try {
                queriesExist = mdbRecommendedQueriesCHDao.exist(hostId, RecommendedQueriesCHDao.Include.REGULAR);
            } catch (ClickhouseException e) {
                log.error("Failed to get any recommended query", e);
                chEx.setValue(e); //так как запросы будут поступать на разные шарды, отложим исключение
            }
            if (queriesExist) {
                events.add(new RetranslateToUsersEvent<>(
                                new UserHostMessageEvent<>(
                                        hostId,
                                        null,
                                        new MessageContent.HostRecommendedOpened(
                                                hostId),
                                        NotificationType.RECOMMENDED_QUERIES,
                                        false)
                        )
                );
                hostsSent.add(hostId);
            }
        });

        hostsWaitFirstRecommendedYDao.deleteHosts(hostsSent);
        wmcEventsService.addEventContents(events);

        if (chEx.getValue() != null) {
            throw new WebmasterException("Failed to get any recommended query",
                    new WebmasterErrorResponse.ClickhouseErrorResponse(getClass(), null, chEx.getValue()), chEx.getValue());
        }

        return new Result(TaskResult.SUCCESS);
    }

    @Override
    public PeriodicTaskType getType() {
        return PeriodicTaskType.SEND_NOTIFICATIONS_ABOUT_OPEN_RECOMMENDED;
    }

    @Override
    public TaskSchedule getSchedule() {
        return TaskSchedule.startByCron("0 0 7-18 * * *");
    }

    public static class TaskState implements PeriodicTaskState {
    }
}
