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

import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.apache.commons.collections4.CollectionUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedStatistics;
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.ClickhouseServer;
import ru.yandex.webmaster3.storage.util.clickhouse2.MdbClickhouseServer;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;

import static ru.yandex.webmaster3.storage.turbo.dao.TurboDomainsStateHelper.F;
import static ru.yandex.webmaster3.storage.turbo.service.TurboDomainsStateService.TurboDomainState;

/**
 * Created by Oleg Bazdyrev on 03/08/2020.
 */
@Repository
public class TurboDomainsStateCHDao extends AbstractClickhouseDao {

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

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

    @NotNull
    public TurboDomainState getDomainState(String domain) {
        return getDomainState(domain, turboDomainsStateHelper.getAllFields());
    }

    @NotNull
    public TurboDomainState getDomainStateOnlyFeeds(String domain) {
        return getDomainState(domain, turboDomainsStateHelper.getFeedsFields());
    }

    @NotNull
    public TurboDomainState getDomainStateOnlyFeedsAndAutomorda(String domain) {
        return getDomainState(domain, turboDomainsStateHelper.getFeedsAndAutomordaFields());
    }

    @NotNull
    public Map<String, TurboDomainState> getDomainsStateOnlyFeedsAndAutomorda(Collection<String> domains) {
        return getDomainsState(domains, turboDomainsStateHelper.getFeedsAndAutomordaFields());
    }

    @NotNull
    public TurboDomainState getDomainStateOnlyProblems(String domain) {
        return getDomainState(domain, turboDomainsStateHelper.getProblemsFields());
    }

    @NotNull
    public TurboDomainState getDomainState(String domain, TurboDomainsStateHelper.TurboDomainsStateMapperAndFields mapperAndFields) {
        LocalClickhouseTableProvider table = mdbTableStorage.getTable(TableType.TURBO_DOMAINS_STATE);
        var st = QueryBuilder.select(mapperAndFields.getFields())
                .from(table.getTableName())
                .where(QueryBuilder.eq(F.DOMAIN, domain));
        return getClickhouseServer().queryOne(table.chContext(getClickhouseServer(), domain), st.toString(), mapperAndFields.getMapper())
                .orElse(TurboDomainState.empty(domain));
    }

    public Map<String, TurboDomainState> getDomainsState(Collection<String> domains) {
        return getDomainsState(domains, turboDomainsStateHelper.getAllFields());
    }

    public Map<String, TurboDomainState> getDomainsStateOnlyProblems(Collection<String> domains) {
        return getDomainsState(domains, turboDomainsStateHelper.getProblemsFields());
    }

    public Map<String, TurboDomainState> getDomainsState(Collection<String> domains,
                                                         TurboDomainsStateHelper.TurboDomainsStateMapperAndFields mapperAndFields) {
        if (CollectionUtils.isEmpty(domains)) {
            return Collections.emptyMap();
        }
        LocalClickhouseTableProvider table = mdbTableStorage.getTable(TableType.TURBO_DOMAINS_STATE);
        var st = QueryBuilder.select(mapperAndFields.getFields())
                .from(table.getTableName()).where(QueryBuilder.in(F.DOMAIN, domains));

        return getClickhouseServer().queryAll(st.toString(), mapperAndFields.getMapper()).stream()
                .collect(Collectors.toMap(TurboDomainState::getDomain, Function.identity(), W3Collectors.replacingMerger()));
    }

    public TurboFeedStatistics getFeedStatistics(String domain, String feedUrl) {
        TurboDomainState domainState = getDomainState(domain, turboDomainsStateHelper.getFeedsFields());
        return Stream.concat(domainState.getRssFeeds().stream(), domainState.getYmlFeeds().stream())
                .filter(feed -> feed.getUrl().equals(feedUrl)).findAny().orElse(null);
    }

}
