import { getAuthProfile, saveAuthProfile } from '../auth/profiles.js';
import { createLogger } from '../logger.js';
import { createReauthError, DEFAULT_AUTH_PROFILE } from './oauth-utils.js';
import { readKeychainOAuthTokenInfo, storeKeychainOAuthTokenInfo, readKeychainOAuthClientInfo } from './keychain.js';
import { OAuthTokenManager } from './oauth-token-manager.js';
const logger = createLogger('token-refresh');
function createPersistenceCallback(serverUrl, profileName, profile, existingTokens) {
    return async (newTokens) => {
        const tokenInfo = {
            accessToken: newTokens.access_token,
            tokenType: newTokens.token_type,
        };
        if (newTokens.expires_in !== undefined) {
            tokenInfo.expiresIn = newTokens.expires_in;
            tokenInfo.expiresAt = Math.floor(Date.now() / 1000) + newTokens.expires_in;
        }
        const refreshToken = newTokens.refresh_token ?? existingTokens.refreshToken;
        if (refreshToken) {
            tokenInfo.refreshToken = refreshToken;
        }
        if (newTokens.scope !== undefined) {
            tokenInfo.scope = newTokens.scope;
        }
        await storeKeychainOAuthTokenInfo(serverUrl, profileName, tokenInfo);
        const updatedProfile = {
            ...profile,
            refreshedAt: new Date().toISOString(),
        };
        if (newTokens.scope) {
            updatedProfile.scopes = newTokens.scope.split(' ');
        }
        await saveAuthProfile(updatedProfile);
        logger.info(`Token refreshed and saved for profile: ${profileName}`);
    };
}
export async function getValidAccessTokenFromKeychain(serverUrl, profileName = DEFAULT_AUTH_PROFILE) {
    const profile = await getAuthProfile(serverUrl, profileName);
    if (!profile) {
        logger.debug(`No auth profile found for ${serverUrl} (profile: ${profileName})`);
        return undefined;
    }
    const tokens = await readKeychainOAuthTokenInfo(serverUrl, profileName);
    if (!tokens?.accessToken) {
        logger.warn(`Auth profile exists but has no access token in keychain: ${profileName}`);
        return undefined;
    }
    if (!tokens.refreshToken) {
        if (tokens.expiresAt && Date.now() / 1000 > tokens.expiresAt - 60) {
            throw createReauthError(serverUrl, profileName, 'Authentication token expired and no refresh token available');
        }
        logger.debug(`Using auth profile: ${profileName}`);
        return tokens.accessToken;
    }
    const clientInfo = await readKeychainOAuthClientInfo(serverUrl, profileName);
    if (!clientInfo?.clientId) {
        throw createReauthError(serverUrl, profileName, 'OAuth client ID not found in keychain (required for token refresh)');
    }
    const tokenManager = new OAuthTokenManager({
        serverUrl,
        profileName,
        clientId: clientInfo.clientId,
        refreshToken: tokens.refreshToken,
        accessToken: tokens.accessToken,
        ...(tokens.expiresAt !== undefined && { accessTokenExpiresAt: tokens.expiresAt }),
        onTokenRefresh: createPersistenceCallback(serverUrl, profileName, profile, tokens),
    });
    logger.debug(`Using auth profile: ${profileName}`);
    return await tokenManager.getValidAccessToken();
}
//# sourceMappingURL=token-refresh.js.map