package ru.yandex.webmaster3.storage.spam;

import java.util.Set;
import java.util.TreeSet;
import java.util.function.Consumer;

import lombok.RequiredArgsConstructor;
import lombok.Value;
import org.joda.time.DateTime;
import org.joda.time.Duration;
import org.joda.time.Instant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Repository;

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;

@Repository
public class MetrikaCountersSpamStatsYDao extends AbstractYDao {
    private static final String TABLE_NAME = "metrika_counters_spam_stats";
    private static final Duration TTL = Duration.standardDays(1);

    public MetrikaCountersSpamStatsYDao() {
        super(PREFIX_INTERNAL, TABLE_NAME);
    }

    public void addEvent(long userId, long counterId, DateTime date) {
        upsert(
                F.USER_ID.value(userId),
                F.COUNTER_ID.value(counterId),
                F.DATE.value(date.toInstant()),
                F.UPDATE_TIME.value(Instant.now())
        ).execute();
    }

    public Set<Long> getCountersForUser(long userId) {
        Set<Long> res = new TreeSet<>();
        Instant current = Instant.now();
        foreachCounterId(cons -> {
            if (cons.getUserId() == userId && cons.getUpdateTime().isAfter(current.minus(TTL)))
                res.add(cons.getCounterId());
        });
        return res;
    }

    public void foreachCounterId(Consumer<Record> cons) {
        streamReader(MAPPER, cons);
    }

    public void deleteForUser(long userId) {
        delete().where(F.USER_ID.eq(userId)).execute();
    }

    private static final DataMapper<Record> MAPPER = DataMapper.create(F.USER_ID, F.COUNTER_ID, F.DATE, F.UPDATE_TIME, Record::new);

    @Value
    @RequiredArgsConstructor(onConstructor_ = @Autowired)
    public static class Record {
        Long userId;
        Long CounterId;
        Instant date;
        Instant updateTime;
    }

    private static class F {
        static final Field<Long> USER_ID = Fields.longField("user_id");
        static final Field<Long> COUNTER_ID = Fields.longField("counter_id");
        static final Field<Instant> DATE = Fields.jodaInstantField("date");
        static final Field<Instant> UPDATE_TIME = Fields.jodaInstantField("expire_after");
    }


}
