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

import lombok.Data;
import org.jetbrains.annotations.Nullable;
import org.joda.time.Duration;
import org.joda.time.Instant;
import org.springframework.stereotype.Repository;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.storage.cache.DashboardType;
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;

/**
 * @author leonidrom
 */
@Repository
public class DashboardCacheYDao extends AbstractYDao  {
    // Должен совпадать с ttl по полю update_date в базе
    public static final Duration TTL = Duration.standardDays(3);

    private static final String TABLE_NAME = "dashboard_cache";

    public DashboardCacheYDao()  {
        super(PREFIX_CACHE, TABLE_NAME);
    }

    public void saveData(WebmasterHostId hostId, DashboardType type, String key, byte[] data, Instant updateDate, Duration ttl) {
        upsert(
                F.HOST_ID.value(hostId),
                F.TYPE.value(type),
                F.KEY.value(key),
                F.DATA.value(data),
                F.UPDATE_DATE.value(updateDate),
                F.TTL.value(ttl.getMillis()))
        .execute();
    }

    @Nullable
    public byte[] getData(WebmasterHostId hostId, DashboardType type, String key) {
        var rec = select(MAPPER)
                .where(F.HOST_ID.eq(hostId))
                .and(F.TYPE.eq(type))
                .and(F.KEY.eq(key))
                .queryOne();

        if (rec == null || rec.getUpdateDate().plus(Duration.millis(rec.ttl)).isBeforeNow()) {
            return null;
        }

        return rec.data;
    }


    public void delete(WebmasterHostId hostId, DashboardType type, String key) {
        delete().where(F.HOST_ID.eq(hostId)).and(F.TYPE.eq(type)).and(F.KEY.eq(key)).execute();
    }

    @Data
    private static class Record {
        final WebmasterHostId hostId;
        final DashboardType type;
        final String key;
        final byte[] data;
        final Instant updateDate;
        final long ttl;
    }

    private static final DataMapper<Record> MAPPER = DataMapper.create(F.HOST_ID, F.TYPE, F.KEY, F.DATA, F.UPDATE_DATE, F.TTL, Record::new);

    private static class F {
        private static final Field<WebmasterHostId> HOST_ID = Fields.hostIdField("host_id");
        private static final Field<DashboardType> TYPE = Fields.intEnumField("type", DashboardType.R);
        private static final Field<String> KEY = Fields.stringField("key");
        private static final Field<byte[]> DATA = Fields.byteArrayField("data");
        private static final Field<Instant> UPDATE_DATE = Fields.jodaInstantField("update_date");
        private static final Field<Long> TTL = Fields.longField("ttl");
    }
}
