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

import java.util.Collection;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import lombok.Value;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.DateTime;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.util.enums.EnumResolver;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.query.Clause;
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;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.ValueDataMapper;

@Repository
public class HostRemovalNotificationsYDao extends AbstractYDao {
    private static final String DB_NAME = PREFIX_NOTIFICATION;
    private static final String TABLE_NAME = "host_removal_notifications";


    protected HostRemovalNotificationsYDao() {
        super(DB_NAME, TABLE_NAME);
    }

    public void insert(Long userId, WebmasterHostId hostId, Type type) {
        DateTime now = DateTime.now();
        upsert(F.USER_ID.value(userId), F.HOST_ID.value(hostId), F.TYPE.value(type), F.TTL_DATE.value(now)).execute();
    }

    public void insert(Collection<UserHostInfo> items) {
        batchInsert(VALUE_MAPPER, items).execute();
    }

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

    public Set<Pair<Long, WebmasterHostId>> selectByType(List<Pair<Long, WebmasterHostId>> usersWithHosts, Type type) {
        return select(MAPPER)
                .where(new Clause.InClause(
                        "(" + F.USER_ID.getName() + "," + F.HOST_ID.getName() + ")", usersWithHosts)
                ).and(F.TYPE.eq(type)).queryForList()
                .stream()
                .map(x -> Pair.of(x.userId, x.hostId))
                .collect(Collectors.toSet());
    }


    private static class F {
        static final Field<Long> USER_ID = Fields.longField("user_id");
        static final Field<WebmasterHostId> HOST_ID = Fields.hostIdField("host_id");
        static final Field<Type> TYPE = Fields.stringEnumField("type", Type.R);
        static final Field<DateTime> TTL_DATE = Fields.jodaDateTimeField("ttl_date");

    }


    private static final DataMapper<UserHostInfo> MAPPER = DataMapper.create(F.USER_ID, F.HOST_ID, F.TYPE,
            UserHostInfo::new);
    private static final ValueDataMapper<UserHostInfo> VALUE_MAPPER =
            ValueDataMapper.create2(
                    Pair.of(F.USER_ID, UserHostInfo::getUserId),
                    Pair.of(F.HOST_ID, UserHostInfo::getHostId),
                    Pair.of(F.TYPE, UserHostInfo::getType),
                    Pair.of(F.TTL_DATE, x -> DateTime.now()));

    @Value
    public static class UserHostInfo {
        Long userId;
        WebmasterHostId hostId;
        Type type;
    }

    public enum Type {
        WEEK,
        THREE_WEEKS,
        ;

        public static final EnumResolver<Type> R = EnumResolver.er(Type.class);

    }
}
