'use strict';

var dayjs = require('dayjs');
var customParseFormat = require('../../_virtual/customParseFormat.js');
var UserReports = require('../types/UserReports.js');
var logger = require('./logger.js');
var localsHelper = require('./localsHelper.js');
var ErrorHandler = require('./ErrorHandler/ErrorHandler.js');

dayjs.extend(customParseFormat);
const BAD_REQUEST_STATUSES = [UserReports.RequestStatus.ABORTED, UserReports.RequestStatus.FAILED, UserReports.RequestStatus.EXPIRED];
const IN_PROGRESS_REQUEST_STATUSES = [
    UserReports.RequestStatus.SUBMITTED,
    UserReports.RequestStatus.STARTED,
    UserReports.RequestStatus.PICKED,
];
function findWorstStatusResponse(statusRequests) {
    return Promise.all(statusRequests).then((statusResponses) => {
        const badStatus = statusResponses.find((response) => typeof response.status === 'number' || BAD_REQUEST_STATUSES.includes(response.status));
        if (badStatus) {
            return badStatus;
        }
        const inProgressStatus = statusResponses.find((response) => IN_PROGRESS_REQUEST_STATUSES.includes(response.status));
        if (inProgressStatus) {
            return inProgressStatus;
        }
        return statusResponses[0];
    });
}
const getStatusByReportType = async (services, req, res, token, userId) => {
    const { definitionsPath } = localsHelper.default.getValues(res);
    const { type, reportId, executionId, id, tableId } = req.body;
    const requestedReport = await services.requestedReportService.getReportByExecutionId(executionId, userId);
    const reports = requestedReport?.childExecutionData ?? [];
    let statusRequests = [];
    if (type === UserReports.ReportType.REPORT) {
        reports.push({ executionId, tableId, variantId: id });
        statusRequests = reports.map((executionData) => {
            return services.reportingService.getAsyncReportStatus(token, reportId, executionData.variantId, executionData.executionId || '', definitionsPath, executionData.tableId || '');
        });
    }
    if (type === UserReports.ReportType.DASHBOARD) {
        statusRequests.push(services.dashboardService.getAsyncStatus(token, reportId, id, executionId, tableId, definitionsPath));
    }
    const statusResponse = await findWorstStatusResponse(statusRequests);
    return {
        status: statusResponse.status,
        statusResponse,
    };
};
const getStatus = async ({ req, res, services, }) => {
    const { token, dprUser } = localsHelper.default.getValues(res);
    const { status: currentStatus, requestedAt } = req.body;
    const timeoutExemptStatuses = [UserReports.RequestStatus.READY, UserReports.RequestStatus.EXPIRED, UserReports.RequestStatus.FAILED];
    let status;
    let errorMessage;
    let statusResponse;
    try {
        const statusResponseData = await getStatusByReportType(services, req, res, token, dprUser.id);
        statusResponse = statusResponseData.statusResponse;
        status = statusResponseData.status;
        if (shouldTimeoutRequest({ requestedAt, compareTime: new Date(), durationMins: 15 }) &&
            !timeoutExemptStatuses.includes(status)) {
            throw new Error('Request taking too long. Request Halted');
        }
        if (status === UserReports.RequestStatus.FAILED) {
            logger.default.error(`Error: ${JSON.stringify(statusResponse.error)}`);
            errorMessage = new ErrorHandler.ErrorHandler(statusResponse.error).formatError();
        }
    }
    catch (error) {
        errorMessage = new ErrorHandler.ErrorHandler(error).formatError();
        status = currentStatus === UserReports.RequestStatus.FINISHED ? UserReports.RequestStatus.EXPIRED : UserReports.RequestStatus.FAILED;
    }
    if (typeof status === 'number') {
        status = UserReports.RequestStatus.FAILED;
    }
    return {
        status,
        ...(errorMessage && { errorMessage }),
    };
};
/**
 * Gets the expired status of a viewed report
 * - if reports status was READY/FINISHED
 * - And the new Status is an error status
 * - it means the report has expired
 *
 * @param {AsyncReportUtilsParams} { req, res, services }
 * @return {*}
 */
const getExpiredStatus = async ({ req, res, services }) => {
    const { token, dprUser } = localsHelper.default.getValues(res);
    const { executionId, status: currentStatus } = req.body;
    let errorMessage;
    let status;
    try {
        const statusData = await getStatusByReportType(services, req, res, token, dprUser.id);
        status = statusData.status;
    }
    catch (error) {
        errorMessage = new ErrorHandler.ErrorHandler(error).formatError();
        status =
            currentStatus === UserReports.RequestStatus.READY || currentStatus === UserReports.RequestStatus.FINISHED
                ? UserReports.RequestStatus.EXPIRED
                : UserReports.RequestStatus.FAILED;
    }
    const result = {
        status,
        ...(errorMessage && { errorMessage }),
    };
    return {
        isExpired: result.status === UserReports.RequestStatus.EXPIRED,
        executionId,
    };
};
const shouldTimeoutRequest = ({ requestedAt, compareTime, durationMins, }) => {
    const compareDate = dayjs(compareTime);
    const requestDate = dayjs(requestedAt);
    const result = compareDate.diff(requestDate, 'minutes');
    return result >= durationMins;
};

exports.getExpiredStatus = getExpiredStatus;
exports.getStatus = getStatus;
exports.shouldTimeoutRequest = shouldTimeoutRequest;
//# sourceMappingURL=requestStatusHelper.js.map
