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

import java.util.List;
import java.util.stream.Collectors;

import com.fasterxml.jackson.annotation.JsonCreator;
import com.google.common.collect.ImmutableList;
import lombok.NonNull;
import org.apache.commons.lang3.tuple.Pair;

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.notification.LanguageEnum;
import ru.yandex.webmaster3.storage.user.message.content.MessageContent;
import ru.yandex.webmaster3.storage.user.notification.NotificationType;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHPrimitiveType;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHRow;
import ru.yandex.webmaster3.storage.util.clickhouse2.CHTable;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseException;
import ru.yandex.webmaster3.storage.util.clickhouse2.ClickhouseQueryContext;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.OrderBy;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.Statement;

/**
 * Created by kravchenko99 on 2020-02-18.
 */

// нужно для отправки сообщений про изменение displayName
public class DisplayNameChangesCHDao extends AbstractNotificationsChangesCHDao {

    public static final CHTable TABLE = CHTable.builder()
            .database(DB_WEBMASTER3_NOTIFICATIONS)
            .name("display_name_changes_%s")
            .partitionBy("toYYYYMM(" + F.DATE + ")")
            .keyField(F.DATE, CHPrimitiveType.Date)
            .keyField(F.HOST_ID, CHPrimitiveType.String)
            .field(F.USER_ID, CHPrimitiveType.UInt64)
            .field(F.FIO, CHPrimitiveType.String)
            .field(F.EMAIL, CHPrimitiveType.String)
            .field(F.LANGUAGE, CHPrimitiveType.String)
            .field(F.CHANNEL_EMAIL, CHPrimitiveType.UInt8)
            .field(F.LOGIN, CHPrimitiveType.String)
            .field(F.CHANNEL_SERVICE, CHPrimitiveType.UInt8)
            .field(F.NEW_DISPLAY_NAME, CHPrimitiveType.String)
            .build();
    private static final List<Pair<Object, OrderBy.Direction>> ORDER_BY = ImmutableList.of(
            Pair.of(F.HOST_ID, OrderBy.Direction.ASC),
            Pair.of(F.USER_ID, OrderBy.Direction.ASC)
    );



    public List<Pair<WebmasterHostId, String>> getAllHostsIdWithNewDisplayName(String tableId) throws ClickhouseException {
        ClickhouseQueryContext.Builder context = ClickhouseQueryContext.useDefaults()
                .setHost(getClickhouseServer().pickAliveHostOrFail(SHARD));
        String tableName = getTable().replicatedMergeTreeTableName(0, tableId);

        Statement statement = QueryBuilder
                .selectDistinct(F.HOST_ID, F.NEW_DISPLAY_NAME)
                .from(getTable().getDatabase(), tableName);

        return getClickhouseServer().collectAll(context, statement.toString(),
                Collectors.mapping(row -> Pair.of(row.getHostId(F.HOST_ID), row.getString(F.NEW_DISPLAY_NAME)),
                        Collectors.toList()));
    }

    @Override
    public CHTable getTable() {
        return TABLE;
    }

    @Override
    public List<Pair<Object, OrderBy.Direction>> getOrderBy() {
        return ORDER_BY;
    }

    @Override
    protected AbstractMessage getMapper(CHRow row) {
        return new Message(row);
    }


    public interface F {
        String DATE = "date";
        String HOST_ID = "host_id";
        String USER_ID = "user_id";
        String LOGIN = "login";
        String FIO = "fio";
        String EMAIL = "email";
        String LANGUAGE = "language";
        String CHANNEL_EMAIL = "channel_email";
        String CHANNEL_SERVICE = "channel_service";
        String NEW_DISPLAY_NAME = "new_display_name";
    }

    public static class Message extends AbstractMessage {

        @JsonCreator
        public Message(@NonNull CHRow row) {
            super(
                    row.getHostId(F.HOST_ID),
                    NotificationType.SITE_DISPLAY_NAME,
                    row.getLongUnsafe(F.USER_ID),
                    row.getInt(F.CHANNEL_EMAIL) > 0,
                    row.getInt(F.CHANNEL_SERVICE) > 0,
                    row.getString(F.EMAIL),
                    row.getString(F.FIO),
                    LanguageEnum.fromString(row.getString(F.LANGUAGE)),
                    row.getString(F.LOGIN)
            );
        }

        public MessageContent getContent() {
            return new MessageContent.HostDisplayNameChanged(hostId);
        }
    }
}
