import QueryError from "../../errors/QueryError.js";
import OpticReadFailureCause from "./OpticReadFailureCause.js";
import OpticReadFailureContext from "./OpticReadFailureContext.js";
import OpticReadTarget from "./OpticReadTarget.js";
const REASON_CONTEXT_FIELD = 'reason';
export default class CheckpointTailReadFailure {
    _graphName;
    _target;
    constructor(options) {
        this._graphName = options.graphName;
        this._target = createTarget(options);
        Object.freeze(this);
    }
    enrich(error) {
        const cause = causeForOpticReadError(error);
        if (cause === null) {
            return error;
        }
        return new QueryError(error.message, {
            code: error.code,
            context: new OpticReadFailureContext({
                sourceContext: error.context,
                graphName: this._graphName,
                target: this._target,
                cause,
                includeReason: hasReason(error),
            }).toQueryErrorContext(),
        });
    }
}
function createTarget(options) {
    if (options.opticKind === 'node') {
        return OpticReadTarget.node(options.nodeId);
    }
    if (options.opticKind === 'neighborhood') {
        return OpticReadTarget.neighborhood(options.nodeId);
    }
    if (options.opticKind === 'traversal') {
        return OpticReadTarget.traversal(options.nodeId);
    }
    return OpticReadTarget.nodeProperty(options.nodeId, options.propertyKey ?? '');
}
function causeForOpticReadError(error) {
    const reason = reasonForError(error);
    if (reason !== null && reason.length > 0) {
        return new OpticReadFailureCause(reason);
    }
    if (error.code === 'E_OPTIC_TAIL_BUDGET_EXCEEDED') {
        return new OpticReadFailureCause('tail-budget-exceeded');
    }
    if (error.code === 'E_OPTIC_READ_IDENTITY') {
        return new OpticReadFailureCause('read-identity-missing-field');
    }
    return null;
}
function hasReason(error) {
    return reasonForError(error) !== null;
}
function reasonForError(error) {
    const reason = error.context[REASON_CONTEXT_FIELD];
    return typeof reason === 'string' ? reason : null;
}
