package ru.yandex.webmaster3.storage.takeout;

import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.DateTime;
import org.springframework.stereotype.Repository;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.QueryBuilder;
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 ru.yandex.webmaster3.storage.util.yt.YtPath;

import java.util.Collection;
import java.util.List;
import java.util.UUID;
import java.util.function.Consumer;

/**
 * @author leonidrom
 *
 */
@Repository
public class YtUserDataDeleteQueueYDao extends AbstractYDao {
    public YtUserDataDeleteQueueYDao() {
        super(PREFIX_INTERNAL, "x§");
    }

    public void add(List<Record> records) {
        batchInsert(VALUE_MAPPER, records).execute();
    }

    public List<UUID> listInProgressRequestIds() {
        return select(F.REQUEST_ID).distinct().where(F.IS_DONE.eq(false)).queryForList();
    }

    public void forEach(Consumer<Record> consumer) {
        streamReader(DATA_MAPPER, consumer);
    }

    public void markAsDone(Collection<UUID> requestIds, YtPath tablePath) {
        var cond = QueryBuilder.and(F.REQUEST_ID.in(requestIds), F.TABLE_PATH.eq(tablePath));
        update(F.IS_DONE.set(true)).where(cond).execute();
    }

    public void delete(UUID requestId) {
        delete().where(F.REQUEST_ID.eq(requestId)).execute();
    }

    private static final DataMapper<Record> DATA_MAPPER = DataMapper.create(
            F.REQUEST_ID, F.USER_ID, F.TABLE_PATH, F.ADD_DATE, F.IS_DONE, Record::new
    );

    private static final ValueDataMapper<Record> VALUE_MAPPER = ValueDataMapper.create2(
            Pair.of(F.REQUEST_ID, Record::requestId),
            Pair.of(F.TABLE_PATH, Record::tablePath),
            Pair.of(F.USER_ID, Record::userId),
            Pair.of(F.ADD_DATE, Record::addDate),
            Pair.of(F.IS_DONE, Record::isDone)
    );

    private static final class F {
        static final Field<UUID> REQUEST_ID = Fields.uuidField("request_id");
        static final Field<Long> USER_ID = Fields.longField("user_id");
        static final Field<YtPath> TABLE_PATH = Fields.ytPathField("path");
        static final Field<DateTime> ADD_DATE = Fields.jodaDateTimeField("add_date");
        static final Field<Boolean> IS_DONE = Fields.boolField("is_done");
    }

    public record Record(UUID requestId, long userId, YtPath tablePath,
                         DateTime addDate, boolean isDone) {}
}
