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.joda.time.DateTime;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.data.WebmasterUser;
import ru.yandex.webmaster3.storage.admin.IDMVerificationRecord;
import ru.yandex.webmaster3.storage.user.UserTakeoutDataProvider;
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;


/**
 * @author kravchenko99
 * @date 12/22/20
 */

@Repository
public class IDMVerificationsYDao extends AbstractYDao implements UserTakeoutDataProvider {
    private static final String TABLE_NAME = "idm_verifications";

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

    public void addRecord(IDMVerificationRecord verificationRecord) {
        upsert(
                F.USER_ID.value(verificationRecord.getUserId()),
                F.HOST_ID.value(verificationRecord.getHostId()),
                F.ADMIN_USER_ID.value(verificationRecord.getAdminUserId()),
                F.CREATED_DATE.value(verificationRecord.getCreatedDate()),
                F.REQUESTED_HOST.value(verificationRecord.getRequestedHost()),
                F.REQUESTED_LOGIN.value(verificationRecord.getRequestedLogin())
        ).execute();
    }

    public List<IDMVerificationRecord> listAllVerifications() {
        return select(MAPPER)
                .queryForList(
                        Pair.of(F.USER_ID, IDMVerificationRecord::getUserId),
                        Pair.of(F.HOST_ID, IDMVerificationRecord::getHostId)
                );
    }

    public IDMVerificationRecord getVerificationForUserAndHost(long userId, WebmasterHostId hostId) {
        return select(MAPPER)
                .where(F.USER_ID.eq(userId))
                .and(F.HOST_ID.eq(hostId))
                .queryOne();
    }

    public List<IDMVerificationRecord> listVerificationsForUser(long userId) {
        return select(MAPPER)
                .where(F.USER_ID.eq(userId))
                .queryForList();
    }

    public void removeRecord(long userId, WebmasterHostId hostId) {
        delete().where(F.USER_ID.eq(userId))
                .and(F.HOST_ID.eq(hostId))
                .execute();
    }

    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 static final DataMapper<IDMVerificationRecord> MAPPER = DataMapper.create(
            F.USER_ID, F.HOST_ID, F.ADMIN_USER_ID, F.REQUESTED_HOST, F.REQUESTED_LOGIN, F.CREATED_DATE,
            IDMVerificationRecord::new
    );

    public void batchInsert(List<IDMVerificationRecord> items) {
        batchInsert(VALUE_MAPPER, items).execute();
    }

    private static final ValueDataMapper<IDMVerificationRecord> VALUE_MAPPER = ValueDataMapper.create2(
            Pair.of(F.USER_ID, IDMVerificationRecord::getUserId),
            Pair.of(F.HOST_ID, IDMVerificationRecord::getHostId),
            Pair.of(F.ADMIN_USER_ID, IDMVerificationRecord::getAdminUserId),
            Pair.of(F.REQUESTED_HOST, IDMVerificationRecord::getRequestedHost),
            Pair.of(F.REQUESTED_LOGIN, IDMVerificationRecord::getRequestedLogin),
            Pair.of(F.CREATED_DATE, IDMVerificationRecord::getCreatedDate)
    );

    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<Long> ADMIN_USER_ID = Fields.longField("admin_user_id");
        static final Field<DateTime> CREATED_DATE = Fields.jodaDateTimeField("created_date");
        static final Field<String> REQUESTED_HOST = Fields.stringField("requested_host");
        static final Field<String> REQUESTED_LOGIN = Fields.stringField("requested_login");
    }
}
