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

import java.util.List;

import org.apache.commons.lang3.tuple.Pair;
import org.jetbrains.annotations.NotNull;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.blackbox.UserWithLogin;
import ru.yandex.webmaster3.core.data.WebmasterUser;
import ru.yandex.webmaster3.storage.admin.AdminUserInfo;
import ru.yandex.webmaster3.storage.user.UserTakeoutDataProvider;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.Upsert;
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;

/*
 * @author kravchenko99
 * @date 8/21/20
 */
@Repository
public class AdminUsersYDao extends AbstractYDao implements UserTakeoutDataProvider {
    private static final String TABLE_NAME = "admin_users";
    private static final String LOGIN_INDEX = "login_index";

    private static final ValueDataMapper<AdminUserInfo> VALUE_MAPPER = ValueDataMapper.create(
            Pair.of(F.USER_ID, e -> F.USER_ID.get(e.getAdminUser().getUserId())),
            Pair.of(F.LOGIN, e -> F.LOGIN.get(e.getAdminUser().getLogin())),
            Pair.of(F.PASSPORT_USER_ID, e -> F.PASSPORT_USER_ID.get(e.getPassportUser().getUserId())),
            Pair.of(F.PASSPORT_USER_LOGIN, e -> F.PASSPORT_USER_LOGIN.get(e.getPassportUser().getLogin()))
    );

    private static final DataMapper<UserWithLogin> MAPPER_USER = DataMapper.create(
            F.USER_ID, F.LOGIN, UserWithLogin::new
    );
    private static final DataMapper<UserWithLogin> MAPPER_PASSPORT = DataMapper.create(
            F.PASSPORT_USER_ID, F.PASSPORT_USER_LOGIN, UserWithLogin::new
    );
    private static final DataMapper<AdminUserInfo> MAPPER = DataMapper.create(
            MAPPER_USER, MAPPER_PASSPORT, AdminUserInfo::new
    );

    public AdminUsersYDao() {
        super( PREFIX_ADMIN, TABLE_NAME);
    }

    public AdminUserInfo getUserInfoById(long userId) {
//        return adminUsersCDao.getUserInfoById(userId);
        return queryOne(select(MAPPER).where(F.USER_ID.eq(userId)).getStatement(), MAPPER);
    }

    public AdminUserInfo getUserInfoByLogin(String login) {
//        return adminUsersCDao.getUserInfoByLogin(login);
        return queryOne(select(MAPPER).secondaryIndex(LOGIN_INDEX).where(F.LOGIN.eq(login)).getStatement(), MAPPER);
    }

    public void addUserInfo(AdminUserInfo user) {
        final Upsert upsert = upsert(F.USER_ID.value(user.getAdminUser().getUserId()),
                F.LOGIN.value(user.getAdminUser().getLogin()),
                F.PASSPORT_USER_ID.value(user.getPassportUser().getUserId()),
                F.PASSPORT_USER_LOGIN.value(user.getPassportUser().getLogin()));
        execute(upsert);
    }

    public void batchInsert(List<AdminUserInfo> userInfos) {
        execute(batchInsert(VALUE_MAPPER, userInfos));
    }

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

    @Override
    public void deleteUserData(WebmasterUser user) {
        deleteForUser(user.getUserId());
    }

    @Override
    public @NotNull List<String> getTakeoutTables() {
        return List.of(
                getTablePath()
        );
    }

    private interface F {
        Field<Long> USER_ID = Fields.longField("user_id");
        Field<String> LOGIN = Fields.stringField("login");
        Field<Long> PASSPORT_USER_ID = Fields.longField("passport_user_id");
        Field<String> PASSPORT_USER_LOGIN = Fields.stringField("passport_user_login");
    }

}
