"use strict";
Object.defineProperty(exports, "__esModule", {
    value: true
});
function _export(target, all) {
    for(var name in all)Object.defineProperty(target, name, {
        enumerable: true,
        get: Object.getOwnPropertyDescriptor(all, name).get
    });
}
_export(exports, {
    get extractErrorFromFetchResponse () {
        return extractErrorFromFetchResponse;
    },
    get isRecoverable () {
        return isRecoverable;
    }
});
const _constants = require("@tamanu/constants");
const _BaseError = require("./BaseError");
const _constants1 = require("./constants");
const _Problem = require("./Problem");
const _errors = require("./errors");
function isRecoverable(error) {
    if (!(error instanceof _BaseError.BaseError)) {
        return false;
    }
    if (error instanceof _errors.RemoteUnreachableError || error.type === _constants1.ERROR_TYPE.RATE_LIMITED) {
        return true;
    }
    if ([
        _constants1.ERROR_TYPE.AUTH_CREDENTIAL_INVALID,
        _constants1.ERROR_TYPE.AUTH_CREDENTIAL_MISSING,
        _constants1.ERROR_TYPE.CLIENT_INCOMPATIBLE,
        _constants1.ERROR_TYPE.STORAGE_INSUFFICIENT
    ].includes(error.type)) {
        return false;
    }
    if (error.status >= 400 && error.status < 500) {
        return false;
    }
    if (error.detail?.includes('Sync session')) {
        return false;
    }
    return true;
}
function convertLegacyError(error, response) {
    let legacyMessage = error?.message || response.status.toString();
    let errorName;
    let ErrorClass;
    switch(error?.status ?? response.status){
        case 400:
            {
                ErrorClass = _errors.UnknownError;
                if (response.headers.has('x-max-client-version') || response.headers.has('x-min-client-version')) {
                    ErrorClass = _errors.ClientIncompatibleError;
                } else if (error.name) {
                    errorName = error.name;
                }
                break;
            }
        case 401:
            {
                legacyMessage = error?.message || 'Failed authentication';
                ErrorClass = _errors.BadAuthenticationError;
                break;
            }
        case 403:
            ErrorClass = _errors.ForbiddenError;
            break;
        case 404:
            ErrorClass = _errors.NotFoundError;
            break;
        case 409:
            ErrorClass = _errors.EditConflictError;
            break;
        default:
            ErrorClass = _errors.UnknownError;
            if (error.name) {
                errorName = error.name;
            }
    }
    const problem = _Problem.Problem.fromError(new ErrorClass(legacyMessage));
    if (error.name || errorName) {
        // ! -> we know from the condition that at least one of error.name or errorName is defined
        problem.title = errorName ?? error.name;
        problem.message = legacyMessage;
    }
    problem.extra.set('legacy-error', error);
    if (problem.type === _constants1.ERROR_TYPE.CLIENT_INCOMPATIBLE) {
        const minAppVersion = response.headers.get('x-min-client-version');
        if (minAppVersion) problem.extra.set(_constants.VERSION_MINIMUM_PROBLEM_KEY, minAppVersion);
        const maxAppVersion = response.headers.get('x-max-client-version');
        if (maxAppVersion) problem.extra.set(_constants.VERSION_MAXIMUM_PROBLEM_KEY, maxAppVersion);
    }
    return problem;
}
async function readResponse(response, logger = console) {
    let data;
    try {
        data = await response.text();
    } catch (err) {
        logger.warn('readResponseError: Error decoding text', err);
        return _Problem.Problem.fromError(new _errors.ValidationError('Invalid text encoding in response').withCause(err));
    }
    if (data.length === 0) {
        return new _Problem.Problem(_constants1.ERROR_TYPE.REMOTE, 'Server error', response.status, 'No response data');
    }
    let json;
    try {
        json = JSON.parse(data);
    } catch (err) {
        logger.warn('readResponseError: Error parsing JSON', err);
        return _Problem.Problem.fromError(new _errors.ValidationError('Invalid JSON in response').withCause(err));
    }
    const problem = _Problem.Problem.fromJSON(json);
    if (problem) {
        return problem;
    }
    if (json.error) {
        return convertLegacyError(json.error, response);
    }
    const unk = new _Problem.Problem(_constants1.ERROR_TYPE.REMOTE, 'Server error', response.status, 'Unknown response format');
    unk.extra.set('response-data', json);
    return unk;
}
function messageField(problem) {
    if (!problem.detail) {
        return problem.title;
    }
    if (problem.detail === problem.title) {
        return problem.detail;
    }
    return `${problem.title}: ${problem.detail}`;
}
async function extractErrorFromFetchResponse(response, url, logger = console) {
    const problem = await readResponse(response, logger);
    problem.extra.set('request-url', url);
    problem.response = response;
    problem.message = messageField(problem);
    return problem;
}

//# sourceMappingURL=extractErrorFromFetchResponse.js.map