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

import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.util.List;
import java.util.stream.Collectors;

import org.joda.time.LocalDate;
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.GzipUtils;
import ru.yandex.webmaster3.core.util.json.JsonMapping;
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.turbo.service.TurboDomainsStateService;
import ru.yandex.webmaster3.storage.turbo.service.TurboFeedRawStatsData;
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.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.OrderBy;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;

import static ru.yandex.webmaster3.storage.turbo.service.TurboDomainsStateService.TurboFeedRawState;

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

    public static final CHTable TABLE = CHTable.builder()
            .database(AbstractClickhouseDao.DB_WEBMASTER3_TURBO)
            .name("turbo_feeds_history_%s")
            .partitionBy("toYYYYMM(date)")
            .keyField(F.DATE, CHPrimitiveType.Date)
            .keyField(F.FEED, CHPrimitiveType.String)
            .field(F.TIMESTAMP, CHPrimitiveType.Int64)
            .field(F.DATA, CHPrimitiveType.String)
            .field(F.LAST_ACCESS, CHPrimitiveType.Int64)
            .field(F.TYPE, CHPrimitiveType.String)
            .partsToThrowInsert(2000)
            .build();

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

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

    public List<TurboFeedStatistics> getStatistics(String domain, String feedUrl, LocalDate date) {
        LocalClickhouseTableProvider table = mdbTableStorage.getTable(TableType.TURBO_FEEDS_HISTORY);
        var st = QueryBuilder.select(TABLE.getFields().stream().map(CHField::getName).collect(Collectors.toList()))
                .from(table.getTableName())
                .where(QueryBuilder.eq(F.FEED, feedUrl))
                .and(QueryBuilder.eq(F.DATE, date))
                .orderBy(F.TIMESTAMP, OrderBy.Direction.DESC);

        return getClickhouseServer().queryAll(table.chContext(getClickhouseServer(), feedUrl), st, chRow -> {

            TurboFeedRawState rawState = new TurboFeedRawState(domain, chRow.getString(F.FEED), chRow.getString(F.TYPE),
                    true, chRow.getLong(F.TIMESTAMP), chRow.getLong(F.LAST_ACCESS), getData(chRow.getString(F.DATA)));

            return turboDomainsStateService.feedStatisticsFromRawState(rawState);
        });
    }

    private TurboFeedRawStatsData getData(String s) {
        try {
            return JsonMapping.OM.readValue(GzipUtils.unGzip(new ByteArrayInputStream(s.getBytes())), TurboFeedRawStatsData.class);
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public interface F {
        String DATE = "date";
        String FEED = "feed";
        String TIMESTAMP = "timestamp";
        String DATA = "data";
        String LAST_ACCESS = "last_access";
        String TYPE = "type";
    }

}
