/**
 * OCR Error Classes - Local GPU Processing
 *
 * FAIL-FAST: These errors propagate immediately, no fallbacks.
 * Must match Python error categories in python/ocr_worker_local.py.
 *
 * Categories for local processing:
 *   OCR_FILE_ERROR  - File access or validation errors
 *   OCR_TIMEOUT     - Processing timeout exceeded
 *   OCR_MODEL_ERROR - Model loading or inference errors
 *   OCR_GPU_ERROR   - GPU memory or CUDA errors
 */
export class OCRError extends Error {
    category;
    constructor(message, category) {
        super(message);
        this.category = category;
        this.name = 'OCRError';
    }
}
export class OCRTimeoutError extends OCRError {
    constructor(message) {
        super(message, 'OCR_TIMEOUT');
        this.name = 'OCRTimeoutError';
    }
}
export class OCRFileError extends OCRError {
    filePath;
    constructor(message, filePath) {
        super(message, 'OCR_FILE_ERROR');
        this.filePath = filePath;
        this.name = 'OCRFileError';
    }
}
export class OCRModelError extends OCRError {
    constructor(message) {
        super(message, 'OCR_MODEL_ERROR');
        this.name = 'OCRModelError';
    }
}
export class OCRGPUError extends OCRError {
    constructor(message) {
        super(message, 'OCR_GPU_ERROR');
        this.name = 'OCRGPUError';
    }
}
/**
 * Classify whether an error is transient (retryable) or permanent.
 *
 * TRANSIENT errors keep document status='pending' for retry:
 *   - OCR_TIMEOUT: timeout, will likely succeed on retry
 *   - OCR_MODEL_ERROR with "No module named": missing dependency, fixed by image rebuild
 *   - OCR_GPU_ERROR: GPU OOM or CUDA error, may work after memory freed
 *   - InsufficientBalanceError: user needs to add funds, then retry
 *
 * PERMANENT errors mark document status='failed':
 *   - OCR_FILE_ERROR: file not found, corrupt file, unsupported format
 *   - Any other unclassified error: fail fast, make user investigate
 */
export function isTransientError(error) {
    // InsufficientBalanceError from license client
    if (error instanceof Error && error.constructor.name === 'InsufficientBalanceError') {
        return true;
    }
    // SpendingLimitError is transient — the monthly limit resets, so documents
    // should stay 'pending' and retry after the period resets or the user raises the limit.
    if (error instanceof Error && error.constructor.name === 'SpendingLimitError') {
        return true;
    }
    if (!(error instanceof OCRError)) {
        return false;
    }
    switch (error.category) {
        case 'OCR_TIMEOUT':
        case 'OCR_GPU_ERROR':
            return true;
        case 'OCR_MODEL_ERROR':
            // ALL model errors are environment-level: missing dependencies, daemon crash,
            // model loading failure. They affect ALL documents equally (not per-document).
            // Mark as transient so documents stay 'pending' and can be retried after
            // the environment is fixed (e.g., pip install beautifulsoup4).
            return true;
        case 'OCR_FILE_ERROR':
            return false;
        default:
            return false;
    }
}
/**
 * Return a human-readable transient error category label for logging.
 */
export function transientErrorCategory(error) {
    if (error instanceof Error && error.constructor.name === 'InsufficientBalanceError') {
        return 'InsufficientBalance';
    }
    if (error instanceof Error && error.constructor.name === 'SpendingLimitError') {
        return 'SpendingLimitReached';
    }
    if (error instanceof OCRError) {
        return error.category;
    }
    return 'UNKNOWN';
}
/**
 * Map Python error JSON to TypeScript error class.
 * FAIL-FAST: Unknown categories throw OCRError.
 */
export function mapPythonError(category, message, details) {
    switch (category) {
        case 'OCR_TIMEOUT':
            return new OCRTimeoutError(message);
        case 'OCR_FILE_ERROR':
            return new OCRFileError(message, details.file_path ?? 'unknown');
        case 'OCR_MODEL_ERROR':
            return new OCRModelError(message);
        case 'OCR_GPU_ERROR':
            return new OCRGPUError(message);
        default:
            throw new OCRError(`Unknown error category: ${category}. Message: ${message}`, 'OCR_MODEL_ERROR');
    }
}
//# sourceMappingURL=errors.js.map