package ru.yandex.webmaster3.worker.video;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonProperty;
import com.google.common.collect.Range;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

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.util.IdUtils;
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.checklist.service.SiteProblemsService;
import ru.yandex.webmaster3.storage.util.yt.AsyncTableReader;
import ru.yandex.webmaster3.storage.util.yt.YtException;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.util.yt.YtService;
import ru.yandex.webmaster3.storage.util.yt.YtTableReadDriver;
import ru.yandex.webmaster3.storage.video.VideohostOfferService;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

/**
 * @author vsedaikina
 * 08.11.21
 */

@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Component
public class NotifyVideohostOfferIsNeededPeriodicTask extends PeriodicTask<NotifyVideohostOfferIsNeededPeriodicTask.TaskState> {
    private final YtService ytService;
    private final VideohostOfferService videohostOfferService;
    @Value("${webmaster3.worker.video.upload.videohost_to_alert.path}")
    private final YtPath alertedVideohosts;

    @Override
    public Result run(UUID runId) throws Exception {
        log.info("Notify videohost owners without an offer");

        Set<WebmasterHostId> alertedHosts = new HashSet<>();
        ytService.withoutTransaction(cypressService -> {
            AsyncTableReader<YtRow> tableReader = new AsyncTableReader<>(
                    cypressService, alertedVideohosts, Range.all(),
                    YtTableReadDriver.createYSONDriver(YtRow.class)
            );

            int count = 0;
            try (AsyncTableReader.TableIterator<YtRow> iterator = tableReader.read()) {
                while (iterator.hasNext()) {
                    count++;
                    YtRow row = iterator.next();
                    if (row.hostUrl != null) {
                        if (videohostOfferService.isDomainInWebmaster(row.hostUrl)) {
                            WebmasterHostId hostId = IdUtils.urlToHostId(row.hostUrl);
                            alertedHosts.add(hostId);
                        }
                    }
                }

                log.info("Videohosts to alert amount {}, of them in webmaster {}", count, alertedHosts.size());
            } catch (YtException | InterruptedException | IOException e) {
                throw new WebmasterException("Error reading Yt table",
                        new WebmasterErrorResponse.YTServiceErrorResponse(getClass(), e), e);
            }

            return true;
        });

        log.info("Hosts for notification - {}", alertedHosts.size());

        videohostOfferService.sendVideohostOfferIsNeeded(alertedHosts);

        return new Result(TaskResult.SUCCESS);
    }

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

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

    public static class TaskState implements PeriodicTaskState {
    }

    public static class YtRow {
        @JsonProperty("host")
        private final String hostUrl;
        @JsonProperty("group")
        private final String group;

        @JsonCreator
        public YtRow(String hostUrl, String group) {
            this.hostUrl = hostUrl;
            this.group = group;
        }
    }
}
