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

import java.util.List;

import lombok.Setter;
import org.joda.time.LocalDate;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

import ru.yandex.webmaster3.storage.clickhouse.ClickhouseTableInfo;
import ru.yandex.webmaster3.storage.clickhouse.TableProvider;
import ru.yandex.webmaster3.storage.clickhouse.TableType;
import ru.yandex.webmaster3.storage.metrika.data.MetrikaStatsByTime;
import ru.yandex.webmaster3.storage.util.clickhouse2.AbstractClickhouseDao;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHPrimitiveType;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHRow;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHTable;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.OrderBy;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;

/**
 * @author shabashoff
 */
public class MetrikaStatsByTimeCHDao extends AbstractClickhouseDao {
    private static final DateTimeFormatter FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
    public static final String TABLE_NAME_PREFIX = "metrika_stats_by_time";

    @Setter
    private TableProvider tableStorage;
    public static final CHTable TABLE = CHTable.builder()
            .database(AbstractClickhouseDao.DB_WEBMASTER3)
            .name(TABLE_NAME_PREFIX + "%s")
            .partitionBy("toYYYYMM(" + F.DATE + ")")
            .keyField(F.DATE, CHPrimitiveType.Date)
            .keyField(F.COUNTER_ID, CHPrimitiveType.UInt64)
            .keyField(F.DOMAIN, CHPrimitiveType.String)
            .field(F.TABLE_DATE, CHPrimitiveType.String)
            .field(F.VISITS, CHPrimitiveType.Int64)
            .field(F.BOUNCE_COUNT, CHPrimitiveType.Int64)
            .build();

    public List<MetrikaStatsByTime> getMetrika(String host, long counterId) {
        ClickhouseTableInfo table = tableStorage.getTable(TableType.METRIKA_STATS_BY_TIME);

        return getClickhouseServer().queryAll(
                table.chContext(getClickhouseServer(), counterId),
                QueryBuilder.select(F.DATE, F.TABLE_DATE, F.VISITS, F.BOUNCE_COUNT)
                        .from(table.getLocalTableName())
                        .where(QueryBuilder.eq(F.COUNTER_ID, counterId))
                        .and(QueryBuilder.eq(F.DOMAIN, host))
                        .orderBy(F.TABLE_DATE, OrderBy.Direction.ASC),
                this::mapper
        );
    }

    private MetrikaStatsByTime mapper(CHRow row) {
        var visits = row.getLongUnsafe(F.VISITS);
        var bounce = row.getLongUnsafe(F.BOUNCE_COUNT);
        return new MetrikaStatsByTime(
                LocalDate.parse(row.getString(F.DATE), FORMATTER),
                LocalDate.parse(row.getString(F.TABLE_DATE), FORMATTER),
                visits,
                bounce
        );
    }

    public static class F {
        public static final String DATE = "date";
        public static final String DOMAIN = "domain";
        public static final String COUNTER_ID = "counter_id";
        public static final String TABLE_DATE = "table_date";
        public static final String VISITS = "visits";
        public static final String BOUNCE_COUNT = "bounce_count";
    }

}
