"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.runAuthCommand = runAuthCommand;
exports.runAuthSetupFlow = runAuthSetupFlow;
const availability_1 = require("../auth-profiles/availability");
const credential_store_1 = require("../auth-profiles/credential-store");
const store_1 = require("../auth-profiles/store");
const kind_1 = require("../auth-profiles/kind");
const storage_1 = require("../auth-profiles/storage");
const storage_helpers_1 = require("../auth-profiles/storage-helpers");
const auth_setup_support_1 = require("./auth-setup-support");
const auth_clear_support_1 = require("./auth-clear-support");
const auth_message_sanitizer_1 = require("./auth-message-sanitizer");
const prompts_1 = require("./prompts");
const catalog_1 = require("../i18n/catalog");
const locale_1 = require("./locale");
async function runAuthCommand(options, deps = {}) {
    const locale = await (0, locale_1.loadCommandLocale)(process.cwd());
    switch (options.action) {
        case "setup":
            return runAuthSetupCommand(locale, deps);
        case "list":
            return runAuthListCommand(locale, deps);
        case "order":
            return runAuthOrderCommand(locale, deps);
        case "clear":
            return runAuthClearCommand(locale, options, deps);
    }
}
async function runAuthSetupFlow(locale, deps = {}) {
    const prompter = deps.prompter ?? (0, prompts_1.createCliPrompter)({ locale });
    if (!prompter.interactive) {
        throw new Error((0, catalog_1.translate)(locale, "auth.command.setup.requiresInteractive"));
    }
    try {
        const provider = await prompter.select({
            label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.provider"),
            options: [
                { value: "codex", label: "Codex" },
                { value: "claude", label: "Claude" },
            ],
            defaultValue: "codex",
        });
        if (provider === "codex") {
            const method = await prompter.select({
                label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.codexMethod"),
                options: [
                    {
                        value: "browser",
                        label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.codexBrowser"),
                    },
                    {
                        value: "device-auth",
                        label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.codexDevice"),
                    },
                    {
                        value: "api-key",
                        label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.codexApiKey"),
                    },
                    {
                        value: "env-var",
                        label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.codexEnv"),
                    },
                ],
                defaultValue: "browser",
            });
            if (method === "api-key") {
                const apiKey = await prompter.input({
                    label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.codexApiKeyValue"),
                    masked: true,
                    validate: (value) => {
                        if (!value.trim()) {
                            throw new Error((0, catalog_1.translate)(locale, "auth.command.setup.prompt.apiKeyRequired"));
                        }
                    },
                });
                return setupSavedAuthProfile({
                    provider: "codex",
                    method,
                    apiKey,
                }, locale, deps.runCodexLogin, deps.runClaudeLogin);
            }
            return setupSavedAuthProfile({
                provider: "codex",
                method,
            }, locale, deps.runCodexLogin, deps.runClaudeLogin, prompter, deps.credentialStore);
        }
        const method = await prompter.select({
            label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.claudeMethod"),
            options: [
                {
                    value: "config",
                    label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.claudeCli"),
                },
                {
                    value: "api-key",
                    label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.claudeApiKey"),
                },
                {
                    value: "env-var",
                    label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.claudeEnv"),
                },
            ],
            defaultValue: "config",
        });
        return setupSavedAuthProfile({
            provider: "claude",
            method,
        }, locale, undefined, deps.runClaudeLogin, prompter, deps.credentialStore);
    }
    catch (error) {
        if (error instanceof prompts_1.PromptCanceledError) {
            return null;
        }
        throw error;
    }
}
async function runAuthSetupCommand(locale, deps) {
    const profile = await runAuthSetupFlow(locale, deps);
    if (!profile) {
        console.log((0, catalog_1.translate)(locale, "auth.command.setup.canceled"));
        return 1;
    }
    const { profiles } = await (0, storage_1.loadAuthProfiles)(getAuthHomeDirectory());
    console.log((0, catalog_1.translate)(locale, "auth.command.setup.added", {
        label: (0, store_1.formatAuthAccountDisplay)(profile, profiles, locale),
    }));
    const provider = (0, store_1.getAuthProfileProvider)(profile);
    console.log((0, catalog_1.translate)(locale, "auth.command.setup.enableWorkerHint", {
        provider: (0, store_1.formatAuthProvider)(provider),
        worker: provider,
    }));
    return 0;
}
async function runAuthListCommand(locale, deps) {
    const homeDirectory = getAuthHomeDirectory();
    const getAvailability = deps.getAuthAvailability ?? availability_1.getSavedAuthAvailability;
    const [{ profiles }, { states }] = await Promise.all([
        (0, storage_1.loadAuthProfiles)(homeDirectory),
        (0, storage_1.loadAuthProfileStateFile)(homeDirectory),
    ]);
    if (profiles.length === 0) {
        console.log((0, catalog_1.translate)(locale, "auth.command.noAuthsConfigured"));
        return 0;
    }
    const stateByProfileId = new Map(states.map((state) => [state.profileId, state]));
    let hasAuthInvalidProfile = false;
    for (const profile of profiles) {
        const state = stateByProfileId.get(profile.id);
        const availability = await getAvailability(profile, deps.credentialStore);
        if (state && (0, kind_1.isAuthProfileInvalid)(state)) {
            hasAuthInvalidProfile = true;
        }
        console.log(formatListEntry(locale, profile, profiles, availability, state));
    }
    if (hasAuthInvalidProfile) {
        console.log((0, catalog_1.translate)(locale, "auth.command.list.authInvalidHelp"));
    }
    return 0;
}
async function runAuthOrderCommand(locale, deps) {
    const prompter = deps.prompter ?? (0, prompts_1.createCliPrompter)({ locale });
    if (!prompter.interactive) {
        throw new Error((0, catalog_1.translate)(locale, "auth.command.order.requiresInteractive"));
    }
    try {
        const homeDirectory = getAuthHomeDirectory();
        const { profiles } = await (0, storage_1.loadAuthProfiles)(homeDirectory);
        if (profiles.length === 0) {
            console.log((0, catalog_1.translate)(locale, "auth.command.noAuthsConfigured"));
            return 0;
        }
        const providers = getSavedAuthProviders(profiles);
        if (providers.length === 0) {
            console.log((0, catalog_1.translate)(locale, "auth.command.noAuthsConfigured"));
            return 0;
        }
        let provider;
        if (providers.length === 1) {
            const [onlyProvider] = providers;
            if (!onlyProvider) {
                throw new Error((0, catalog_1.translate)(locale, "auth.command.noAuthsConfigured"));
            }
            provider = onlyProvider;
        }
        else {
            provider = await prompter.select({
                label: (0, catalog_1.translate)(locale, "auth.command.order.prompt.provider"),
                options: providers.map((value) => ({
                    value,
                    label: (0, store_1.formatAuthProvider)(value),
                })),
                defaultValue: providers[0] ?? "codex",
            });
        }
        const providerProfiles = (0, storage_helpers_1.getProviderAuthProfiles)(profiles, provider);
        if (providerProfiles.length < 2) {
            console.log((0, catalog_1.translate)(locale, "auth.command.order.onlyOneForProvider", {
                provider: (0, store_1.formatAuthProvider)(provider),
            }));
            return 0;
        }
        console.log((0, catalog_1.translate)(locale, "auth.command.order.currentOrder", {
            provider: (0, store_1.formatAuthProvider)(provider),
        }));
        printNumberedProfiles(providerProfiles, locale);
        const selectedId = await prompter.select({
            label: (0, catalog_1.translate)(locale, "auth.command.order.prompt.selectMove"),
            options: providerProfiles.map((profile) => ({
                value: profile.id,
                label: (0, store_1.formatAuthAccountDisplay)(profile, providerProfiles, locale),
            })),
            defaultValue: providerProfiles[0]?.id ?? "",
        });
        const selectedIndex = providerProfiles.findIndex((profile) => profile.id === selectedId);
        if (selectedIndex === -1) {
            throw new Error((0, catalog_1.translate)(locale, "auth.command.order.selectedMissing"));
        }
        const selectedProfile = providerProfiles[selectedIndex];
        if (!selectedProfile) {
            throw new Error((0, catalog_1.translate)(locale, "auth.command.order.selectedMissing"));
        }
        const targetPosition = await prompter.input({
            label: (0, catalog_1.translate)(locale, "auth.command.order.prompt.moveTo", {
                label: (0, store_1.formatAuthAccountDisplay)(selectedProfile, providerProfiles, locale),
            }),
            defaultValue: String(selectedIndex + 1),
            validate: (value) => {
                const parsed = Number(value);
                if (!Number.isInteger(parsed)) {
                    throw new Error((0, catalog_1.translate)(locale, "auth.command.order.enterWholeNumber"));
                }
                if (parsed < 1 || parsed > providerProfiles.length) {
                    throw new Error((0, catalog_1.translate)(locale, "auth.command.order.choosePosition", {
                        count: providerProfiles.length,
                    }));
                }
            },
        });
        const reordered = moveProfileToPosition(providerProfiles, selectedIndex, Number(targetPosition) - 1, locale);
        console.log((0, catalog_1.translate)(locale, "auth.command.order.newOrder"));
        printNumberedProfiles(reordered, locale);
        const confirmed = await prompter.confirm({
            label: (0, catalog_1.translate)(locale, "auth.command.order.prompt.save"),
            defaultValue: true,
        });
        if (!confirmed) {
            console.log((0, catalog_1.translate)(locale, "auth.command.order.changeCanceled"));
            return 1;
        }
        await (0, storage_1.setAuthProfileProviderOrder)(provider, reordered.map((profile) => profile.id), homeDirectory);
        return 0;
    }
    catch (error) {
        if (error instanceof prompts_1.PromptCanceledError) {
            console.log((0, catalog_1.translate)(locale, "auth.command.order.canceled"));
            return 1;
        }
        throw error;
    }
}
async function runAuthClearCommand(locale, options, deps) {
    const prompter = deps.prompter ?? (0, prompts_1.createCliPrompter)({ locale });
    try {
        const homeDirectory = getAuthHomeDirectory();
        let profiles;
        try {
            profiles = (await (0, storage_1.loadAuthProfiles)(homeDirectory)).profiles;
        }
        catch (error) {
            if (options.all &&
                options.yes &&
                options.targetProvider === undefined &&
                options.invalid !== true) {
                const credentialDeleteFailures = await (0, storage_1.clearAllAuthProfiles)(homeDirectory, deps.credentialStore);
                console.log((0, catalog_1.translate)(locale, "auth.command.clear.clearedAll"));
                (0, auth_clear_support_1.printCredentialDeleteFailureWarning)(locale, credentialDeleteFailures.length);
                return 0;
            }
            throw error;
        }
        if (profiles.length === 0) {
            console.log((0, catalog_1.translate)(locale, "auth.command.noAuthsConfigured"));
            return 0;
        }
        const hasSelector = (0, auth_clear_support_1.hasAuthClearSelector)(options);
        let selectedProfiles;
        if (hasSelector) {
            selectedProfiles = await (0, auth_clear_support_1.filterAuthClearProfiles)(profiles, options, homeDirectory, deps.getAuthAvailability ?? availability_1.getSavedAuthAvailability, deps.credentialStore);
        }
        else if (prompter.interactive) {
            const selectedIds = await prompter.checkbox({
                label: (0, catalog_1.translate)(locale, "auth.command.clear.prompt.selectRemove"),
                options: profiles.map((profile) => ({
                    value: profile.id,
                    label: (0, store_1.formatAuthAccountDisplay)(profile, profiles, locale),
                })),
                defaultValue: [],
            });
            selectedProfiles = profiles.filter((profile) => selectedIds.includes(profile.id));
        }
        else {
            throw new Error((0, catalog_1.translate)(locale, "auth.command.clear.requiresInteractiveOrSelector"));
        }
        if (selectedProfiles.length === 0) {
            if (hasSelector) {
                console.log((0, catalog_1.translate)(locale, "auth.command.clear.noMatching"));
                return 0;
            }
            console.log((0, catalog_1.translate)(locale, "auth.command.clear.canceled"));
            return 1;
        }
        if (!options.yes) {
            if (!prompter.interactive) {
                throw new Error((0, catalog_1.translate)(locale, "auth.command.clear.requiresYes"));
            }
            (0, auth_clear_support_1.printClearNotes)(locale, selectedProfiles);
            const confirmed = await prompter.confirm({
                label: (0, catalog_1.translate)(locale, "auth.command.clear.prompt.remove", {
                    count: renderSavedAuthCount(locale, selectedProfiles),
                }),
                defaultValue: false,
            });
            if (!confirmed) {
                console.log((0, catalog_1.translate)(locale, "auth.command.clear.canceled"));
                return 1;
            }
        }
        const disabledProviders = (0, auth_clear_support_1.getAuthClearDisabledProviders)(profiles, selectedProfiles);
        const removeResults = [];
        for (const profile of selectedProfiles) {
            removeResults.push(await (0, storage_1.removeAuthProfile)(profile.id, homeDirectory, deps.credentialStore));
        }
        console.log((0, catalog_1.translate)(locale, "auth.command.clear.cleared", {
            count: renderSavedAuthCount(locale, selectedProfiles),
        }));
        (0, auth_clear_support_1.printCredentialDeleteFailureWarning)(locale, removeResults.filter((result) => result.kind === "removed" && result.credentialDeleteFailure).length);
        printClearWorkerHints(locale, disabledProviders);
        return 0;
    }
    catch (error) {
        if (error instanceof prompts_1.PromptCanceledError) {
            console.log((0, catalog_1.translate)(locale, "auth.command.clear.canceled"));
            return 1;
        }
        throw error;
    }
}
async function setupSavedAuthProfile(input, locale, runCodexLogin = auth_setup_support_1.defaultRunCodexLogin, runClaudeLogin = auth_setup_support_1.defaultRunClaudeLogin, prompter = (0, prompts_1.createCliPrompter)({ locale }), credentialStore) {
    const homeDirectory = getAuthHomeDirectory();
    const profile = (0, auth_setup_support_1.unwrapRegisteredAuthProfile)(await (0, storage_1.registerAuthProfile)((0, auth_setup_support_1.buildRegisterAuthProfileInput)(input), homeDirectory), locale);
    try {
        if (input.provider === "codex" && input.method !== "env-var") {
            const codexHomePath = (0, auth_setup_support_1.getCodexHomePathForSavedAuth)(profile, locale);
            if (input.method === "api-key") {
                await runCodexLogin(codexHomePath, input.method, locale, input.apiKey);
            }
            else {
                await runCodexLogin(codexHomePath, input.method, locale);
            }
        }
        else if (input.method === "config") {
            await runClaudeLogin((0, auth_setup_support_1.getClaudeConfigPathForSavedAuth)(profile, locale), locale);
        }
        else if (input.provider === "claude" && input.method === "api-key") {
            await setupClaudeApiKeyCredential(profile, prompter, locale, credentialStore);
        }
        return profile;
    }
    catch (error) {
        await (0, storage_1.removeAuthProfile)(profile.id, homeDirectory, credentialStore);
        throw error;
    }
}
async function setupClaudeApiKeyCredential(profile, prompter, locale, credentialStore) {
    if (profile.kind !== "claude-api-key") {
        throw new Error((0, catalog_1.translate)(locale, "auth.command.setup.expectedClaudeApiKey"));
    }
    const apiKey = await prompter.input({
        label: (0, catalog_1.translate)(locale, "auth.command.setup.prompt.claudeApiKeyValue"),
        masked: true,
        validate: (value) => {
            if (!value.trim()) {
                throw new Error((0, catalog_1.translate)(locale, "auth.command.setup.prompt.requiredApiKey"));
            }
        },
    });
    (0, credential_store_1.writeStoredCredential)(profile, apiKey.trim(), credentialStore);
}
function formatListEntry(locale, profile, profiles, availability, state) {
    const label = (0, store_1.formatAuthAccountDisplay)(profile, profiles, locale);
    if (state && (0, kind_1.isAuthProfileInvalid)(state)) {
        const reason = state.lastReason
            ? (0, catalog_1.translate)(locale, "auth.command.list.authInvalidReason", {
                reason: (0, auth_message_sanitizer_1.sanitizeAuthMessage)(state.lastReason, locale),
            })
            : "";
        return (0, catalog_1.translate)(locale, "auth.command.list.authInvalid", {
            label,
            reason,
        });
    }
    if (!availability.available) {
        switch (availability.reason) {
            case "missing_env_var":
                return (0, catalog_1.translate)(locale, "auth.command.list.missingEnvVar", {
                    label,
                    envVarName: availability.envVarName,
                });
            case "missing_stored_credential":
                return (0, catalog_1.translate)(locale, "auth.command.list.missingStoredCredential", {
                    label,
                });
            case "missing_managed_sign_in_data":
                return (0, catalog_1.translate)(locale, "auth.command.list.missingManagedData", {
                    label,
                });
            case "auth_unavailable":
                return (0, catalog_1.translate)(locale, "auth.command.list.authUnavailable", {
                    label,
                });
        }
    }
    if (state && (0, store_1.isAuthProfileOnCooldown)(state) && state.cooldownUntil) {
        return (0, catalog_1.translate)(locale, "auth.command.list.unavailableUntil", {
            label,
            cooldownUntil: state.cooldownUntil,
        });
    }
    return (0, catalog_1.translate)(locale, "auth.command.list.availableNow", { label });
}
function printClearWorkerHints(locale, providers) {
    for (const provider of providers) {
        console.log((0, catalog_1.translate)(locale, "auth.command.clear.disableWorkerHint", {
            provider: (0, store_1.formatAuthProvider)(provider),
            worker: provider,
        }));
    }
}
function renderSavedAuthCount(locale, profiles) {
    if (profiles.length === 1) {
        return (0, catalog_1.translate)(locale, "auth.command.savedAuthCount.one");
    }
    return (0, catalog_1.translate)(locale, "auth.command.savedAuthCount.many", {
        count: profiles.length,
    });
}
function printNumberedProfiles(profiles, locale) {
    profiles.forEach((profile, index) => {
        console.log(`${index + 1}. ${(0, store_1.formatAuthAccountDisplay)(profile, profiles, locale)}`);
    });
}
function moveProfileToPosition(profiles, currentIndex, targetIndex, locale) {
    const next = [...profiles];
    const [moved] = next.splice(currentIndex, 1);
    if (!moved) {
        throw new Error((0, catalog_1.translate)(locale, "auth.command.order.selectedUnavailable"));
    }
    next.splice(targetIndex, 0, moved);
    return next;
}
function getSavedAuthProviders(profiles) {
    const providers = [];
    for (const profile of profiles) {
        const provider = (0, store_1.getAuthProfileProvider)(profile);
        if (!providers.includes(provider)) {
            providers.push(provider);
        }
    }
    return providers;
}
function getAuthHomeDirectory() {
    const { HOME: home } = process.env;
    return home?.trim() || undefined;
}
