package ru.yandex.webmaster3.worker.importanturls;

import java.util.Comparator;
import java.util.Optional;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

import lombok.Setter;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import ru.yandex.webmaster3.storage.importanturls.RecommendedUrlsImportService;
import ru.yandex.webmaster3.storage.util.yt.YtException;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.ytimport.YtClickhouseDataLoad;
import ru.yandex.webmaster3.storage.ytimport.YtClickhouseDataLoadState;
import ru.yandex.webmaster3.storage.ytimport.YtClickhouseDataLoadType;
import ru.yandex.webmaster3.worker.ytimport.AbstractYtClickhouseDataLoadTask;

/**
 * @author avhaliullin
 */
public class RecommendedUrlsImportTask extends AbstractYtClickhouseDataLoadTask {
    private static final Pattern TABLE_NAME_REGEX = Pattern.compile("^(\\d{8})_(\\d{8})$");
    public static final DateTimeFormatter TABLE_NAME_DATE_FORMAT = DateTimeFormat.forPattern("yyyyMMdd");

    @Setter
    private RecommendedUrlsImportService recommendedUrlsImportService;

    @Override
    protected YtClickhouseDataLoad prepare(YtClickhouseDataLoad imprt) throws Exception {
        return recommendedUrlsImportService.prepareRecommendedUrls(imprt).withNextState();
    }

    @Override
    protected YtClickhouseDataLoad doImport(YtClickhouseDataLoad imprt) throws Exception {
        return recommendedUrlsImportService.importRecommendedUrls(imprt).withNextState();
    }

    @Override
    protected YtClickhouseDataLoad replicate(YtClickhouseDataLoad imprt) throws Exception {
        return recommendedUrlsImportService.replicateRecommendedUrls(imprt).withNextState();
    }

    @Override
    protected YtClickhouseDataLoad init(YtClickhouseDataLoad imprt) throws Exception {
        return ytService.withoutTransactionQuery(cypressService -> {
            Optional<Pair<LocalDate, YtPath>> newTableOpt = cypressService.list(tablePath).stream()
                    .flatMap(path -> {
                        Matcher m = TABLE_NAME_REGEX.matcher(path.getName());
                        if (m.find()) {
                            return Stream.of(Pair.of(LocalDate.parse(m.group(2), TABLE_NAME_DATE_FORMAT), path));
                        } else {
                            return Stream.empty();
                        }
                    }).max(Comparator.comparing(Pair::getLeft));
            if (newTableOpt.isEmpty()) {
                log.info("Not found recommended urls table");
                return imprt.withState(YtClickhouseDataLoadState.DONE);
            }
            LocalDate newTableDate = newTableOpt.get().getLeft();
            YtPath newTable = newTableOpt.get().getRight();
            if (imprt.getDateTo() == null || imprt.getDateTo().isBefore(newTableDate)) {
                return imprt.withSourceTable(newTable, newTableDate, newTableDate);
            }
            return imprt.withState(YtClickhouseDataLoadState.DONE);
        });
    }

    @Override
    protected YtClickhouseDataLoad clean(YtClickhouseDataLoad imprt) throws InterruptedException, YtException {
        return recommendedUrlsImportService.cleanRecommendedUrls(imprt);
    }

    @Override
    protected YtClickhouseDataLoad rename(YtClickhouseDataLoad imprt) throws Exception {
        return recommendedUrlsImportService.renameRecommendedUrls(imprt);
    }

    @Override
    protected YtClickhouseDataLoad createDistributedTables(YtClickhouseDataLoad imprt) throws Exception {
        return imprt.withNextState();
    }

    @Override
    protected YtClickhouseDataLoadType getImportType() {
        return YtClickhouseDataLoadType.RECOMMENDED_URLS;
    }

}
