package ru.yandex.webmaster3.worker.regions;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Required;
import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.util.IdUtils;
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.host.moderation.regions.dao.HostModeratedRegionsYDao;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.util.yt.YtException;
import ru.yandex.webmaster3.storage.util.yt.YtNode;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.util.yt.YtService;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;
import ru.yandex.webmaster3.worker.extended.http.codes.export.ExtendedHttpCodesExportTask;

import java.util.UUID;

/**
 * @author avhaliullin
 */
public class HostRegionUploadTask extends PeriodicTask<ExtendedHttpCodesExportTask.TaskState> {
    private static final Logger log = LoggerFactory.getLogger(HostRegionUploadTask.class);

    private static final int WMC_REGION_OFFSET = 31000000;
    private static final String FIELD_HOST = "host";
    private static final String FIELD_REGION = "region";

    private HostModeratedRegionsYDao hostModeratedRegionsYDao;
    private YtService ytService;
    // @see WMC-3522 таблица в YT для экспорта регионов
    private YtPath outputYtTablePath;

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

    @Override
    public Result run(UUID runId) throws Exception {
        // экспортируем в таблицу в YT
        exportRegionsToYtTable();
        return new Result(TaskResult.SUCCESS);
    }

    private void exportRegionsToYtTable() throws Exception {
        ytService.inTransaction(outputYtTablePath).execute(cypressService -> {
            log.info("Uploading moderated host regions started, writing to YT-table {}", outputYtTablePath);
            // создадим табличку, затирая старые данные
            cypressService.create(outputYtTablePath, YtNode.NodeType.TABLE, true, null, true);
            // пишем новые данные
            cypressService.writeTable(outputYtTablePath, tableWriter -> {
                try {
                    hostModeratedRegionsYDao.forEach(regions -> {
                        for (Integer r : regions.getRegions()) {
                            tableWriter.column(FIELD_HOST, IdUtils.toRobotHostString(regions.getHostId()));
                            tableWriter.column(FIELD_REGION, WMC_REGION_OFFSET + r);
                            tableWriter.rowEnd();
                        }
                    });
                } catch (WebmasterYdbException e) {
                    throw new WebmasterException("Failed to obtain moderated regions for export",
                            new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
                } catch (YtException e) {
                    throw new WebmasterException("Failed to write moderated regions for export",
                            new WebmasterErrorResponse.YTServiceErrorResponse(getClass(), e), e);
                }
            });
            log.info("Successfully uploaded moderated host regions to YT-table {}", outputYtTablePath);
            return true;
        });
    }

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

    @Required
    public void setHostModeratedRegionsYDao(HostModeratedRegionsYDao hostModeratedRegionsYDao) {
        this.hostModeratedRegionsYDao = hostModeratedRegionsYDao;
    }

    @Required
    public void setYtService(YtService ytService) {
        this.ytService = ytService;
    }

    @Required
    public void setOutputYtTablePath(YtPath outputYtTablePath) {
        this.outputYtTablePath = outputYtTablePath;
    }

    public static class TaskState implements PeriodicTaskState {
    }
}
