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

import java.util.List;
import java.util.UUID;

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

import ru.yandex.webmaster3.storage.notifications.SearchBaseNotificationInfo;
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;


/**
 * @author kravchenko99
 * @date 11/3/21
 */

@Repository
public class SearchBaseNotificationsYDao extends AbstractYDao {
    private static final String TABLE_NAME = "search_base_notifications";
    private static final Duration TTL = Duration.standardDays(14);

    public SearchBaseNotificationsYDao() {
        super(PREFIX_NOTIFICATION, TABLE_NAME);
    }


    public List<SearchBaseNotificationInfo> listNotifications() {
        DateTime ttlThreshold = DateTime.now().minus(TTL);
        return select(MAPPER)
                .where(F.TTL_DATE.gte(ttlThreshold))
                .queryForList();
    }

    public SearchBaseNotificationInfo getNotificationInfo(UUID notificationId) {
        DateTime ttlThreshold = DateTime.now().minus(TTL);
        return select(MAPPER)
                .where(F.NOTIFICATION_ID.eq(notificationId))
                .and(F.TTL_DATE.gte(ttlThreshold))
                .queryOne();
    }

    public void insertNotification(UUID notificationId, DateTime date, boolean sendBaseUpdate,
                                   boolean sendImportantUrls, Duration ttl) {
        var ttlDate = DateTime.now().plus(TTL).minus(ttl);
        upsert(
                F.NOTIFICATION_ID.value(notificationId),
                F.NOTIFICATION_DATE.value(date),
                F.SEND_BASE_UPDATE.value(sendBaseUpdate),
                F.SEND_IMPORTANT_URLS.value(sendImportantUrls),
                F.TTL_DATE.value(ttlDate)
        ).execute();
    }

    public void updateNotification(SearchBaseNotificationInfo notificationInfo, Duration ttl) {
        var ttlDate = DateTime.now().plus(TTL).minus(ttl);
        upsert(
                F.NOTIFICATION_ID.value(notificationInfo.getNotificationId()),
                F.NOTIFICATION_DATE.value(notificationInfo.getNotificationDate()),
                F.RECEIVERS_LIST_ID.value(notificationInfo.getRecListId()),
                F.SENDING.value(notificationInfo.isSending()),
                F.SEND_BASE_UPDATE.value(notificationInfo.isSendBaseUpdate()),
                F.SEND_IMPORTANT_URLS.value(notificationInfo.isSendImportantUrls()),
                F.TTL_DATE.value(ttlDate)
        ).execute();
    }

    private static final DataMapper<SearchBaseNotificationInfo> MAPPER = DataMapper.create(
            F.NOTIFICATION_ID, F.RECEIVERS_LIST_ID,
            F.NOTIFICATION_DATE, F.SEND_BASE_UPDATE, F.SEND_IMPORTANT_URLS, F.SENDING,
            SearchBaseNotificationInfo::new
    );
    private static final DataMapper<Pair<SearchBaseNotificationInfo, DateTime>> MAPPER_WITH_TTL = DataMapper.create(
            MAPPER, F.TTL_DATE, Pair::of
    );

    private static class F {
        static final Field<UUID> NOTIFICATION_ID = Fields.uuidField("notification_id");
        static final Field<UUID> RECEIVERS_LIST_ID = Fields.uuidField("receivers_list_id").makeOptional();
        static final Field<DateTime> NOTIFICATION_DATE = Fields.jodaDateTimeField("notification_date");
        static final Field<Boolean> SENDING = Fields.boolField("sending").withDefault(false);
        static final Field<Boolean> SEND_BASE_UPDATE = Fields.boolField("send_base_update").withDefault(true);
        static final Field<Boolean> SEND_IMPORTANT_URLS = Fields.boolField("send_important_urls").withDefault(true);
        static final Field<DateTime> TTL_DATE = Fields.jodaDateTimeField("ttl_date");
    }
}
