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

import com.google.common.base.Preconditions;
import org.apache.commons.lang3.tuple.Pair;
import org.springframework.stereotype.Repository;
import ru.yandex.webmaster3.core.blackbox.UserWithLogin;
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;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.typesafe.ValueDataMapper;

import java.util.Collection;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author leonidrom
 */
@Repository
public class LoginsToUidsYDao extends AbstractYDao {
    public LoginsToUidsYDao() {
        super(PREFIX_INTERNAL, "logins_to_uids");
    }

    public void addUsers(Collection<UserWithLogin> users) {
        if (users.isEmpty()) {
            return;
        }

        batchUpdate(INSERT_VALUE_MAPPER, users).execute();
    }

    public Map<String, Long> getUids(Collection<String> logins)  {
        Preconditions.checkArgument(logins.size() <= YDB_SELECT_ROWS_LIMIT,
                "Collection size exceeds YDB limitation");
        var lst = select(F.LOGIN.combine(F.USER_ID, Pair::of))
                .where(F.LOGIN.in(logins))
                .queryForList();

        return lst.stream().collect(Collectors.toMap(Pair::getLeft, Pair::getRight));
    }

    public void deleteForUser(long userId) {
        var sel = select(PK_MAPPER).secondaryIndex(USER_ID_INDEX).where(F.USER_ID.eq(userId)).getStatement();
        delete().on(sel).execute();
    }

    private static final ValueDataMapper<UserWithLogin> INSERT_VALUE_MAPPER = ValueDataMapper.create2(
            Pair.of(F.LOGIN, UserWithLogin::getLogin),
            Pair.of(F.USER_ID, UserWithLogin::getUserId)
    );

    private static final DataMapper<String> PK_MAPPER = DataMapper.create(F.LOGIN, l -> l);

    private static class F {
        static final Field<String> LOGIN = Fields.stringField("login");
        static final Field<Long> USER_ID = Fields.longField("user_id");
    }
}
