package ru.yandex.webmaster3.storage.turbo.dao.statistics;

import java.util.Collection;
import java.util.Collections;
import java.util.EnumMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import com.google.common.collect.ImmutableMap;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.turbo.model.TurboSource;
import ru.yandex.webmaster3.core.turbo.model.statistics.TurboSearchUrlsStats;
import ru.yandex.webmaster3.core.util.W3Collectors;
import ru.yandex.webmaster3.storage.clickhouse.LegacyMdbTableStorage;
import ru.yandex.webmaster3.storage.clickhouse.LocalClickhouseTableProvider;
import ru.yandex.webmaster3.storage.clickhouse.TableType;
import ru.yandex.webmaster3.storage.util.clickhouse2.AbstractClickhouseDao;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHField;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHPrimitiveType;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHRow;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHTable;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseServer;
import ru.yandex.webmaster3.storage.util.clickhouse2.MdbClickhouseServer;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.Statement;

/**
 * Created by Oleg Bazdyrev on 23/04/2019.
 */
public class TurboSearchUrlsStatsCHDao extends AbstractClickhouseDao {

    public static final CHTable SEARCHURLS_STATS_TABLE = CHTable.builder()
            .database(AbstractClickhouseDao.DB_WEBMASTER3_TURBO)
            .name("searchurls_stats_%s")
            .sharded(false)
            .partitionBy("toYYYYMM(" + F.DATE + ")")
            .keyField(F.DATE, CHPrimitiveType.Date)
            .keyField(F.DOMAIN, CHPrimitiveType.String)
            .field(F.TURBO_URLS, CHPrimitiveType.Int32)
            .field(F.TURBO_SEARCH_URLS, CHPrimitiveType.Int32)
            .field(F.TURBO_SEARCH_URLS_NO_AP, CHPrimitiveType.Int32)
            .field(F.AUTOPARSED_URLS, CHPrimitiveType.Int32)
            .field(F.AUTOPARSED_BUTTON_URLS, CHPrimitiveType.Int32)
            .field(F.RSS_URLS, CHPrimitiveType.Int32)
            .field(F.YML_URLS, CHPrimitiveType.Int32)
            .field(F.API_URLS, CHPrimitiveType.Int32)
            .field(F.YML_LISTING_URLS, CHPrimitiveType.Int32)
            .field(F.AUTO_MORDA_URLS, CHPrimitiveType.Int32)
            .build();
    private static final List<String> ALL_FIELDS = SEARCHURLS_STATS_TABLE.getFields().stream().filter(f -> !f.getName().equals(F.DATE))
            .map(CHField::getName).collect(Collectors.toList());
    private static final Map<TurboSource, String> FIELDS_BY_SOURCE = new EnumMap<>(
            ImmutableMap.<TurboSource, String>builder()
                    .put(TurboSource.AUTOPARSER, F.AUTOPARSED_URLS)
                    .put(TurboSource.AUTOPARSER_BUTTON, F.AUTOPARSED_BUTTON_URLS)
                    .put(TurboSource.RSS, F.RSS_URLS)
                    .put(TurboSource.YML, F.YML_URLS)
                    .put(TurboSource.API, F.API_URLS)
                    .put(TurboSource.YML_LISTING, F.YML_LISTING_URLS)
                    .put(TurboSource.AUTO_MORDA, F.AUTO_MORDA_URLS)
                    .build()
    );

    @Autowired
    private LegacyMdbTableStorage mdbTableStorage;
    @Autowired
    private MdbClickhouseServer legacyMdbClickhouseServer;

    @Override
    protected ClickhouseServer getClickhouseServer() {
        return legacyMdbClickhouseServer;
    }

    private static EnumMap<TurboSource, Long> getSourcesMap(CHRow row) {
        EnumMap<TurboSource, Long> result = new EnumMap<>(TurboSource.class);
        for (TurboSource source : TurboSource.values()) {
            result.put(source, row.getLongUnsafe(FIELDS_BY_SOURCE.get(source)));
        }
        return result;
    }

    @NotNull
    public TurboSearchUrlsStats getStats(String domain) {
        return getStats(Collections.singleton(domain)).getOrDefault(domain, TurboSearchUrlsStats.EMPTY);
    }

    @NotNull
    public Map<String, TurboSearchUrlsStats> getStats(Collection<String> domains) {
        if (CollectionUtils.isEmpty(domains)) {
            return Map.of();
        }
        LocalClickhouseTableProvider table = mdbTableStorage.getTable(TableType.TURBO_SEARCHURLS_STATS);;
        Statement st = QueryBuilder.select(ALL_FIELDS).from(table.getDistrTableName()).where(QueryBuilder.in(F.DOMAIN, domains));
        return getClickhouseServer().queryAll(st.toString(), chRow ->
                Pair.of(chRow.getString(F.DOMAIN), TurboSearchUrlsStats.builder()
                        .turboUrls(chRow.getLongUnsafe(F.TURBO_URLS))
                        .turboSearchUrls(chRow.getLongUnsafe(F.TURBO_SEARCH_URLS))
                        .turboSearchUrlsNoAP(chRow.getLongUnsafe(F.TURBO_SEARCH_URLS_NO_AP))
                        .urlsBySource(getSourcesMap(chRow))
                        .build()
                )).stream().collect(W3Collectors.toHashMap());
    }

    private interface F {
        String DATE = "date";
        String DOMAIN = "domain";
        String TURBO_URLS = "turbo_urls";
        String TURBO_SEARCH_URLS = "turbo_search_urls";
        String TURBO_SEARCH_URLS_NO_AP = "turbo_search_urls_no_ap";
        String AUTOPARSED_URLS = "autoparsed_urls";
        String AUTOPARSED_BUTTON_URLS = "autoparsed_button_urls";
        String RSS_URLS = "rss_urls";
        String YML_URLS = "yml_urls";
        String API_URLS = "api_urls";
        String YML_LISTING_URLS = "yml_listing_urls";
        String AUTO_MORDA_URLS = "auto_morda_urls";
    }
}
