package ru.yandex.webmaster3.storage.indexing2.internal.dao;

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

import com.fasterxml.jackson.core.type.TypeReference;
import org.joda.time.DateTime;
import org.joda.time.Instant;
import org.joda.time.LocalDate;
import org.springframework.stereotype.Repository;

import ru.yandex.webmaster3.storage.indexing2.internal.data.IndexingSamplesImportType;
import ru.yandex.webmaster3.storage.indexing2.internal.data.IndexingSamplesTableInfo;
import ru.yandex.webmaster3.storage.indexing2.internal.data.IndexingSamplesTableState;
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.yt.YtPath;

/**
 * @author avhaliullin
 */
@Repository
public class IndexingSamplesTablesYDao extends AbstractYDao implements IndexingSamplesTablesRepository {
    private static final TypeReference<Set<LocalDate>> LOCAL_DATE_SET_REFERENCE = new TypeReference<>() {
    };

    public IndexingSamplesTablesYDao() {
        super(PREFIX_IMPORTER, "indexing_samples_tables");
    }

    @Override
    public void insertState(IndexingSamplesTableInfo tableInfo) {
        upsert(
                F.IMPORT_TYPE.value(tableInfo.getImportType()),
                F.TABLE_DATE.value(tableInfo.getTableDate()),
                F.UPDATE_TIME.value(tableInfo.getUpdateTime()),
                F.LAST_UPDATE.value(DateTime.now()),
                F.IS_TAIL.value(tableInfo.isTail()),
                F.REPLACING_CH_TABLES.value(tableInfo.getReplacingCHTables()),
                F.SOURCE_YT_PATH.value(tableInfo.getSourceYtPath()),
                F.STATE.value(tableInfo.getState()),
                F.PREPARED_YT_TABLES.value(tableInfo.getPreparedYtTables()),
                F.IMPORT_MANAGER_TASK_ID.value(tableInfo.getImportManagerTaskId()),
                F.REPLICATION_MANAGER_TASK_ID.value(tableInfo.getReplicationManagerTaskId()),
                F.TMP_TABLE_NAME.value(tableInfo.getTmpTableName())
        ).execute();
    }

    @Override
    public List<IndexingSamplesTableInfo> listAllTables() {
        return select(MAPPER).queryForList(); // TODO pagination?
    }

    private static final DataMapper<IndexingSamplesTableInfo> MAPPER = DataMapper.create(
            F.IMPORT_TYPE, F.TABLE_DATE, F.IS_TAIL, F.UPDATE_TIME, F.REPLACING_CH_TABLES, F.SOURCE_YT_PATH, F.STATE,
            F.PREPARED_YT_TABLES, F.IMPORT_MANAGER_TASK_ID, F.REPLICATION_MANAGER_TASK_ID, F.TMP_TABLE_NAME,
            IndexingSamplesTableInfo::new
    );

    private interface F {
        Field<IndexingSamplesImportType> IMPORT_TYPE = Fields.stringEnumField("import_type", IndexingSamplesImportType.R);
        Field<LocalDate> TABLE_DATE = Fields.jodaDateField("table_date");
        Field<Instant> UPDATE_TIME = Fields.jodaInstantField("update_time");
        Field<DateTime> LAST_UPDATE = Fields.jodaDateTimeField("last_update").makeOptional();
        Field<Boolean> IS_TAIL = Fields.boolField("is_tail");
        Field<Set<LocalDate>> REPLACING_CH_TABLES = Fields.jsonField2("replacing_ch_fields", LOCAL_DATE_SET_REFERENCE).makeOptional();
        Field<YtPath> SOURCE_YT_PATH = Fields.ytPathField("source_yt_path").makeOptional();
        Field<IndexingSamplesTableState> STATE = Fields.stringEnumField("state", IndexingSamplesTableState.R).makeOptional();
        Field<List<YtPath>> PREPARED_YT_TABLES = Fields.jsonField2("prepared_yt_tables", Fields.YT_PATH_LIST_REFERENCE).makeOptional();
        Field<UUID> IMPORT_MANAGER_TASK_ID = Fields.uuidField("import_manager_task_id").makeOptional();
        Field<UUID>  REPLICATION_MANAGER_TASK_ID = Fields.uuidField("replication_manager_task_id").makeOptional();
        Field<String> TMP_TABLE_NAME = Fields.stringField("tmp_table_name").makeOptional();
    }
}
