package ru.yandex.webmaster3.worker.notifications;

import java.util.Map;
import java.util.UUID;

import com.google.common.annotations.VisibleForTesting;
import lombok.AllArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.text.StrSubstitutor;
import org.joda.time.DateTime;
import org.joda.time.LocalDate;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.util.Either;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskState;
import ru.yandex.webmaster3.core.worker.task.PeriodicTaskType;
import ru.yandex.webmaster3.core.worker.task.TaskResult;
import ru.yandex.webmaster3.storage.notifications.dao.EuEmailYDao;
import ru.yandex.webmaster3.storage.util.ydb.YdbYqlService;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

/**
 * @author akhazhoyan 02/2019
 */
@Slf4j
@RequiredArgsConstructor
@Component
public final class ImportEuEmailsTask extends PeriodicTask<ImportEuEmailsTask.State> {

    private static final String QUERY_PREFIX = "\n" +
            "$current_timestamp = ${CURRENT_TIMESTAMP}ul;\n" +
            "$update_date = DateTime::FromMilliseconds(cast($current_timestamp as Uint64));\n";

    public static final String DATA_SELECT_QUERY = "SELECT \n" +
            "            cast(email as Utf8) as email_address,\n" +
            "            cast($update_date as Timestamp) as imported_date,\n" +
            "        FROM ${SOURCE_TABLE}";

    private final YdbYqlService ydbYqlService;
    private final EuEmailYDao euEmailYDao;
    private final EuEmailService euEmailService;
    @Value("${external.yt.service.hahn}://home/crypta/public/ids_storage/email/emails_eu")
    private YtPath cryptaTablePath;

    @Override
    public Result run(UUID runId) throws Exception {
        Either<String, State> stateEither = initStateAndCheck();
        if (stateEither.isLeft()) {
            log.error(stateEither.getLeftUnsafe());
            return new Result(TaskResult.SUCCESS);
        }
        final State st = stateEither.getRightUnsafe();
        setState(st);
        DateTime now = new DateTime(st.today.getYear(), st.today.getMonthOfYear(), st.today.getDayOfMonth(), 0, 0);
        StrSubstitutor substitutor = new StrSubstitutor(Map.of(
                "CURRENT_TIMESTAMP", String.valueOf(now.getMillis()),
                "SOURCE_TABLE", cryptaTablePath.toYqlPath()
        ));
        ydbYqlService.importToYdb(euEmailYDao.getTablePath(), substitutor.replace(DATA_SELECT_QUERY), substitutor.replace(QUERY_PREFIX));
//        euEmailYDao.deleteBefore(now);
        euEmailService.setLastImportDate(st.today);

        return new Result(TaskResult.SUCCESS);
    }

    @VisibleForTesting
    @AllArgsConstructor
    static class State implements PeriodicTaskState {
        final LocalDate today;
        final LocalDate lastUpdateDate;
    }

    @VisibleForTesting
    Either<String, State> initStateAndCheck() {
        LocalDate lastImportDate = euEmailService.lastImportDate();
        LocalDate today = LocalDate.now();
        if (!lastImportDate.isBefore(today)) {
            return Either.left("The table was already imported today, skipping");
        }
        return Either.right(new State(today, lastImportDate));
    }

    @Override
    public PeriodicTaskType getType() {
        return PeriodicTaskType.IMPORT_EU_EMAILS;
    }

    @Override
    public TaskSchedule getSchedule() {
        return TaskSchedule.startByCron("0 13 * * * *");
    }
}
