package ru.yandex.webmaster3.worker.http;

import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import org.joda.time.Instant;
import org.springframework.beans.factory.annotation.Autowired;

import ru.yandex.webmaster3.core.WebmasterException;
import ru.yandex.webmaster3.core.http.Action;
import ru.yandex.webmaster3.core.http.ActionRequest;
import ru.yandex.webmaster3.core.http.ActionResponse;
import ru.yandex.webmaster3.core.http.WebmasterErrorResponse;
import ru.yandex.webmaster3.core.searchbase.SearchBaseDates;
import ru.yandex.webmaster3.core.searchbase.SearchBaseUpdateInfo;
import ru.yandex.webmaster3.storage.util.ydb.exception.WebmasterYdbException;
import ru.yandex.webmaster3.storage.searchbase.SearchBaseUpdatesService;
import ru.yandex.webmaster3.storage.searchurl.offline.dao.SearchBaseImportTablesYDao;
import ru.yandex.webmaster3.storage.searchurl.offline.data.SearchBaseImportInfo;
import ru.yandex.webmaster3.storage.searchurl.offline.data.SearchBaseImportStageEnum;
import ru.yandex.webmaster3.storage.searchurl.offline.data.SearchBaseImportTaskType;

/**
 * @author avhaliullin
 */
public class ListSearchBaseImportsAction extends Action<ListSearchBaseImportsAction.Request, ListSearchBaseImportsAction.Response> {
    @Autowired
    private SearchBaseImportTablesYDao searchBaseImportTablesYDao;
    @Autowired
    private SearchBaseUpdatesService searchBaseUpdatesService;

    @Override
    public Response process(Request request) throws WebmasterException {
        try {
            SearchBaseDates searchBaseDates = searchBaseUpdatesService.getSearchBaseUpdates();
            List<ImportTaskInfo> result =
                    searchBaseImportTablesYDao.listAllTasks()
                            .stream()
                            .filter(task -> task.getStage() != SearchBaseImportStageEnum.DELETED)
                            .sorted(Comparator.comparing(SearchBaseImportInfo::getTaskType).thenComparing(Comparator.comparing(SearchBaseImportInfo::getSearchBaseDate)))
                            .map(task -> {
                                SearchBaseUpdateInfo baseUpdateInfo = searchBaseDates.getCollectionDate2Info().get(task.getSearchBaseDate());
                                Instant switchDate = baseUpdateInfo == null ? null : baseUpdateInfo.getBaseSwitchDate();
                                return new ImportTaskInfo(
                                        task.getSearchBaseDate(),
                                        switchDate,
                                        task.getTaskType(),
                                        task.isPaused(),
                                        task.getClickhouseDc(),
                                        task.getStage()
                                );
                            })
                            .collect(Collectors.toList());
            return new Response(result);
        } catch (WebmasterYdbException e) {
            throw new WebmasterException("Failed to list import tasks",
                    new WebmasterErrorResponse.YDBErrorResponse(getClass(), e), e);
        }
    }

    public static class Request implements ActionRequest {
    }

    public static class Response implements ActionResponse.NormalResponse {
        private final List<ImportTaskInfo> imports;

        public Response(List<ImportTaskInfo> imports) {
            this.imports = imports;
        }

        public List<ImportTaskInfo> getImports() {
            return imports;
        }
    }

    public static class ImportTaskInfo {
        private final Instant collectionDate;
        private final Instant switchDate;
        private final SearchBaseImportTaskType taskType;
        private final boolean paused;
        private final String clickhouseDc;
        private final SearchBaseImportStageEnum stage;

        public ImportTaskInfo(Instant collectionDate, Instant switchDate, SearchBaseImportTaskType taskType, boolean paused, String clickhouseDc, SearchBaseImportStageEnum stage) {
            this.collectionDate = collectionDate;
            this.switchDate = switchDate;
            this.taskType = taskType;
            this.paused = paused;
            this.clickhouseDc = clickhouseDc;
            this.stage = stage;
        }

        public Instant getCollectionDate() {
            return collectionDate;
        }

        public Instant getSwitchDate() {
            return switchDate;
        }

        public SearchBaseImportTaskType getTaskType() {
            return taskType;
        }

        public boolean isPaused() {
            return paused;
        }

        public String getClickhouseDc() {
            return clickhouseDc;
        }

        public SearchBaseImportStageEnum getStage() {
            return stage;
        }
    }

}
