/**
 * AUDIT-3 one-shot migration — encrypt existing plaintext TOTP secrets.
 *
 * Run once after PR-48 (AUDIT-3) merges to upgrade existing rows from
 * plaintext to the AES-256-GCM envelope used for channel configs.
 * Idempotent: rows already in `v1:...` form are skipped.
 *
 *   Dry-run:  npx tsx scripts/maint/encrypt-totp-secrets.ts
 *   Apply:    npx tsx scripts/maint/encrypt-totp-secrets.ts --apply
 *
 * Safe to run while the app is live — the read path
 * (TwoFactorService.verifyCode + getSecret) goes through
 * decryptIfNeeded which handles both forms transparently.
 *
 * The script reads CHANNEL_ENCRYPTION_KEY from env, same key used
 * elsewhere. Must be set.
 */
import { PrismaClient } from '@prisma/client';
import 'dotenv/config';
import { encrypt, isEncrypted } from '../../src/lib/crypto/secret-vault';

const prisma = new PrismaClient();
const APPLY = process.argv.includes('--apply');

async function main(): Promise<void> {
    const users = await prisma.user.findMany({
        where: { totpEnabled: true, totpSecret: { not: null } },
        select: { id: true, email: true, totpSecret: true },
    });

    if (users.length === 0) {
        console.log('No users with totpEnabled=true; nothing to do.');
        return;
    }

    const needsEncryption = users.filter((u) => u.totpSecret && !isEncrypted(u.totpSecret));

    console.log(
        `Scanned ${users.length} user(s) with 2FA enabled. ` +
        `${needsEncryption.length} still in plaintext form.`,
    );

    if (needsEncryption.length === 0) {
        console.log('All TOTP secrets are already encrypted. Done.');
        return;
    }

    for (const u of needsEncryption) {
        console.log(`  - id=${u.id} email=${u.email}`);
    }

    if (!APPLY) {
        console.log('\nDry-run. Re-run with --apply to encrypt the listed rows.');
        return;
    }

    let migrated = 0;
    for (const u of needsEncryption) {
        if (!u.totpSecret) continue;
        const enc = encrypt(u.totpSecret);
        await prisma.user.update({
            where: { id: u.id },
            data: { totpSecret: enc },
        });
        migrated++;
    }

    console.log(`\nEncrypted ${migrated} TOTP secret(s).`);
}

main()
    .catch((e) => {
        console.error('FAILED:', e instanceof Error ? e.message : e);
        process.exit(1);
    })
    .finally(() => prisma.$disconnect());
