import { OpenAICodexAdapter } from "./providers/openai_codex.js";
export class AuthManager {
    authStorage;
    static sessionSelections = new Map();
    adapters;
    constructor(authStorage, adapters) {
        this.authStorage = authStorage;
        const defaultAdapters = adapters ?? [new OpenAICodexAdapter()];
        this.adapters = new Map(defaultAdapters.map((adapter) => [adapter.id, adapter]));
    }
    listProviders() {
        return [...this.adapters.values()].map((adapter) => ({
            id: adapter.id,
            label: adapter.label,
        }));
    }
    async listProviderAccounts() {
        this.authStorage.reload();
        const invalidReason = this.authStorage.getInvalidReason();
        if (invalidReason) {
            throw new Error(invalidReason);
        }
        const results = [];
        for (const adapter of this.adapters.values()) {
            const accounts = await adapter.listAccountInfo(this.authStorage);
            if (accounts.length > 0) {
                const forcedAccountId = adapter.getForcedAccountId?.(this.authStorage);
                const selectedAccountId = forcedAccountId ?? adapter.selectAccountFromList?.(accounts);
                results.push({
                    providerId: adapter.id,
                    providerLabel: adapter.label,
                    accounts,
                    selectedAccountId,
                });
            }
        }
        return results;
    }
    addOAuthAccount(providerId, credentials) {
        const adapter = this.adapters.get(providerId);
        if (!adapter) {
            throw new Error(`unsupported auth provider "${providerId}"`);
        }
        this.authStorage.reload();
        adapter.validateOAuthCredentials?.(credentials);
        adapter.addOAuthAccount(this.authStorage, credentials);
    }
    removeAccount(providerId, accountId) {
        const adapter = this.adapters.get(providerId);
        if (!adapter) {
            throw new Error(`unsupported auth provider "${providerId}"`);
        }
        this.authStorage.reload();
        const removed = adapter.removeAccount(this.authStorage, accountId);
        if (!removed) {
            throw new Error(`account "${accountId}" not found for provider "${providerId}"`);
        }
    }
    async getApiKey(provider, options) {
        const adapter = this.adapters.get(provider);
        if (!adapter) {
            return undefined;
        }
        this.authStorage.reload();
        const invalidReason = this.authStorage.getInvalidReason();
        if (invalidReason) {
            throw new Error(invalidReason);
        }
        const forcedAccountId = adapter.getForcedAccountId?.(this.authStorage);
        if (forcedAccountId) {
            const apiKey = await adapter.getApiKeyForAccount(this.authStorage, forcedAccountId);
            if (apiKey) {
                if (options?.sessionId) {
                    AuthManager.setSelectedAccount(options.sessionId, adapter.id, forcedAccountId);
                }
                return apiKey;
            }
            return undefined;
        }
        const sessionId = options?.sessionId;
        if (sessionId) {
            const selectedAccountId = AuthManager.getSelectedAccount(sessionId, adapter.id);
            if (selectedAccountId) {
                const apiKey = await adapter.getApiKeyForAccount(this.authStorage, selectedAccountId);
                if (apiKey) {
                    const usable = adapter.isAccountUsable
                        ? await adapter.isAccountUsable(this.authStorage, selectedAccountId, { apiKey })
                        : true;
                    if (usable) {
                        return apiKey;
                    }
                }
                AuthManager.clearSelectedAccount(sessionId, adapter.id);
            }
        }
        const selection = await adapter.selectAccount(this.authStorage);
        if (!selection) {
            return undefined;
        }
        if (sessionId) {
            AuthManager.setSelectedAccount(sessionId, adapter.id, selection.accountId);
        }
        return selection.apiKey;
    }
    async noteProviderError(provider, options) {
        const adapter = this.adapters.get(provider);
        if (!adapter) {
            return;
        }
        this.authStorage.reload();
        const invalidReason = this.authStorage.getInvalidReason();
        if (invalidReason) {
            throw new Error(invalidReason);
        }
        const sessionId = options?.sessionId;
        if (!sessionId)
            return;
        const forcedAccountId = adapter.getForcedAccountId?.(this.authStorage);
        const selectedAccountId = forcedAccountId ?? AuthManager.getSelectedAccount(sessionId, adapter.id);
        if (!selectedAccountId)
            return;
        if (!adapter.handleProviderError) {
            return;
        }
        const shouldClear = await adapter.handleProviderError(this.authStorage, selectedAccountId, options?.error);
        if (shouldClear && !forcedAccountId) {
            AuthManager.clearSelectedAccount(sessionId, adapter.id);
        }
    }
    static getSelectedAccount(sessionId, providerId) {
        return AuthManager.sessionSelections.get(sessionId)?.get(providerId);
    }
    static setSelectedAccount(sessionId, providerId, accountId) {
        let selections = AuthManager.sessionSelections.get(sessionId);
        if (!selections) {
            selections = new Map();
            AuthManager.sessionSelections.set(sessionId, selections);
        }
        selections.set(providerId, accountId);
    }
    static clearSelectedAccount(sessionId, providerId) {
        const selections = AuthManager.sessionSelections.get(sessionId);
        if (!selections)
            return;
        selections.delete(providerId);
        if (selections.size === 0) {
            AuthManager.sessionSelections.delete(sessionId);
        }
    }
}
//# sourceMappingURL=auth_manager.js.map