"use strict";
/**
 * Retry Handler - Error recovery and retry logic
 *
 * Handles:
 * - Network error detection
 * - Token expiration handling
 * - Quota management
 * - Account switching
 */
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    var desc = Object.getOwnPropertyDescriptor(m, k);
    if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
      desc = { enumerable: true, get: function() { return m[k]; } };
    }
    Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
    if (k2 === undefined) k2 = k;
    o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
    Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
    o["default"] = v;
});
var __importStar = (this && this.__importStar) || function (mod) {
    if (mod && mod.__esModule) return mod;
    var result = {};
    if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
    __setModuleDefault(result, mod);
    return result;
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.isProviderError = exports.detectFailedTier = exports.PROVIDER_ERROR_PATTERNS = exports.handleQuotaCheck = exports.handleTokenExpiration = exports.handleNetworkError = exports.isNetworkError = void 0;
const ui_1 = require("../../utils/ui");
const account_safety_1 = require("../accounts/account-safety");
/**
 * Check if error is network-related
 */
function isNetworkError(error) {
    const networkErrors = [
        'getaddrinfo',
        'ENOTFOUND',
        'ETIMEDOUT',
        'ECONNREFUSED',
        'ENETUNREACH',
        'EAI_AGAIN',
    ];
    return networkErrors.some((errCode) => error.message.includes(errCode));
}
exports.isNetworkError = isNetworkError;
/**
 * Handle network error with user-friendly message
 */
function handleNetworkError(_error) {
    console.error('');
    console.error((0, ui_1.fail)('No network connection detected'));
    console.error('');
    console.error('CLIProxy binary download requires internet access.');
    console.error('Please check your network connection and try again.');
    console.error('');
    process.exit(1);
}
exports.handleNetworkError = handleNetworkError;
/**
 * Handle token expiration
 */
async function handleTokenExpiration(provider, verbose) {
    const { ensureTokenValid } = await Promise.resolve().then(() => __importStar(require('../auth/token-manager')));
    const tokenResult = await ensureTokenValid(provider, verbose);
    if (!tokenResult.valid) {
        // Check if this is an account ban/disable before generic error
        if (tokenResult.error) {
            const { getDefaultAccount } = await Promise.resolve().then(() => __importStar(require('../accounts/account-manager')));
            const account = getDefaultAccount(provider);
            if (account) {
                (0, account_safety_1.handleBanDetection)(provider, account.id, tokenResult.error);
            }
            (0, account_safety_1.warnPossible403Ban)(provider, tokenResult.error);
        }
        // Token expired and refresh failed - trigger re-auth
        console.error((0, ui_1.warn)('OAuth token expired and refresh failed'));
        if (tokenResult.error) {
            console.error(`    ${tokenResult.error}`);
        }
        console.error(`    Run "ccs ${provider} --auth" to re-authenticate`);
        process.exit(1);
    }
    if (tokenResult.refreshed && verbose) {
        console.error('[cliproxy] Token was refreshed proactively');
    }
}
exports.handleTokenExpiration = handleTokenExpiration;
/**
 * Handle quota check and auto-switching for providers with quota-based rotation.
 */
async function handleQuotaCheck(provider) {
    const { isManagedQuotaProvider, preflightCheck } = await Promise.resolve().then(() => __importStar(require('../quota/quota-manager')));
    if (!isManagedQuotaProvider(provider))
        return;
    const preflight = await preflightCheck(provider);
    if (!preflight.proceed) {
        console.error((0, ui_1.fail)(`Cannot start session: ${preflight.reason}`));
        process.exit(1);
    }
    if (preflight.switchedFrom) {
        console.log((0, ui_1.info)(`Auto-switched to ${preflight.accountId}`));
        console.log(`    Reason: ${preflight.reason}`);
        if (preflight.quotaPercent !== undefined && preflight.quotaPercent !== null) {
            console.log(`    New account quota: ${preflight.quotaPercent.toFixed(1)}%`);
        }
        else {
            console.log(`    New account quota: N/A (fetch unavailable)`);
        }
    }
}
exports.handleQuotaCheck = handleQuotaCheck;
/** Error patterns indicating provider failure */
exports.PROVIDER_ERROR_PATTERNS = [
    /Error:\s*4[0-9]{2}/i,
    /Error:\s*5[0-9]{2}/i,
    /overloaded/i,
    /quota.*exceeded/i,
    /ECONNREFUSED/i,
    /rate.?limit/i,
];
/** Detect which composite tier failed from stderr output */
function detectFailedTier(stderr, tiers) {
    for (const tier of ['opus', 'sonnet', 'haiku']) {
        // Strip thinking suffix (e.g., "model(high)" → "model") for matching
        const model = tiers[tier].model.replace(/\([^)]+\)$/, '');
        if (stderr.includes(model))
            return tier;
    }
    return null;
}
exports.detectFailedTier = detectFailedTier;
/** Check if Claude exit indicates provider error (vs normal user exit) */
function isProviderError(exitCode, stderr) {
    // Exit code 0 means success, even if stderr has error-like output
    // (could be warnings, debug info, etc.)
    if (exitCode === 0)
        return false;
    return exports.PROVIDER_ERROR_PATTERNS.some((p) => p.test(stderr));
}
exports.isProviderError = isProviderError;
//# sourceMappingURL=retry-handler.js.map