package ru.yandex.webmaster3.worker.serpdata;

import java.util.Map;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableMap;

import ru.yandex.webmaster3.core.worker.task.PeriodicTaskType;
import ru.yandex.webmaster3.storage.clickhouse.TableType;
import ru.yandex.webmaster3.storage.greenurls.CurrentSerpDataCHDao;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHField;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHTable;
import ru.yandex.webmaster3.storage.yql.YqlFunctions;
import ru.yandex.webmaster3.storage.yql.YqlQueryBuilder;
import ru.yandex.webmaster3.storage.ytimport.YtClickhouseDataLoad;
import ru.yandex.webmaster3.storage.ytimport.YtClickhouseDataLoadType;
import ru.yandex.webmaster3.worker.TaskSchedule;
import ru.yandex.webmaster3.worker.turbo.AbstractYqlPrepareImportTask;


public class ImportCurrentSerpDataTask extends AbstractYqlPrepareImportTask {
    private static final Map<String, String> SOURCE_EXPRESSIONS = new ImmutableMap.Builder<String, String>()
            .put(CurrentSerpDataCHDao.F.HOST_ID, "$url2HostId(Host)")
            .put(CurrentSerpDataCHDao.F.GREEN_URLS_CNT, "cast(nvl(GreenUrlsCnt, 0) as String)")
            .put(CurrentSerpDataCHDao.F.QA_URLS_CNT, "cast(nvl(QAUrlsCnt, 0) as String)")
            .build();
    private static final int LINES_COUNT = 256;

    @Override
    protected YqlQueryBuilder prepareIntermediateTable(YtClickhouseDataLoad imprt) {
        String fields = getTable().getFields().stream().map(CHField::getName).map(SOURCE_EXPRESSIONS::get)
                .collect(Collectors.joining(" || '\\t' || \n", "\n(", " || '\\n')\n"));
        return YqlQueryBuilder.newBuilder()
                .cluster(tablePath)
                .appendFDefinition(YqlFunctions.URL_2_HOST_ID)
                .appendText("PRAGMA yt.MaxRowWeight = '128M';\n")
                .appendText("INSERT INTO " + INTERMEDIATE_TABLE)
                .appendText("SELECT ShardId, RowId, Compress::Gzip(String::JoinFromList(AGGREGATE_LIST(data), ''), 6) as data FROM (\n")
                .appendText("SELECT (Digest::Fnv64($url2HostId(Host)) % " + getShardsCount() + ") as ShardId,")
                .appendText("((Digest::Fnv64($url2HostId(Host)) / " + getShardsCount() + ") % " + LINES_COUNT + ") as RowId,")
                .appendText(fields).appendText("as data ")
                .appendText("FROM (\n")
                .appendText("SELECT Host, QAUrlsCnt, GreenUrlsCnt \n")
                .appendText("FROM (\n")
                .appendText("SELECT \n")
                .appendText("Host, \n")
                .appendText("count_if(ListHasItems(ListSkipWhile(Result, ($x) -> ($x.FeatureName != 'qapage')))) as QAUrlsCnt, \n")
                .appendText("count_if(ListHasItems(ListSkipWhile(Result, ($x) -> ($x.FeatureName != 'breadcrumbs')))) as GreenUrlsCnt \n")
                .appendText("FROM \n")
                .appendTable(imprt.getSourceTable())
                .appendText("GROUP BY `Host` as Host \n")
                .appendText(") \n")
                .appendText("WHERE QAUrlsCnt > 0 OR GreenUrlsCnt > 0")
                .appendText(") \n")
                .appendText(") \n GROUP BY ShardId, RowId;")
                .appendText("COMMIT;\n\n");
    }

    @Override
    protected CHTable getTable() {
        return CurrentSerpDataCHDao.TABLE;
    }

    @Override
    protected TableType getTableType() {
        return TableType.CURRENT_SERP_DATA;
    }

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

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

    @Override
    protected int getShardsCount() {
        return 1; // no sharding
    }

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