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

import java.util.List;

import org.apache.commons.lang3.tuple.Pair;
import org.joda.time.Instant;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.storage.abt.model.ExperimentHistory;
import ru.yandex.webmaster3.storage.download.DownloadStatus;
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/12/20
 */

@Repository
public class AbtExperimentsHistoryYDao extends AbstractYDao {
    private static final String TABLE_NAME = "abt_experiment_history";

    public AbtExperimentsHistoryYDao() {
        super(PREFIX_INTERNAL, TABLE_NAME);
    }

    private static final DataMapper<ExperimentHistory> MAPPER = DataMapper.create(
            F.EXPERIMENT,
            F.GROUP,
            F.SCOPE,
            F.DESCRIPTION,
            F.CREATE_TIME,
            F.DELTA,
            F.STATUS,
            ExperimentHistory::new
    );

    private static final ValueDataMapper<ExperimentHistory> VALUE_MAPPER = ValueDataMapper.create(
            Pair.of(F.EXPERIMENT, e -> F.EXPERIMENT.get(e.getExperiment())),
            Pair.of(F.GROUP, e -> F.GROUP.get(e.getGroup())),
            Pair.of(F.SCOPE, e -> F.SCOPE.get(e.getScope())),
            Pair.of(F.DESCRIPTION, e -> F.DESCRIPTION.get(e.getDescription())),
            Pair.of(F.CREATE_TIME, e -> F.CREATE_TIME.get(e.getDateTime())),
            Pair.of(F.DELTA, e -> F.DELTA.get(e.getDelta())),
            Pair.of(F.STATUS, e -> F.STATUS.get(e.getStatus()))
    );

    public void insert(String experiment, String group, String scope, Instant time, Long delta, String description, DownloadStatus status)  {
        insert(
                F.EXPERIMENT.value(experiment),
                F.GROUP.value(group),
                F.SCOPE.value(scope),
                F.CREATE_TIME.value(time),
                F.DELTA.value(delta),
                F.DESCRIPTION.value(description),
                F.STATUS.value(status)
        ).execute();
    }

    public void update(String experiment, String group, String scope, Instant time, Long delta, String description, DownloadStatus status) {
        update()
                .with(F.STATUS.set(status))
                .and(F.DESCRIPTION.set(description))
                .where(F.EXPERIMENT.eq(experiment))
                .and(F.GROUP.eq(group))
                .and(F.SCOPE.eq(scope))
                .and(F.CREATE_TIME.eq(time))
                .execute();
    }

    public List<ExperimentHistory> getRecords(String experiment) {
        return select(MAPPER)
                .where(F.EXPERIMENT.eq(experiment)).queryForList();
    }

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

    private interface F {
        Field<String> EXPERIMENT = Fields.stringField("experiment");
        Field<String> GROUP = Fields.stringField("group");
        Field<String> SCOPE = Fields.stringField("scope");
        Field<String> DESCRIPTION = Fields.stringField("description");
        Field<Instant> CREATE_TIME = Fields.jodaInstantField("create_time");
        Field<Long> DELTA = Fields.longField("delta");
        Field<DownloadStatus> STATUS = Fields.intEnumField("download_status", DownloadStatus.R);
    }
}
