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

import lombok.Data;
import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.DateTime;
import org.springframework.stereotype.Repository;
import ru.yandex.webmaster3.core.data.WebmasterHostId;
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.function.Consumer;
import java.util.stream.Collectors;

/**
 * @author leonidrom
 */
@Repository
public class DeletedUnverifiedHostsYDao extends AbstractYDao {
    private static final String TABLE_NAME = "deleted_unverified_hosts";

    public DeletedUnverifiedHostsYDao() {
        super(PREFIX_HOST, TABLE_NAME);
    }

    public void addBatch(Collection<WebmasterHostId> hostIds, DateTime addDate) {
        var records = hostIds.stream()
                .map(hostId -> new RowRecord(hostId, addDate, null))
                .collect(Collectors.toList());
        batchUpdate(INSERT_VALUE_MAPPER, records).execute();
    }

    public void delete(WebmasterHostId hostId) {
        delete().where(F.HOST_ID.eq(hostId)).execute();
    }

    public void markDeleted(WebmasterHostId hostId, DateTime deletedDate) {
        insert(
            F.HOST_ID.value(hostId),
            F.DELETE_DATE.value(deletedDate)
        ).execute();
    }

    public void markDeleted(Collection<WebmasterHostId> hostIds, DateTime deletedDate) {
        var records = hostIds.stream()
                .map(hostId -> new RowRecord(hostId, null, deletedDate))
                .collect(Collectors.toList());
        batchUpdate(UPDATE_DELETE_DATE_VALUE_MAPPER, records).execute();
    }

    public void forEach(Consumer<RowRecord> consumer) {
        streamReader(MAPPER, consumer);
    }

    private static class F {
        static final Field<WebmasterHostId> HOST_ID = Fields.hostIdField("host_id");
        static final Field<DateTime> ADD_DATE = Fields.jodaDateTimeField("add_date");
        static final Field<DateTime> DELETE_DATE = Fields.jodaDateTimeField("delete_date").makeOptional();
    }

    @Data
    public static class RowRecord {
        public final WebmasterHostId hostId;
        public final DateTime addDate;
        public final DateTime deleteDate;
    }

    public static final DataMapper<RowRecord> MAPPER = DataMapper.create(F.HOST_ID, F.ADD_DATE, F.DELETE_DATE, RowRecord::new);

    private static final ValueDataMapper<RowRecord> UPDATE_DELETE_DATE_VALUE_MAPPER = ValueDataMapper.create(
            Pair.of(F.HOST_ID, r -> F.HOST_ID.get(r.hostId)),
            Pair.of(F.DELETE_DATE, r -> F.DELETE_DATE.get(r.deleteDate)
    ));

    private static final ValueDataMapper<RowRecord> INSERT_VALUE_MAPPER = ValueDataMapper.create(
            Pair.of(F.HOST_ID, r -> F.HOST_ID.get(r.hostId)),
            Pair.of(F.ADD_DATE, r -> F.ADD_DATE.get(r.addDate)
   ));
}
