import chalk from "chalk";
/**
 * Convert raw errors into clean, user-friendly one-liners.
 */
export function formatUserError(err) {
    if (err instanceof Error && err.name === "AbortError") {
        return chalk.red("Interrupted.");
    }
    const { message, provider, statusCode } = extractErrorInfo(err);
    const lowerMsg = message.toLowerCase();
    // Auth: not logged in
    if (lowerMsg.includes("not logged in") ||
        lowerMsg.includes("resolve authentication") ||
        lowerMsg.includes("api key") ||
        lowerMsg.includes("apikey") ||
        lowerMsg.includes("no auth")) {
        return chalk.red('Not logged in. Run "ggcoder login" to authenticate.');
    }
    // Auth: invalid/expired token
    if (statusCode === 401 ||
        lowerMsg.includes("unauthorized") ||
        lowerMsg.includes("token refresh failed") ||
        lowerMsg.includes("invalid_grant") ||
        /invalid.*key/.test(lowerMsg) ||
        /invalid.*token/.test(lowerMsg)) {
        return chalk.red('Session expired or invalid. Run "ggcoder login" to re-authenticate.');
    }
    // Billing/quota errors (GLM returns 429 for these)
    if (lowerMsg.includes("insufficient balance") ||
        lowerMsg.includes("no resource package") ||
        lowerMsg.includes("quota exceeded") ||
        lowerMsg.includes("recharge")) {
        const name = displayProvider(provider);
        return chalk.red(`${name} reports a billing or quota issue. Check your account balance or resource package.`);
    }
    // Rate limiting
    if (statusCode === 429 || lowerMsg.includes("rate limit")) {
        const name = displayProvider(provider);
        return chalk.red(`Rate limited by ${name}. Wait a moment and try again.`);
    }
    // Server errors (5xx)
    if (statusCode && statusCode >= 500 && statusCode < 600) {
        const name = displayProvider(provider);
        return chalk.red(`${name} server error (${statusCode}). Try again shortly.`);
    }
    // Network errors
    if (lowerMsg.includes("econnrefused") ||
        lowerMsg.includes("fetch failed") ||
        lowerMsg.includes("enotfound") ||
        lowerMsg.includes("etimedout") ||
        lowerMsg.includes("network")) {
        const name = displayProvider(provider);
        return chalk.red(`Cannot reach ${name} API. Check your internet connection.`);
    }
    // Model not found (404) — provider says the model doesn't exist or account lacks access
    if (statusCode === 404 ||
        lowerMsg.includes("model_not_found") ||
        lowerMsg.includes("does not exist") ||
        /model.*not.*exist/.test(lowerMsg) ||
        /not have access.*model/.test(lowerMsg)) {
        const name = displayProvider(provider);
        const modelMatch = message.match(/model[:\s]+["']?([^\s"',)]+)/i);
        const modelHint = modelMatch ? ` (${modelMatch[1]})` : "";
        return chalk.red(`${name} does not recognize the requested model${modelHint}. It may not exist or your account may not have access. Check the model name and your account permissions.`);
    }
    // Bad request (400)
    if (statusCode === 400) {
        const name = displayProvider(provider);
        const firstLine = message.split("\n")[0];
        return chalk.red(`Request error (${name}): ${firstLine}`);
    }
    // File not found
    if (lowerMsg.includes("enoent")) {
        const path = extractPath(message);
        return chalk.red(path ? `File not found: ${path}` : "File not found.");
    }
    // Permission denied
    if (lowerMsg.includes("eacces")) {
        const path = extractPath(message);
        return chalk.red(path ? `Permission denied: ${path}` : "Permission denied.");
    }
    // Internal/unexpected JS errors (RangeError, TypeError, SyntaxError,
    // ReferenceError) shouldn't be flattened to a one-liner — those are bugs in
    // our code, and the stack is the only thing that points at the offending
    // file. A bare "Maximum call stack size exceeded" tells the user nothing.
    if (err instanceof Error && isInternalJsError(err) && err.stack) {
        return chalk.red(err.stack);
    }
    // Generic Error — show first line only, no stack
    if (message) {
        const firstLine = message.split("\n")[0];
        return chalk.red(`Error: ${firstLine}`);
    }
    return chalk.red("An unexpected error occurred.");
}
function isInternalJsError(err) {
    return (err instanceof RangeError ||
        err instanceof TypeError ||
        err instanceof SyntaxError ||
        err instanceof ReferenceError);
}
function extractErrorInfo(err) {
    if (typeof err !== "object" || err === null) {
        return { message: String(err), provider: undefined, statusCode: undefined };
    }
    const e = err;
    const message = typeof e.message === "string" ? e.message : String(err);
    const provider = typeof e.provider === "string" ? e.provider : undefined;
    const statusCode = typeof e.statusCode === "number"
        ? e.statusCode
        : typeof e.status === "number"
            ? e.status
            : undefined;
    return { message, provider, statusCode };
}
function displayProvider(provider) {
    switch (provider) {
        case "anthropic":
            return "Anthropic";
        case "openai":
            return "OpenAI";
        case "glm":
            return "Z.AI (GLM)";
        case "moonshot":
            return "Moonshot";
        default:
            return "The provider";
    }
}
function extractPath(message) {
    // Match common ENOENT/EACCES patterns: "... 'path'" or "... \"path\""
    const match = message.match(/['"]([^'"]+)['"]/);
    return match?.[1];
}
//# sourceMappingURL=error-handler.js.map