package ru.yandex.webmaster3.worker.user.takeout;

import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskState;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskType;
import ru.yandex.webmaster3.storage.takeout.YtUserDataDeleteService;
import ru.yandex.webmaster3.storage.takeout.YtUserDataDirsYDao;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

import javax.annotation.PostConstruct;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.Executors;

/**
 * @author leonidrom
 *
 */
@Component
@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class ScrapeForTakeoutYtDirsPeriodicTask extends PeriodicTask<ScrapeForTakeoutYtDirsPeriodicTask.TaskState> {
    private final YtUserDataDeleteService ytUserDataDeleteService;
    private final YtUserDataDirsYDao ytUserDataDirsYDao;

    @Value("${external.yt.service.arnold.root.default}")
    private YtPath arnoldRoot;

    @Value("${external.yt.service.hahn.root.default}")
    private YtPath hahnRoot;

    private List<YtPath> scrapeRoots;

    @PostConstruct
    public void init() {
        scrapeRoots = List.of(
                arnoldRoot,
                hahnRoot
        );
    }

    @Override
    public Result run(UUID runId) throws Exception {
        setState(new TaskState());

        var executorService = Executors.newFixedThreadPool(scrapeRoots.size());
        List<Callable<List<YtPath>>> callables = new ArrayList<>();
        for (YtPath scrapeRoot: scrapeRoots) {
            callables.add(() -> ytUserDataDeleteService.scrapeForUserDataDirs(scrapeRoot));
        }

        var futures = executorService.invokeAll(callables);
        List<YtPath> userDataDirs = new ArrayList<>();
        for (var f : futures) {
            userDataDirs.addAll(f.get());
        }

        DateTime updateDate = DateTime.now();
        ytUserDataDirsYDao.addBatch(userDataDirs, updateDate);
        ytUserDataDirsYDao.clearOldRecords(updateDate);

        getState().totalDirs = userDataDirs.size();

        return Result.SUCCESS;
    }

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

    @Override
    public TaskSchedule getSchedule() {
        return TaskSchedule.startByCron("30 17 * * * *");
    }

    public static class TaskState implements PeriodicTaskState {
        public int totalDirs;
    }
}
