package ru.yandex.webmaster3.worker.turbo.export;

import java.util.UUID;

import lombok.Getter;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedSettings;
import ru.yandex.webmaster3.core.turbo.model.feed.TurboFeedState;
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.turbo.dao.TurboFeedsSettingsYDao;
import ru.yandex.webmaster3.storage.util.yt.TableWriter;
import ru.yandex.webmaster3.storage.util.yt.YtColumn;
import ru.yandex.webmaster3.storage.util.yt.YtCypressService;
import ru.yandex.webmaster3.storage.util.yt.YtException;
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 kravchenko99
 * @date 5/12/22
 */


@Slf4j
@RequiredArgsConstructor(onConstructor_ = @Autowired)
@Component
public class ExportTurboFeedsSettingsTask extends PeriodicTask<ExportTurboFeedsSettingsTask.TaskState> {

    private final TurboFeedsSettingsYDao turboFeedsSettingsYDao;
    private final YtService ytService;
    @Value("${external.yt.service.hahn.root.default}/export/turbo/feeds_settings")
    private YtPath ytPath;

    @Override
    public Result run(UUID runId) throws Exception {
        YtTableData tableData = ytService.prepareTableData("turbo_feeds_settnigs", tableWriter -> {
            turboFeedsSettingsYDao.forEach(info -> {
                if (info.getState() == TurboFeedState.DELETED) {
                    return;
                }
                write(info, tableWriter);
            });
        });
        try {
            ytService.inTransaction(ytPath).execute(cypressService -> uploadToYt(cypressService, ytPath, tableData));
        } finally {
            tableData.delete();
        }
        return new Result(TaskResult.SUCCESS);
    }

    private static boolean uploadToYt(YtCypressService cypressService, YtPath path,
                                      YtTableData tableData) throws YtException {
        YtNodeAttributes attributes = new YtNodeAttributes().setSchema(F.SCHEMA);
        cypressService.create(path, YtNode.NodeType.TABLE, true, attributes, true);
        cypressService.writeTable(path, tableData, false);
        return true;
    }

    private static void write(TurboFeedSettings info, TableWriter tw) throws YtException {
            F.DOMAIN.set(tw, info.getDomain());
            F.URL.set(tw, info.getUrl());
            F.TYPE.set(tw, info.getType().name());
            F.STATE.set(tw, info.getState().name());
            F.ACTIVE.set(tw, info.isActive());
            F.ADD_DATE.set(tw, info.getAddDate() == null ? null : info.getAddDate().getMillis());
            F.VALIDATE_DATE.set(tw, info.getValidateDate() == null ? null : info.getValidateDate().getMillis());
            F.BUSINESS_ID.set(tw, info.getBusinessId());
            F.PARTNER_ID.set(tw, info.getPartnerId());
            F.FEED_ID.set(tw, info.getFeedId());
            F.STATUS_SCC.set(tw, info.getStatus() == null ? null : info.getStatus().name());
            F.ERROR_SCC.set(tw, info.getErrorScc());
            F.TIME_SCC.set(tw, info.getTimeScc() == null ? null : info.getTimeScc().getMillis());
            tw.rowEnd();
    }

    private interface F {
        YtSchema SCHEMA = new YtSchema();
        YtColumn<String> DOMAIN = SCHEMA.addColumn("domain", YtColumn.Type.STRING);
        YtColumn<String> URL = SCHEMA.addColumn("url", YtColumn.Type.STRING);
        YtColumn<String> STATE = SCHEMA.addColumn("state", YtColumn.Type.STRING);
        YtColumn<String> TYPE = SCHEMA.addColumn("type", YtColumn.Type.STRING);
        YtColumn<Boolean> ACTIVE = SCHEMA.addColumn("active", YtColumn.Type.BOOLEAN);
        YtColumn<Long> ADD_DATE = SCHEMA.addColumn("add_date", YtColumn.Type.INT_64);
        YtColumn<Long> VALIDATE_DATE = SCHEMA.addColumn("validate_date", YtColumn.Type.INT_64);
        YtColumn<Long> BUSINESS_ID = SCHEMA.addColumn("business_id", YtColumn.Type.INT_64);
        YtColumn<Long> PARTNER_ID = SCHEMA.addColumn("partner_id", YtColumn.Type.INT_64);
        YtColumn<Long> FEED_ID = SCHEMA.addColumn("feed_id", YtColumn.Type.INT_64);
        YtColumn<String> STATUS_SCC = SCHEMA.addColumn("status_scc", YtColumn.Type.STRING);
        YtColumn<String> ERROR_SCC = SCHEMA.addColumn("error_scc", YtColumn.Type.STRING);
        YtColumn<Long> TIME_SCC = SCHEMA.addColumn("time_scc", YtColumn.Type.INT_64);
    }

    @Getter
    public static class TaskState implements PeriodicTaskState {

    }

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

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