/**
 * AUDIT-4 one-shot migration — encrypt existing plaintext values in
 * SystemSetting rows whose key is registered as a secret.
 *
 * Run once after AUDIT-4 merges. Idempotent: rows already in `v1:...`
 * form are skipped.
 *
 *   Dry-run: npx tsx scripts/maint/encrypt-system-setting-secrets.ts
 *   Apply:   npx tsx scripts/maint/encrypt-system-setting-secrets.ts --apply
 *
 * Safe to run live — readers go through decryptIfSecret which handles
 * both forms transparently.
 */
import { PrismaClient } from '@prisma/client';
import 'dotenv/config';
import { encrypt, isEncrypted } from '../../src/lib/crypto/secret-vault';
import { SECRET_SETTING_KEYS } from '../../src/lib/services/system-setting-secrets';

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

async function main(): Promise<void> {
    const keys = Array.from(SECRET_SETTING_KEYS);
    const rows = await prisma.systemSetting.findMany({
        where: { key: { in: keys } },
    });

    const toMigrate = rows.filter((r) => r.value && !isEncrypted(r.value));

    console.log(
        `Scanned ${rows.length} rows across secret keys [${keys.join(', ')}]. ` +
        `${toMigrate.length} still in plaintext form.`,
    );

    if (toMigrate.length === 0) {
        console.log('All secret SystemSetting values are already encrypted. Done.');
        return;
    }

    for (const r of toMigrate) {
        console.log(`  - key=${r.key} (length=${r.value.length})`);
    }

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

    let migrated = 0;
    for (const r of toMigrate) {
        await prisma.systemSetting.update({
            where: { key: r.key },
            data: { value: encrypt(r.value) },
        });
        migrated++;
    }

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

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