package ru.yandex.webmaster3.worker.checklist.badad;

import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
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.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.checklist.dao.YaBrowserBadAdRecheckQueueYDao;
import ru.yandex.webmaster3.storage.util.yt.*;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
import java.util.UUID;

/**
 * Created by Oleg Bazdyrev on 11/12/2017.
 */
public class UploadYaBrowserBadAdsRechecksTask extends PeriodicTask<PeriodicTaskState> {

    private static final String EXPORT_TABLE_SCHEMA = "[" +
            "{'name': 'host', 'type': 'string'}, " +
            "{'name': 'formats', 'type': 'any'}, " +
            "{'name': 'timestamp', 'type': 'int64'}]";
    private static JsonNode EXPORT_TABLE_SCHEMA_JSON;

    static {
        try {
            EXPORT_TABLE_SCHEMA_JSON = new ObjectMapper().configure(JsonParser.Feature.ALLOW_SINGLE_QUOTES, true)
                    .readTree(EXPORT_TABLE_SCHEMA);
        } catch (IOException e) {
            // не должно быть никаких ошибок
            throw new RuntimeException(e);
        }
    }

    private YaBrowserBadAdRecheckQueueYDao yaBrowserBadAdRecheckQueueYDao;
    private YtService ytService;

    private YtPath tablePath;

    @Override
    public Result run(UUID runId) throws Exception {
        Set<UUID> requests = new HashSet<>();
        YtTableData tableData = ytService.prepareTableData("badad_recheck_queue", tableWriter -> {
            try {
                yaBrowserBadAdRecheckQueueYDao.forEach(recheckRecord -> {
                    try {
                        tableWriter.column("host", IdUtils.hostIdToUrl(recheckRecord.getHostId()));
                        tableWriter.column("timestamp", recheckRecord.getDate().getMillis() / 1000);
                        tableWriter.columnObject("formats", recheckRecord.getFormats());
                        tableWriter.rowEnd();
                        requests.add(recheckRecord.getId());
                    } catch (YtException e) {
                        e.printStackTrace();
                    }
                });
            } catch (WebmasterYdbException e) {
                throw new WebmasterException("Error reading recheck queue",
                        new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
            }
        });

        ytService.inTransaction(tablePath).execute(cypressService -> {
            if (!cypressService.exists(tablePath)) {
                YtNodeAttributes attributes = new YtNodeAttributes();
                attributes.getAttributes().put("schema", EXPORT_TABLE_SCHEMA_JSON);
                cypressService.create(tablePath, YtNode.NodeType.TABLE, true, attributes, true);
            }
            cypressService.writeTable(tablePath, tableData, true);
            return true;
        });

        // удаляем старье
        if (requests.size() > 0) {
            yaBrowserBadAdRecheckQueueYDao.deleteRecords(requests);
        }
        return new Result(TaskResult.SUCCESS);
    }

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

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

    @Required
    public void setYaBrowserBadAdRecheckQueueYDao(YaBrowserBadAdRecheckQueueYDao yaBrowserBadAdRecheckQueueYDao) {
        this.yaBrowserBadAdRecheckQueueYDao = yaBrowserBadAdRecheckQueueYDao;
    }

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

    @Required
    public void setTablePath(YtPath tablePath) {
        this.tablePath = tablePath;
    }
}
