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

import java.util.List;
import java.util.function.Consumer;

import com.google.common.base.Strings;
import lombok.Builder;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.LocalDate;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.QueryBuilder;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.Select;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.Update;
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;


/**
 * ishalaru
 * 16.06.2020
 **/
@Slf4j
@Repository
public class TurboCmntStatisticsYDao extends AbstractYDao {
    private static final String TABLE_NAME = "turbo_cmnt_statistics";

    public TurboCmntStatisticsYDao() {
        super(PREFIX_TURBO, TABLE_NAME);
    }

    public List<TurboCmntStatistics> select(String domain,
                                            LocalDate startDate,
                                            LocalDate endDate,
                                            String template,
                                            Boolean enable,
                                            int pageSize) {
        final Select.Where select = select(TURBO_CMNT_STATISTICS_DATA_MAPPER)
                .where(F.DOMAIN.eq(domain));
        if (!Strings.isNullOrEmpty(template)) {
            select.and(QueryBuilder.or(F.URL.like(template), F.TITLE.like(template)));
        }
        if (startDate != null) {
            select.and(F.START_DATE.gte(startDate));
        }
        if (endDate != null) {
            select.and(F.START_DATE.lte(endDate));
        }
        select.order(F.START_DATE.asc()).order(F.URL.asc())
                .limit(pageSize);

        if (enable != null) {
            select.where(F.ENABLE.eq(enable));
        }
        return queryForList(select.getStatement(), TURBO_CMNT_STATISTICS_DATA_MAPPER);
    }

    public void update(String domain, String url, LocalDate startDate, Boolean enable) {
        final Update update = update(F.ENABLE.set(enable))
                .where(F.DOMAIN.eq(domain))
                .and(F.START_DATE.eq(startDate))
                .and(F.URL.eq(url)).getStatement();
        execute(update);
    }

    public void batchUpdate(List<TurboCmntStatistics> list) {
        execute(batchInsert(TURBO_CMNT_STATISTICS_VALUE_MAPPER, list));
    }

    public void streamReader(Consumer<TurboCmntStatistics> consumer) {
        streamReader(TURBO_CMNT_STATISTICS_DATA_MAPPER, consumer);
    }

    static final ValueDataMapper<TurboCmntStatistics> TURBO_CMNT_STATISTICS_VALUE_MAPPER = ValueDataMapper.create(
            Pair.of(F.DOMAIN, e -> F.DOMAIN.get(e.getDomain())),
            Pair.of(F.START_DATE, e -> F.START_DATE.get(e.getStartDate())),
            Pair.of(F.URL, e -> F.URL.get(e.getUrl())),
            Pair.of(F.TITLE, e -> F.TITLE.get(e.getTitle())),
            Pair.of(F.ENABLE, e -> F.ENABLE.get(e.isEnable()))
    );

    static final DataMapper<TurboCmntStatistics> TURBO_CMNT_STATISTICS_DATA_MAPPER = DataMapper.create(
            F.DOMAIN, F.URL, F.START_DATE, F.TITLE, F.ENABLE,
            (domain, url, startDate, title, enable) ->
                    new TurboCmntStatistics(domain, url, startDate, title, enable)
    );


    interface F {
        Field<String> DOMAIN = Fields.stringField("domain");
        Field<String> URL = Fields.stringField("url");
        Field<String> TITLE = Fields.stringField("title");
        Field<Boolean> ENABLE = Fields.boolField("enable");
        Field<LocalDate> START_DATE = Fields.jodaDateField("start_date");
    }

    @Value
    @Builder
    public static class TurboCmntStatistics {
        String domain;
        String url;
        org.joda.time.LocalDate startDate;
        String title;
        boolean enable;

        public String getTitle() {
            return title == null ? "" : title;
        }
    }
}
