/** Frontend-specific helpers used by the frontend package install scripts. */
import { SyntaxKind } from 'ts-morph';
/**
 * Idempotently swap the `CurrentAccountService` provider in
 * `aurora.provider.ts` from `AnonymousCurrentAccountAdapter` to
 * `CurrentAccountIamAdapter` (design D5).
 *
 * Operations (all idempotent):
 * 1. Add `import { CurrentAccountIamAdapter } from './domains/admin/bounded-contexts/iam/account'`
 *    — skipped when the import is already present.
 * 2. Find the object literal whose `provide` property text is `CurrentAccountService`
 *    and set its `useClass` initializer to `CurrentAccountIamAdapter`
 *    — no-op when `useClass` is already `CurrentAccountIamAdapter`.
 * 3. Remove the `AnonymousCurrentAccountAdapter` named specifier from the
 *    existing `@aurora` import declaration — never drops the whole import,
 *    just the one named specifier; no-op when already absent.
 *
 * Saves the file synchronously via ts-morph `saveSync()`.
 */
export function swapCurrentAccountAdapter(ctx) {
    const sf = ctx.sourceFile('app', 'aurora.provider.ts');
    const IAM_ADAPTER = 'CurrentAccountIamAdapter';
    const ANON_ADAPTER = 'AnonymousCurrentAccountAdapter';
    const IAM_IMPORT_PATH = './domains/admin/bounded-contexts/iam/account';
    // ── 1. Add CurrentAccountIamAdapter import ────────────────────────────────
    const existingIamImport = sf.getImportDeclarations().find((d) => d.getModuleSpecifierValue() === IAM_IMPORT_PATH);
    if (existingIamImport) {
        // Ensure the named import is present in an existing declaration
        const alreadyNamed = existingIamImport
            .getNamedImports()
            .some((n) => n.getName() === IAM_ADAPTER);
        if (!alreadyNamed) {
            existingIamImport.addNamedImport(IAM_ADAPTER);
        }
    }
    else {
        sf.addImportDeclaration({
            moduleSpecifier: IAM_IMPORT_PATH,
            namedImports: [IAM_ADAPTER],
        });
    }
    // ── 2. Swap useClass on the CurrentAccountService provider ────────────────
    for (const obj of sf.getDescendantsOfKind(SyntaxKind.ObjectLiteralExpression)) {
        const provideProp = obj.getProperty('provide');
        if (!provideProp)
            continue;
        // The property value is the initializer of the PropertyAssignment
        const provideInit = provideProp.getInitializer?.();
        const provideValueText = provideInit?.getText() ?? provideProp.getLastChild()?.getText() ?? '';
        if (provideValueText !== 'CurrentAccountService')
            continue;
        const useClassProp = obj.getProperty('useClass');
        if (!useClassProp)
            continue;
        const currentValue = useClassProp.getInitializer()?.getText() ?? '';
        if (currentValue === IAM_ADAPTER)
            continue; // already correct — no-op
        useClassProp.setInitializer(IAM_ADAPTER);
        break;
    }
    // ── 3. Remove AnonymousCurrentAccountAdapter from @aurora import ──────────
    const auroraImport = sf.getImportDeclaration((d) => d.getModuleSpecifierValue() === '@aurora');
    if (auroraImport) {
        const anonSpecifier = auroraImport.getNamedImports().find((n) => n.getName() === ANON_ADAPTER);
        if (anonSpecifier) {
            anonSpecifier.remove();
        }
    }
    sf.saveSync();
}
/**
 * Run the consumer's own Prettier over a list of workspace-relative file paths.
 *
 * Identical contract to the backend `formatWorkspaceFiles` in `package-helpers.ts`
 * but accepts a `FrontPackageInstallerContext` (the frontend context does not
 * expose `install`, so it cannot be the backend `PackageInstallerContext`).
 *
 * Using `npx prettier --write` delegates to the consumer's installed Prettier
 * binary and config (including `prettier-plugin-organize-imports` and trailing-
 * comma settings), so the output is byte-for-byte equivalent to what the consumer's
 * `pnpm lint` would produce.
 *
 * Non-fatal: a Prettier failure warns and continues so the install is not aborted
 * for cosmetic reasons.
 */
export async function formatFrontWorkspaceFiles(ctx, relativePaths) {
    // Try the local workspace prettier binary (pnpm hoists it to
    // `node_modules/.bin/prettier` inside the frontend dir), then fall back to
    // `npx prettier`. Non-fatal: a failure warns and continues.
    try {
        await ctx.exec('./node_modules/.bin/prettier', ['--write', ...relativePaths]);
    }
    catch {
        try {
            await ctx.exec('npx', ['prettier', '--write', ...relativePaths]);
        }
        catch {
            console.warn('[aurora-catalyst] prettier --write failed; files are correct but may not match your formatting config. Run `npx prettier --write` manually.');
        }
    }
}
