package ru.yandex.webmaster3.storage.turbo.dao.adv;

import java.util.function.Consumer;

import com.fasterxml.jackson.core.type.TypeReference;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
import org.joda.time.DateTime;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.core.util.enums.EnumResolver;
import ru.yandex.webmaster3.storage.util.ydb.AbstractYDao;
import ru.yandex.webmaster3.storage.util.ydb.querybuilder.Upsert;
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;

/**
 * ishalaru
 * 07.09.2020
 **/
@Repository
@Slf4j
public class TurboAdvBlockPostponedYDao extends AbstractYDao {
    private static final String TABLE_NAME = "turbo_adv_postponed";
    private static final int MAX_WAITING_DURATION_IN_DAYS = 3;

    public TurboAdvBlockPostponedYDao() {
        super(PREFIX_TURBO, TABLE_NAME);
    }

    public void insert(String domain, Status status, PostponeData data) {
        DateTime startDate = DateTime.now();
        final Upsert upsert = upsert(F.DOMAIN.value(domain),
                F.STATUS.value(status),
                F.DATA.value(data),
                F.START_DATE.value(startDate),
                F.END_DATE.value(startDate.plusDays(MAX_WAITING_DURATION_IN_DAYS)));
        execute(upsert);
    }

    public AdvPostponedInfo load(String domain) {
        return queryOne(select(ADV_POSTPONED_INFO_DATA_MAPPER)
                        .where(F.DOMAIN.eq(domain)).getStatement(),
                ADV_POSTPONED_INFO_DATA_MAPPER);
    }

    public void delete(String domain) {
        execute(delete().where(F.DOMAIN.eq(domain)).getStatement());
    }

    public void executeForAll(Consumer<AdvPostponedInfo> consumer) {
        streamReader(ADV_POSTPONED_INFO_DATA_MAPPER, consumer);
    }

    static final DataMapper<AdvPostponedInfo> ADV_POSTPONED_INFO_DATA_MAPPER = DataMapper.create(
            F.DOMAIN, F.STATUS, F.DATA, F.START_DATE, F.END_DATE,
            (domain, status, data, startDate, endDate) ->
                    new AdvPostponedInfo(domain, status, data, startDate, endDate)
    );

    private interface F {
        Field<String> DOMAIN = Fields.stringField("domain");
        Field<Status> STATUS = Fields.stringEnumField("status", EnumResolver.er(Status.class));
        Field<PostponeData> DATA = Fields.jsonField("data", PostponeData.TYPE_REFERENCE);
        Field<DateTime> START_DATE = Fields.jodaDateTimeField("start_date");
        Field<DateTime> END_DATE = Fields.jodaDateTimeField("end_date");
    }

    @Value
    public static class AdvPostponedInfo {
        String domain;
        Status status;
        PostponeData data;
        DateTime startDate;
        DateTime endDate;
    }

    @Value
    public static class PostponeData {
        public final static TypeReference<PostponeData> TYPE_REFERENCE = new TypeReference<>() {
        };
        String email;
        String userId;
        String key;
    }

    public enum Status {
        USER_CREATE_RSI_ACCOUNT,
        WAITING_EXTERNAL_USER_APPROVE,
        WAITING_DOMAIN_VALIDATION,
    }

}
