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

import java.util.Map;
import java.util.stream.Collector;
import java.util.stream.Collectors;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.Setter;
import org.joda.time.Duration;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.data.WebmasterHostId;
import ru.yandex.webmaster3.core.util.WMC1688Workaround;
import ru.yandex.webmaster3.storage.clickhouse.ClickhouseTableInfo;
import ru.yandex.webmaster3.storage.clickhouse.TableProvider;
import ru.yandex.webmaster3.storage.clickhouse.TableType;
import ru.yandex.webmaster3.storage.util.clickhouse2.AbstractClickhouseDao;
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.ClickhouseQueryContext;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.QueryBuilder;
import ru.yandex.webmaster3.storage.util.clickhouse2.query.Statement;

@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class DisplayNameCHDao extends AbstractClickhouseDao {

    private static final Duration TIMEOUT = Duration.standardSeconds(90);
    private static final String PREFIX_TABLE_NAME = "display_names_";
    private static final String DATABASE = DB_WEBMASTER3;
    public static final CHTable TABLE = CHTable.builder()
            .database(DATABASE)
            .name(PREFIX_TABLE_NAME + "%s")
            .sharded(false)
            .partitionBy("toYYYYMM(" + F.DATE + ")")
            .keyField(F.DATE, CHPrimitiveType.Date)
            .keyField(F.HOST, CHPrimitiveType.String)
            .field(F.DISPLAY_NAME, CHPrimitiveType.String)
            .build();
    private final static Collector<CHRow, ?, Map<WebmasterHostId, String>> COLLECTOR =
            Collectors.toMap(
                    x -> getNullableHostId(x, F.HOST),
                    x -> getNullableString(x, F.DISPLAY_NAME),
                    (oldValue, newValue) -> newValue
            );


    @Setter
    private TableProvider tableStorage;

    @Setter
    @Getter
    private boolean isMdb;

    public String getTableVersion() {
        return tableStorage.getTable(TableType.DISPLAY_NAME).getLocalTableName();
    }

    public String getDisplayName(WebmasterHostId host) {
        final ClickhouseTableInfo table = tableStorage.getTable(TableType.DISPLAY_NAME);
        final Statement st = QueryBuilder.select(F.DISPLAY_NAME)
                .from(table.getLocalTableName())
                .where(QueryBuilder.eq(F.HOST, host));
        return getClickhouseServer().queryOne(st.toString(),
                r -> r.getString(F.DISPLAY_NAME)).map(WMC1688Workaround::apply).orElse(null);
    }

    public Map<WebmasterHostId, String> collectAll(String tableVersion) {
        final Statement select = QueryBuilder.select(F.HOST, F.DISPLAY_NAME).from(tableVersion);
        return getClickhouseServer().collectAll(ClickhouseQueryContext.useDefaults()
                        .setTimeout(TIMEOUT).setCredentials(getClickhouseServer().getServiceUserCredentials()),
                select.toString(), COLLECTOR);
    }

    public static String getDatabase() {
        return DATABASE;
    }

    public static String getPrefix() {
        return PREFIX_TABLE_NAME;
    }


    public interface F {
        String DATE = "date";
        String HOST = "host";
        String DISPLAY_NAME = "display_name";
    }
}
