package ru.yandex.webmaster3.worker.checklist;

import java.util.Arrays;
import java.util.UUID;

import lombok.RequiredArgsConstructor;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

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.checklist.service.AllHostsProblemsService;
import ru.yandex.webmaster3.storage.util.yt.YtColumn;
import ru.yandex.webmaster3.storage.util.yt.YtNode;
import ru.yandex.webmaster3.storage.util.yt.YtNodeAttributes;
import ru.yandex.webmaster3.storage.util.yt.YtPath;
import ru.yandex.webmaster3.storage.util.yt.YtSchema;
import ru.yandex.webmaster3.storage.util.yt.YtService;
import ru.yandex.webmaster3.storage.util.yt.YtTableData;
import ru.yandex.webmaster3.worker.PeriodicTask;
import ru.yandex.webmaster3.worker.TaskSchedule;

/**
 * @author lester
 */
@Service
@RequiredArgsConstructor(onConstructor_ = @Autowired)
public class UploadSiteProblemsTask extends PeriodicTask<PeriodicTaskState> {

    private final AllHostsProblemsService allHostsProblemsService;
    private final YtService ytService;
    @Value("${external.yt.service.hahn.root.default}/export/checklist")
    private YtPath hahnWorkDir;
    @Value("${external.yt.service.arnold.root.default}/export/checklist")
    private YtPath arnoldWorkDir;

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

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

    @Override
    public PeriodicTask.Result run(UUID runId) throws Exception {
        YtTableData tableData = ytService.prepareTableData("site-problems", tableWriter -> {
            allHostsProblemsService.forEachProblem(problemInfo -> {
                if (problemInfo.getState().isPresent()) {
                    F.HOST.set(tableWriter, IdUtils.toHostString(problemInfo.getHostId(), true, false, false));
                    F.PROBLEM_TYPE.set(tableWriter, (long) problemInfo.getProblemType().value());
                    F.PROBLEM_TYPE_STR.set(tableWriter, problemInfo.getProblemType().name());
                    F.LAST_UPDATE.set(tableWriter, problemInfo.getLastUpdate() == null ? null : problemInfo.getLastUpdate().getMillis());
                    F.ACTUAL_SINCE.set(tableWriter, problemInfo.getActualSince() == null ? null : problemInfo.getActualSince().getMillis());
                    tableWriter.rowEnd();
                }
            });
        });

        for (YtPath workDir : Arrays.asList(hahnWorkDir, arnoldWorkDir)) {
            YtPath tablePath = YtPath.path(workDir, "site-problems");
            ytService.inTransaction(tablePath).execute(cypressService -> {
                cypressService.remove(tablePath, false, true);
                cypressService.create(tablePath, YtNode.NodeType.TABLE, true, new YtNodeAttributes().setSchema(F.SCHEMA), true);
                cypressService.writeTable(tablePath, tableData);
                cypressService.waitFor(cypressService.sort(tablePath, tablePath, F.HOST.getName(), F.PROBLEM_TYPE.getName()));
                return true;
            });
        }

        return new PeriodicTask.Result(TaskResult.SUCCESS);
    }

    private interface F {
        YtSchema SCHEMA = new YtSchema();
        YtColumn<String> HOST = SCHEMA.addColumn("Host", YtColumn.Type.STRING);
        YtColumn<Long> PROBLEM_TYPE = SCHEMA.addColumn("Problem", YtColumn.Type.UINT_64);
        YtColumn<String> PROBLEM_TYPE_STR = SCHEMA.addColumn("ProblemType", YtColumn.Type.STRING);
        YtColumn<Long> LAST_UPDATE = SCHEMA.addColumn("LastUpdate", YtColumn.Type.UINT_64);
        YtColumn<Long> ACTUAL_SINCE = SCHEMA.addColumn("ActualSince", YtColumn.Type.UINT_64);
    }
}
