package ru.yandex.webmaster3.storage.searchurl.samples.dao;

import java.util.List;
import java.util.Map;
import java.util.function.Function;

import lombok.RequiredArgsConstructor;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.util.TimeUtils;
import ru.yandex.webmaster3.storage.util.clickhouse2.AbstractClickhouseDao;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHRow;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseQueryContext;
import ru.yandex.webmaster3.storage.util.clickhouse2.MdbClickhouseServer;
import ru.yandex.webmaster3.storage.util.clickhouse2.SimpleByteArrayOutputStream;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.Format;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.GroupBy;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.Statement;

/**
 * ishalaru
 * 17.03.2021
 **/
@Repository
@Slf4j
@RequiredArgsConstructor(onConstructor_ = {@Autowired})
public class SearchUrlFreshStatisticsCHDao extends AbstractClickhouseDao {
    private static final DateTimeFormatter DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
    public static final String DATABASE = DB_WEBMASTER3_SEARCHURLS;
    public static final String TABLE_NAME_POSTFIX = "fresh_url_statistics_distributed";
    private static final String TABLE_NAME = DATABASE + "." + TABLE_NAME_POSTFIX;
    @Qualifier("legacyMdbClickhouseServer")
    private final MdbClickhouseServer clickhouseServer;

    public List<Record> loadCountInfo(WebmasterHostId hostId, Instant fromDate, Instant toDate) {
        final Object[] groupFields = {F.DAY};
        String sum = String.format("sum(%s) as add_urls_count, sum(%s) as gone_urls_count",
                F.NEW_URLS,
                F.GONE_URLS);
        final GroupBy groupBy = QueryBuilder.select(F.DAY, sum)
                .from(TABLE_NAME)
                .where(QueryBuilder.eq(F.HOST_ID, hostId))
                .and(QueryBuilder.gte(F.DAY, fromDate.toDateTime(TimeUtils.EUROPE_MOSCOW_ZONE).toString(DATE_FORMATTER)))
                .and(QueryBuilder.lte(F.DAY, toDate.toDateTime(TimeUtils.EUROPE_MOSCOW_ZONE).toString(DATE_FORMATTER)))
                .groupBy(groupFields);

        ClickhouseQueryContext.Builder context = ClickhouseQueryContext.useDefaults();
        return clickhouseServer.queryAll(context, groupBy.toString(), MAPPER);

    }

    public void addRecord(LocalDate date, Map<WebmasterHostId, Long> map) {
        Statement st = QueryBuilder.insertInto(DATABASE, TABLE_NAME_POSTFIX)
                .fields(
                        F.HOST_ID,
                        F.DAY,
                        F.NEW_URLS,
                        F.GONE_URLS
                ).format(Format.Type.TAB_SEPARATED);

        SimpleByteArrayOutputStream bs = new SimpleByteArrayOutputStream();
        for (Map.Entry<WebmasterHostId, Long> entry : map.entrySet()) {
            bs = packRowValues(bs,
                    entry.getKey().toString(),
                    date.toString(DATE_FORMATTER),
                    entry.getValue(),
                    0
            );
        }
        if (bs.size() == 0L) {
            return;
        }

        ClickhouseQueryContext.Builder context = ClickhouseQueryContext.useDefaults();
        clickhouseServer.insert(context, st.toString(), bs.toInputStream());

    }

    private static final Function<CHRow, Record> MAPPER = chRow ->
            new Record(LocalDate.parse(chRow.getString(F.DAY)).toDateTimeAtStartOfDay().toInstant(),
                    chRow.getLongUnsafe(F.NEW_URLS),
                    chRow.getLongUnsafe(F.GONE_URLS));

    @Value
    public static class Record {
        Instant day;
        long newUrlsCount;
        long goneUrlsCount;
    }

    private static class F {
        static final String HOST_ID = "host_id";
        static final String DAY = "base_date";
        static final String NEW_URLS = "add_urls_count";
        static final String GONE_URLS = "gone_urls_count";
    }


}
