package ru.yandex.webmaster3.storage.feeds.statistics;

import java.util.Collection;
import java.util.EnumMap;
import java.util.Map;

import lombok.Value;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.LocalDate;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.feeds.feed.NativeFeedType;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.DataMapper;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.Field;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.Fields;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.ValueDataMapper;

/**
 * Created by Oleg Bazdyrev on 11/04/2022.
 */
@Repository
public class FeedsDomainEnrichmentYDao extends AbstractYDao {

    private static final long MIN_ENRICHMENT_RIVALS = 3;

    private static final ValueDataMapper<DomainEnrichmentInfo> VALUE_DATA_MAPPER = ValueDataMapper.create2(
            Pair.of(F.DOMAIN, DomainEnrichmentInfo::getDomain),
            Pair.of(F.TYPE, DomainEnrichmentInfo::getType),
            Pair.of(F.DATE, DomainEnrichmentInfo::getDate),
            Pair.of(F.ENRICHABLE, DomainEnrichmentInfo::getEnrichable),
            Pair.of(F.ENRICHED, DomainEnrichmentInfo::getEnriched),
            Pair.of(F.COUNT, DomainEnrichmentInfo::getCount)
    );

    private static final DataMapper<DomainEnrichmentInfo> MAPPER = DataMapper.create(
            F.DOMAIN, F.TYPE, F.DATE, F.ENRICHABLE, F.ENRICHED, F.COUNT, DomainEnrichmentInfo::new
    );

    protected FeedsDomainEnrichmentYDao() {
        super(PREFIX_FEEDS, "feeds_domain_enrichment");
    }

    public void insert(Collection<DomainEnrichmentInfo> data) {
        batchInsert(VALUE_DATA_MAPPER, data).execute();
    }

    public Map<NativeFeedType, Double> getEnrichmentInfo(String domain, LocalDate from, LocalDate to) {
        Map<NativeFeedType, Double> result = new EnumMap<>(NativeFeedType.class);
        Map<NativeFeedType, Long> enriched = new EnumMap<>(NativeFeedType.class);
        Map<NativeFeedType, Long> enrichable = new EnumMap<>(NativeFeedType.class);
        for (DomainEnrichmentInfo dei : select(MAPPER).where(F.DOMAIN.eq(domain)).and(F.DATE.gte(from)).and(F.DATE.lte(to)).queryForList()) {
            if (dei.getCount() != null && dei.getCount() > 0 && dei.getCount() < MIN_ENRICHMENT_RIVALS) {
                result.put(dei.getType(), null);
            }
            enriched.compute(dei.getType(), (k, v) -> (v == null ? 0L : v) + dei.getEnriched());
            enrichable.compute(dei.getType(), (k, v) -> (v == null ? 0L : v) + dei.getEnrichable());
        }
        for (NativeFeedType type : enriched.keySet()) {
            if (!result.containsKey(type)) {
                result.put(type, enriched.get(type) / (double) enrichable.get(type));
            }
        }
        return result;
    }

    @Value
    public static class DomainEnrichmentInfo {
        String domain;
        NativeFeedType type;
        LocalDate date;
        Long enrichable;
        Long enriched;
        Long count;
    }

    private interface F {
        Field<String> DOMAIN = Fields.stringField("domain");
        Field<NativeFeedType> TYPE = Fields.stringEnumField("type", NativeFeedType.R);
        Field<LocalDate> DATE = Fields.jodaDateField("date");
        Field<Long> ENRICHABLE = Fields.longField("enrichable");
        Field<Long> ENRICHED = Fields.longField("enriched");
        Field<Long> COUNT = Fields.longField("count").makeOptional();
    }
}
