"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.shouldUseAzureCliForSessions = shouldUseAzureCliForSessions;
exports.isAzureCliMissingError = isAzureCliMissingError;
exports.getAzureSessionsAccessTokenInfo = getAzureSessionsAccessTokenInfo;
exports.getAzureSessionsAccessToken = getAzureSessionsAccessToken;
const node_child_process_1 = require("node:child_process");
const node_util_1 = require("node:util");
const identity_1 = require("@azure/identity");
const logger_1 = __importDefault(require("../../logger"));
const config_1 = require("./config");
const authLogging_1 = require("./authLogging");
const jwtClaims_1 = require("./jwtClaims");
const execFileAsync = (0, node_util_1.promisify)(node_child_process_1.execFile);
const SESSIONS_TOKEN_SCOPE = 'https://dynamicsessions.io/.default';
const SESSIONS_TOKEN_RESOURCE = 'https://dynamicsessions.io';
let cliCredential = null;
let defaultCredential = null;
/** Local dev should use the same identity as `az login` unless explicitly disabled. */
function shouldUseAzureCliForSessions() {
    if (process.env.AZURE_SESSIONS_USE_AZ_CLI_CREDENTIAL === 'false' ||
        process.env.AZURE_SESSIONS_USE_AZ_CLI_CREDENTIAL === '0') {
        return false;
    }
    if (process.env.AZURE_SESSIONS_USE_AZ_CLI_CREDENTIAL === 'true' ||
        process.env.AZURE_SESSIONS_USE_AZ_CLI_CREDENTIAL === '1') {
        return true;
    }
    return process.env.NODE_ENV !== 'production';
}
function getAzureCliCredential() {
    if (!cliCredential) {
        cliCredential = new identity_1.AzureCliCredential();
    }
    return cliCredential;
}
function getDefaultCredential() {
    if (!defaultCredential) {
        defaultCredential = new identity_1.DefaultAzureCredential();
    }
    return defaultCredential;
}
function isAzureCliMissingError(error) {
    const msg = error instanceof Error
        ? error.message
        : typeof error === 'object' &&
            error !== null &&
            'message' in error &&
            typeof error.message === 'string'
            ? error.message
            : String(error);
    return (/azure cli could not be found/i.test(msg) ||
        /az['"]?\s+(is\s+)?not recognized/i.test(msg) ||
        /ENOENT/i.test(msg));
}
async function getTokenViaAzureCliExec() {
    const { stdout } = await execFileAsync('az', ['account', 'get-access-token', '--resource', SESSIONS_TOKEN_RESOURCE, '--query', 'accessToken', '-o', 'tsv'], { timeout: 60000, windowsHide: true });
    const token = stdout.trim();
    if (!token) {
        throw new Error('az account get-access-token returned an empty token');
    }
    return token;
}
async function getTokenViaAzureCliCredential() {
    const token = await getAzureCliCredential().getToken(SESSIONS_TOKEN_SCOPE);
    if (!token?.token) {
        throw new Error('Failed to acquire Azure Sessions access token (empty token)');
    }
    return token.token;
}
async function getTokenViaDefaultCredential() {
    const token = await getDefaultCredential().getToken(SESSIONS_TOKEN_SCOPE);
    if (!token?.token) {
        throw new Error('Failed to acquire Azure Sessions access token (empty token)');
    }
    return token.token;
}
function logTokenAcquired(source, token) {
    const claims = (0, jwtClaims_1.decodeAzureSessionsTokenClaims)(token);
    const info = {
        token,
        credentialSource: source,
        claims,
        identityLabel: (0, jwtClaims_1.formatTokenIdentityForDiagnostics)(claims),
    };
    (0, authLogging_1.logAzureSessionsAuth)('Access token acquired', {
        credentialSource: source,
        identity: info.identityLabel,
        oid: claims?.oid,
    });
    return info;
}
async function getAzureSessionsAccessTokenInfo() {
    const config = (0, config_1.getAzureSessionsConfig)();
    if (!config) {
        throw new Error('Azure Sessions is not configured. Set AZURE_SESSIONS_SUBSCRIPTION_ID, AZURE_SESSIONS_RESOURCE_GROUP, AZURE_SESSIONS_REGION, AZURE_SESSIONS_PYTHON_POOL_NAME, and AZURE_SESSIONS_NODE_POOL_NAME.');
    }
    (0, authLogging_1.logAzureSessionsAuth)('Using auth mode', {
        useAzureCli: shouldUseAzureCliForSessions(),
    });
    try {
        if (shouldUseAzureCliForSessions()) {
            try {
                (0, authLogging_1.logAzureSessionsAuth)('Trying azure-cli-exec');
                const token = await getTokenViaAzureCliExec();
                return logTokenAcquired('azure-cli-exec', token);
            }
            catch (execError) {
                const execMsg = execError instanceof Error ? execError.message : String(execError);
                (0, authLogging_1.logAzureSessionsAuth)('azure-cli-exec failed', { error: execMsg });
                if (!isAzureCliMissingError(execError)) {
                    try {
                        (0, authLogging_1.logAzureSessionsAuth)('Trying azure-cli-credential');
                        const token = await getTokenViaAzureCliCredential();
                        return logTokenAcquired('azure-cli-credential', token);
                    }
                    catch (cliCredError) {
                        (0, authLogging_1.logAzureSessionsAuth)('azure-cli-credential failed', {
                            error: cliCredError instanceof Error ? cliCredError.message : String(cliCredError),
                        });
                    }
                }
                (0, authLogging_1.logAzureSessionsAuth)('Falling back to default-azure-credential');
            }
        }
        else {
            (0, authLogging_1.logAzureSessionsAuth)('Using default-azure-credential');
        }
        const token = await getTokenViaDefaultCredential();
        return logTokenAcquired('default-azure-credential', token);
    }
    catch (error) {
        const message = error instanceof Error ? error.message : String(error);
        (0, authLogging_1.logAzureSessionsAuth)('Failed to acquire access token', { error: message });
        logger_1.default.error(`[Azure Sessions auth] ${message}`);
        throw new Error(`Failed to acquire Azure Sessions token: ${message}. ` +
            'For local dev: install Azure CLI and run `az login`, or set AZURE_TENANT_ID, AZURE_CLIENT_ID, AZURE_CLIENT_SECRET ' +
            '(and AZURE_SESSIONS_USE_AZ_CLI_CREDENTIAL=false) then restart the server. ' +
            'The signed-in identity needs Session Executor on the session pool (see /api/azure-custom-provider/diagnostics).');
    }
}
/**
 * Bearer token for Azure Container Apps dynamic sessions (audience https://dynamicsessions.io).
 */
async function getAzureSessionsAccessToken() {
    const info = await getAzureSessionsAccessTokenInfo();
    return info.token;
}
//# sourceMappingURL=auth.js.map