/**
 * studiograph user command — manage server user accounts.
 *
 * Phase C6 surface: every password input is a flag (`--password` or
 * `--password-stdin`), no interactive prompts. The CLI now works in CI
 * and agent flows out of the box. The web UI (Settings → Team) is the
 * canonical surface for member-tier owner UX; this command is the
 * break-glass recovery path.
 */
import { Command } from 'commander';
import { confirm, log } from '@clack/prompts';
import { Workspace } from '../../../core/workspace.js';
import { WorkspaceManager } from '../../../core/workspace-manager.js';
import { AuthService } from '../../../services/auth-service.js';
import { ensurePersonalFolder } from '../../../services/personal-folder.js';
import { authUserToGitUser, ensurePersonForUser } from '../../../services/user-person-bridge.js';
function getAuthService() {
    const workspace = new Workspace();
    if (!workspace.isWorkspace()) {
        console.error('❌ Not a Studiograph workspace. Run `studiograph init` first.');
        process.exit(1);
    }
    return new AuthService(process.cwd());
}
/**
 * Resolve a password from --password, --password-stdin, or fail. Inline
 * here rather than shared because the only two callers (add and reset-
 * password) need slightly different error wording — pulling this out
 * would obscure that.
 */
async function resolvePassword(cli, fromStdin, forCommand) {
    if (cli) {
        if (cli.length < 8) {
            console.error('❌ Password must be at least 8 characters.');
            process.exit(1);
        }
        return cli;
    }
    if (fromStdin) {
        const chunks = [];
        for await (const chunk of process.stdin)
            chunks.push(chunk);
        const value = Buffer.concat(chunks).toString('utf-8').replace(/\r?\n$/, '');
        if (value.length < 8) {
            console.error('❌ Password from stdin must be at least 8 characters.');
            process.exit(1);
        }
        return value;
    }
    console.error(`❌ ${forCommand} requires a password. Pass \`--password <pw>\` or \`--password-stdin\` (pipe the password to stdin).`);
    process.exit(1);
}
export const userCommand = new Command('user').description('Manage server users');
userCommand
    .command('add')
    .argument('<email>', 'User email address')
    .option('--name <name>', 'Display name', 'User')
    .option('--password <password>', 'Password (>= 8 characters)')
    .option('--password-stdin', 'Read the password from stdin')
    .option('--role <role>', 'User role (owner or member)', 'member')
    .option('--if-empty', 'Only create if no users exist yet')
    .action(async (email, opts) => {
    const auth = getAuthService();
    if (opts.ifEmpty && auth.hasUsers()) {
        auth.close();
        return;
    }
    const pw = await resolvePassword(opts.password, opts.passwordStdin, '`user add`');
    if (opts.role && opts.role !== 'owner' && opts.role !== 'member') {
        console.error(`❌ Invalid role "${opts.role}" — must be "owner" or "member".`);
        auth.close();
        process.exit(1);
    }
    const role = opts.role === 'owner' ? 'owner' : 'member';
    try {
        const user = auth.createUser(email, pw, opts.name, role);
        const workspace = new Workspace();
        await ensurePersonalFolder(workspace, auth, user);
        // Bridge: link or auto-provision a person entity for the new user.
        // Non-fatal; warn but don't fail the CLI command. Construct the
        // workspace manager lazily so it picks up the just-created personal
        // folder via reloadConfig().
        try {
            const config = await workspace.loadConfig();
            const gitUser = authUserToGitUser(user);
            const mgr = new WorkspaceManager(workspace.getWorkspacePath(), config, gitUser);
            const r = await ensurePersonForUser(mgr, auth, user, gitUser);
            if (r.action === 'skipped') {
                console.warn(`⚠ Person entity not auto-provisioned (${r.reason}). The user can link or create one from Settings → Profile.`);
            }
            else if (r.action !== 'already-linked') {
                console.log(`  ↳ ${r.action === 'created' ? 'Auto-provisioned' : 'Linked'} person/${r.ref.entityId} in ${r.ref.repo}.`);
            }
        }
        catch (err) {
            console.warn(`⚠ Could not bridge user to a person entity: ${err?.message ?? err}`);
        }
        console.log(`✓ Created ${user.role} user: ${user.email} (${user.displayName})`);
    }
    catch (err) {
        if (err.message?.includes('UNIQUE constraint')) {
            console.error(`❌ User ${email} already exists.`);
        }
        else {
            console.error(`❌ ${err.message}`);
        }
        process.exit(1);
    }
    finally {
        auth.close();
    }
});
userCommand
    .command('list')
    .action(async () => {
    const auth = getAuthService();
    const users = auth.listUsers();
    auth.close();
    if (users.length === 0) {
        console.log('No users configured. Run `studiograph user add <email> --password <pw>` to create one.');
        return;
    }
    console.log(`\n  ${'Email'.padEnd(30)} ${'Name'.padEnd(20)} ${'Role'.padEnd(8)} Created`);
    console.log(`  ${'─'.repeat(30)} ${'─'.repeat(20)} ${'─'.repeat(8)} ${'─'.repeat(19)}`);
    for (const u of users) {
        console.log(`  ${u.email.padEnd(30)} ${u.displayName.padEnd(20)} ${u.role.padEnd(8)} ${u.createdAt}`);
    }
    console.log();
});
userCommand
    .command('remove')
    .argument('<email>', 'User email address')
    .option('--yes', 'Skip confirmation prompt')
    .action(async (email, opts) => {
    const auth = getAuthService();
    // Check if this is the last owner
    const users = auth.listUsers();
    const target = users.find(u => u.email === email.toLowerCase().trim());
    if (!target) {
        console.error(`❌ User ${email} not found.`);
        auth.close();
        process.exit(1);
    }
    if (target.role === 'owner' && users.filter(u => u.role === 'owner').length <= 1) {
        console.error('❌ Cannot remove the last workspace owner. Transfer ownership first.');
        auth.close();
        process.exit(1);
    }
    if (!opts.yes) {
        const ok = await confirm({
            message: `Remove user ${target.email} (${target.displayName})?`,
        });
        if (!ok || typeof ok === 'symbol') {
            log.info('Cancelled.');
            auth.close();
            return;
        }
    }
    auth.deleteUser(email);
    console.log(`✓ Removed user: ${email}`);
    auth.close();
});
userCommand
    .command('reset-password')
    .argument('<email>', 'User email address')
    .option('--password <password>', 'New password (>= 8 characters)')
    .option('--password-stdin', 'Read the new password from stdin')
    .action(async (email, opts) => {
    const auth = getAuthService();
    const pw = await resolvePassword(opts.password, opts.passwordStdin, '`user reset-password`');
    try {
        const updated = auth.updatePassword(email, pw);
        if (!updated) {
            console.error(`❌ User ${email} not found.`);
            process.exit(1);
        }
        console.log(`✓ Password updated for ${email}`);
    }
    catch (err) {
        console.error(`❌ ${err.message}`);
        process.exit(1);
    }
    finally {
        auth.close();
    }
});
//# sourceMappingURL=user.js.map