/**
 * Copyright 2025 Vybestack LLC
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *   http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
/**
 * @plan PLAN-20251127-OPENAIVERCEL.P14
 * @requirement REQ-OAV-009 - Error Handling
 */
/**
 * Base error class for all provider-related errors
 */
export class ProviderError extends Error {
    provider;
    statusCode;
    originalError;
    isRetryable;
    constructor(message, provider, statusCode, isRetryable = false, originalError) {
        super(message);
        this.name = 'ProviderError';
        this.provider = provider;
        this.statusCode = statusCode;
        this.isRetryable = isRetryable;
        this.originalError = originalError;
        // Maintain proper stack trace for where error was thrown (V8 only)
        if (Error.captureStackTrace) {
            Error.captureStackTrace(this, this.constructor);
        }
    }
}
/**
 * Rate limit error with retry-after support
 */
export class RateLimitError extends ProviderError {
    retryAfter;
    constructor(message, provider, retryAfter, statusCode, originalError) {
        // Rate limit errors are retryable
        super(message, provider, statusCode, true, originalError);
        this.name = 'RateLimitError';
        this.retryAfter = retryAfter;
    }
}
/**
 * Authentication error
 */
export class AuthenticationError extends ProviderError {
    constructor(message, provider, statusCode, originalError) {
        // Auth errors are not retryable
        super(message, provider, statusCode, false, originalError);
        this.name = 'AuthenticationError';
    }
}
/**
 * Wraps raw errors into appropriate typed error classes
 */
export function wrapError(error, provider) {
    // If already a ProviderError, return as-is
    if (error instanceof ProviderError) {
        return error;
    }
    // Handle standard Error objects
    if (error instanceof Error) {
        const statusCode = getStatusCode(error);
        // Check for rate limit (429)
        if (statusCode === 429) {
            const retryAfter = getRetryAfter(error);
            return new RateLimitError(error.message, provider, retryAfter, statusCode, error);
        }
        // Check for authentication errors (401, 403)
        if (statusCode === 401 || statusCode === 403) {
            return new AuthenticationError(error.message, provider, statusCode, error);
        }
        // Check for server errors (5xx) - these are retryable
        if (statusCode && statusCode >= 500 && statusCode < 600) {
            return new ProviderError(error.message, provider, statusCode, true, error);
        }
        // For other errors with status codes, wrap as generic ProviderError (not retryable)
        if (statusCode) {
            return new ProviderError(error.message, provider, statusCode, false, error);
        }
        // For errors without status codes, wrap as generic ProviderError (not retryable)
        return new ProviderError(error.message, provider, undefined, false, error);
    }
    // Handle non-Error objects (strings, etc.)
    return new ProviderError(String(error), provider);
}
function getStatusCode(error) {
    const candidate = error;
    if (typeof candidate.statusCode === 'number')
        return candidate.statusCode;
    if (typeof candidate.status === 'number')
        return candidate.status;
    const response = candidate.response;
    if (response && typeof response === 'object' && 'status' in response) {
        const responseStatus = response.status;
        if (typeof responseStatus === 'number') {
            return responseStatus;
        }
    }
    return undefined;
}
function parseRetryAfter(value) {
    if (typeof value === 'number') {
        return value;
    }
    if (typeof value === 'string') {
        const parsed = Number.parseInt(value, 10);
        return Number.isNaN(parsed) ? undefined : parsed;
    }
    return undefined;
}
function getRetryAfter(error) {
    const record = { ...error };
    const retryAfter = record.retryAfter ??
        record.retry_after ??
        record['retry-after'] ??
        getRetryAfterFromHeaders(record.responseHeaders);
    return parseRetryAfter(retryAfter);
}
function getRetryAfterFromHeaders(headers) {
    if (!headers || typeof headers !== 'object') {
        return undefined;
    }
    const headerValue = headers['retry-after'];
    return parseRetryAfter(headerValue);
}
//# sourceMappingURL=errors.js.map