/**
 * studiograph admin token — manage CLI API tokens for a Studiograph server.
 *
 * Today: just `issue <server-url>`. Future subcommands (revoke, list) can
 * accumulate here when the workflow calls for them.
 *
 * The `issue` flow:
 *   1. Owner provides email/password (flags, env vars, or interactive prompt).
 *   2. POST /api/auth/login → JWT cookie.
 *   3. mintAndStoreCliToken() POSTs /api/auth/tokens with the cookie and
 *      persists the resulting sg_ token to ~/.studiograph/user.json.
 *
 * Once the token is stored, `pull --remote` / `push --remote` resolve it
 * automatically and the CLI runs non-interactively.
 *
 * Pairs with `studiograph deploy`: after deploy completes and the owner
 * creates their account via the web UI setup form, they run
 *   studiograph admin token issue <server-url>
 * from their laptop to bootstrap CLI auth.
 */
import { Command } from 'commander';
import { intro, outro, text, password as promptPassword, isCancel, log } from '@clack/prompts';
import { mintAndStoreCliToken } from '../../../core/user-config.js';
/**
 * Exchange email/password for a JWT session cookie and mint+persist an sg_
 * CLI token from it. Exported (not a private helper) so tests can exercise
 * the login → mint flow without booting a real server or commander.
 *
 * On success: returns `{ ok: true, token, tokenName }` and the token has
 * already been persisted via `mintAndStoreCliToken`.
 * On failure: returns `{ ok: false, reason }` and nothing has been written.
 */
export async function issueCliToken(serverUrl, email, password, opts = {}) {
    const fetchFn = opts.fetchFn ?? fetch;
    const tokenName = opts.name?.trim()
        || `cli-${new URL(serverUrl).hostname}-${new Date().toISOString().slice(0, 10)}`;
    let cookieHeader;
    try {
        const loginRes = await fetchFn(`${serverUrl}/api/auth/login`, {
            method: 'POST',
            headers: { 'Content-Type': 'application/json' },
            body: JSON.stringify({ email, password }),
        });
        if (!loginRes.ok) {
            return { ok: false, reason: `Login failed: ${loginRes.status} ${loginRes.statusText}` };
        }
        const cookies = loginRes.headers.getSetCookie?.() ?? [];
        const tokenCookie = cookies.find((c) => c.startsWith('__sg_token='));
        if (!tokenCookie) {
            return { ok: false, reason: 'Server did not return a session cookie.' };
        }
        cookieHeader = tokenCookie.split(';')[0];
    }
    catch (err) {
        return { ok: false, reason: `Could not reach server: ${err instanceof Error ? err.message : String(err)}` };
    }
    const mint = await mintAndStoreCliToken(serverUrl, cookieHeader, { name: tokenName, fetchFn });
    if (!mint.ok)
        return mint;
    return { ok: true, token: mint.token, tokenName };
}
export const adminTokenCommand = new Command('token').description('Manage CLI API tokens for a Studiograph server');
adminTokenCommand
    .command('issue')
    .description('Mint and store a CLI API token for a Studiograph server')
    .argument('<server-url>', 'URL of the Studiograph server (e.g. https://studio.example.com)')
    .option('--email <email>', 'Owner email (also reads STUDIOGRAPH_EMAIL env var)')
    .option('--password <password>', 'Owner password (also reads STUDIOGRAPH_PASSWORD env var)')
    .option('--name <name>', 'Optional human-readable name for the token (default: cli-<hostname>-<date>)')
    .action(async (rawServerUrl, opts) => {
    intro('Issue Studiograph CLI token');
    const serverUrl = rawServerUrl.replace(/\/+$/, '');
    // Credentials: flags > env vars > interactive prompt. Mirrors clone's
    // bootstrap behavior and complies with feedback_cli_non_interactive —
    // agents and CI never see a prompt as long as flags or env vars are set.
    const flagEmail = opts.email?.trim();
    const flagPassword = opts.password;
    const envEmail = process.env.STUDIOGRAPH_EMAIL?.trim();
    const envPassword = process.env.STUDIOGRAPH_PASSWORD;
    let email;
    let pass;
    const providedEmail = flagEmail ?? envEmail;
    const providedPassword = flagPassword ?? envPassword;
    if (providedEmail && providedPassword) {
        if (!providedEmail.includes('@')) {
            outro('Invalid email address.');
            process.exit(1);
            return;
        }
        email = providedEmail;
        pass = providedPassword;
    }
    else {
        if (!process.stdout.isTTY) {
            outro('No TTY for interactive prompts. Pass --email and --password, or set STUDIOGRAPH_EMAIL + STUDIOGRAPH_PASSWORD.');
            process.exit(1);
            return;
        }
        const emailPrompt = await text({
            message: 'Owner email:',
            validate: (v) => (v.includes('@') ? undefined : 'Enter a valid email'),
        });
        if (isCancel(emailPrompt)) {
            outro('Cancelled');
            process.exit(0);
            return;
        }
        const passPrompt = await promptPassword({ message: 'Owner password:' });
        if (isCancel(passPrompt)) {
            outro('Cancelled');
            process.exit(0);
            return;
        }
        email = String(emailPrompt);
        pass = String(passPrompt);
    }
    const result = await issueCliToken(serverUrl, email, pass, { name: opts.name });
    if (!result.ok) {
        outro(result.reason);
        process.exit(1);
        return;
    }
    log.info(`Token stored in ~/.studiograph/user.json (name: "${result.tokenName}")`);
    outro(`Done. pull/push against ${serverUrl} will now be non-interactive.`);
});
//# sourceMappingURL=token.js.map