/**
 * AI Error Handler Middleware
 * Provides user-friendly error messages for AI API errors
 */
import { createLogger } from "../core/index.js";
import { sendError, sendUnauthorized } from "../core/apiResponse.js";
import { AIError } from "../services/aiService.js";
let logger; // Will be initialized when needed
function ensureLogger() {
    if (!logger) {
        logger = createLogger("AIError");
    }
    return logger;
}
/**
 * AI-specific error handler middleware
 */
export function aiErrorHandler(err, _req, res, next) {
    // Only handle AI-related errors
    if (!_req.path.startsWith("/api/ai/")) {
        return next(err);
    }
    ensureLogger().error("AI Error:", {
        path: _req.path,
        method: _req.method,
        error: err.message,
        status: err.statusCode || err.status,
        stack: err.stack,
        errorType: err.errorType,
        provider: err.provider,
    });
    // Handle our custom AIError instances
    if (err instanceof AIError) {
        const response = {
            error: err.message,
            code: err.errorType,
        };
        // Add provider-specific information
        if (err.provider) {
            response.details = [`Provider: ${err.provider}`];
        }
        // Handle specific error types
        switch (err.errorType) {
            case "AUTH_ERROR":
                sendUnauthorized(res, err.message);
                return;
            case "RATE_LIMIT":
                sendError(res, err.message, 429, { retryAfter: 60 });
                return;
            case "SERVICE_UNAVAILABLE":
                sendError(res, err.message, 503);
                return;
            case "TIMEOUT":
                sendError(res, err.message, 408);
                return;
            default:
                sendError(res, err.message, err.statusCode, response);
                return;
        }
    }
    // Handle legacy structured AI errors with user-friendly messages
    if (err.userMessage) {
        const response = {
            error: err.userMessage,
        };
        if (err.details) {
            response.details = err.details;
        }
        if (err.actionRequired) {
            response.action = err.actionRequired;
        }
        if (err.code) {
            response.code = err.code;
        }
        sendError(res, err.userMessage, err.status || 500, {
            details: err.details,
            action: err.actionRequired,
            code: err.code,
        });
        return;
    }
    // Handle OpenAI specific errors
    if (err.message && err.message.includes("401")) {
        sendUnauthorized(res, "OpenAI API authentication failed: Invalid or missing API key. Check your OpenAI API key configuration");
        return;
    }
    if (err.message && err.message.includes("429")) {
        sendError(res, "OpenAI API rate limit exceeded: Too many requests. Please wait a moment before trying again", 429);
        return;
    }
    if (err.message && err.message.includes("insufficient_quota")) {
        sendError(res, "OpenAI API quota exceeded: Your account has insufficient quota. Check your OpenAI account billing and usage limits", 402);
        return;
    }
    // Handle Anthropic specific errors
    if (err.message && err.message.includes("anthropic")) {
        if (err.message.includes("401")) {
            sendUnauthorized(res, "Anthropic API authentication failed: Invalid or missing API key");
            return;
        }
        if (err.message.includes("rate")) {
            sendError(res, "Anthropic API rate limit exceeded: Too many requests", 429);
            return;
        }
    }
    // Handle JSON parse errors
    if (err.message && err.message.includes("JSON")) {
        sendError(res, "Failed to generate valid template format: The AI response was not in the expected format", 500);
        return;
    }
    // Handle missing required fields
    if (err.message && err.message.includes("missing required fields")) {
        sendError(res, "Generated template is incomplete: Missing required fields", 500);
        return;
    }
    // Handle API key errors
    if (err.message && err.message.includes("API key")) {
        sendUnauthorized(res, "AI API key not configured: Please configure your API key");
        return;
    }
    // Handle timeout errors
    if (err.message &&
        (err.message.includes("timeout") || err.message.includes("ETIMEDOUT"))) {
        sendError(res, "AI request timed out: The request took too long to complete", 504);
        return;
    }
    // Handle network errors
    if (err.message &&
        (err.message.includes("ECONNREFUSED") || err.message.includes("ENOTFOUND"))) {
        sendError(res, "AI service unavailable: Cannot connect to AI service", 503);
        return;
    }
    // Default error response
    sendError(res, err.message || "An error occurred while processing your AI request", err.status || 500);
}
/**
 * Rate limit handler for AI endpoints
 */
export function aiRateLimitHandler(_req, res) {
    sendError(res, "Too many AI requests: Rate limit exceeded. Please wait a moment before trying again", 429);
}
/**
 * Create AI error with user-friendly message
 */
export function createAIError(message, userMessage, status = 500, details, action) {
    const error = new AIError(message, status, "CUSTOM_ERROR", "unknown");
    // Additional legacy properties for compatibility
    error.userMessage = userMessage;
    error.details = details;
    error.actionRequired = action;
    return error;
}
/**
 * Wrap async AI handlers with error handling
 */
export function wrapAIHandler(handler) {
    return async (req, res, next) => {
        try {
            await handler(req, res, next);
        }
        catch (_error) {
            // Convert to AI error if needed
            if (!_error.userMessage && _error.response?.data) {
                // Handle API response errors
                const apiError = _error.response.data;
                _error.userMessage =
                    apiError.error?.message || apiError.message || "AI request failed";
                _error.status = _error.response.status;
                _error.details = apiError.error?.details || [apiError.error?.type];
            }
            next(_error);
        }
    };
}
export default {
    aiErrorHandler,
    aiRateLimitHandler,
    createAIError,
    wrapAIHandler,
};
//# sourceMappingURL=aiErrorHandler.js.map