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


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.core.feedback.Feedback;
import ru.yandex.webmaster3.core.feedback.FeedbackType;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
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.List;
import java.util.function.Consumer;

@Repository
public class FeedbackYDao extends AbstractYDao {

    private static final String TABLE_NAME = "feedback";

    protected FeedbackYDao() {
        super(PREFIX_USER, TABLE_NAME);
    }

    public void insert(WebmasterHostId hostId, Long userId, DateTime createDate, FeedbackType type, String message,
                       String meta)  {
        upsert(
                F.HOST_ID.value(hostId),
                F.USER_ID.value(userId),
                F.CREATE_DATE.value(createDate),
                F.FEEDBACK_TYPE.value(type),
                F.MESSAGE.value(message),
                F.META.value(meta)
        ).execute();
    }

    public void batchInsert(List<Pair<String, Feedback>> items) {
        batchInsert(VALUE_DATA_MAPPER, items).execute();
    }

    public void forEach(Consumer<Pair<String, Feedback>> consumer) {
        streamReader(PAIR_MAPPER, consumer);
    }

    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 DataMapper<Feedback> MAPPER = DataMapper.create(
            F.HOST_ID, F.USER_ID, F.CREATE_DATE, F.FEEDBACK_TYPE, F.MESSAGE, F.META,
            (WebmasterHostId hostId, Long userId, DateTime createDate, FeedbackType feedbackType, String message, String meta) ->
                    new Feedback(hostId == null ? null : hostId.toStringId(), userId, createDate, feedbackType, message, meta)
    );

    private static final DataMapper<Pair<String, Feedback>> PAIR_MAPPER = DataMapper.create(
            F.HOST_ID, MAPPER, (x, y) -> Pair.of(x == null ? null : x.toStringId(), y));

    private static final DataMapper<Pair<WebmasterHostId, DateTime>> PK_MAPPER = DataMapper.create(F.HOST_ID, F.CREATE_DATE, Pair::of);

    private static final ValueDataMapper<Pair<String, Feedback>> VALUE_DATA_MAPPER = ValueDataMapper.create2(
            Pair.of(F.HOST_ID, Pair::getKey),
            Pair.of(F.USER_ID, p -> p.getValue().getUserId()),
            Pair.of(F.CREATE_DATE, p -> p.getValue().getCreateDate()),
            Pair.of(F.FEEDBACK_TYPE, p -> p.getValue().getType()),
            Pair.of(F.MESSAGE, p -> p.getValue().getMessage()),
            Pair.of(F.META, p -> p.getValue().getMeta())
    );

    private static class F {
        static final Field<WebmasterHostId> HOST_ID = Fields.hostIdField("host_id").makeOptional();
        static final Field<Long> USER_ID = Fields.longField("user_id");
        static final Field<DateTime> CREATE_DATE = Fields.jodaDateTimeField("create_date");
        static final Field<FeedbackType> FEEDBACK_TYPE = Fields.intEnumField("type", FeedbackType.R);
        static final Field<String> MESSAGE = Fields.stringField("message");
        static final Field<String> META = Fields.stringField("meta").makeOptional();
    }
}
