"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.__tsfTypeAliases = void 0;
exports.parseMigrationCommandOptions = parseMigrationCommandOptions;
exports.executeMigrationCommand = executeMigrationCommand;
const node_path_1 = require("node:path");
const database_1 = require("../database");
const services_1 = require("../services");
function parseMigrationCommandOptions(command, args, options = {}) {
    let appPath;
    let description = 'auto_migration';
    let migrationsDir = 'src/migrations';
    let pgSchema;
    const tableNames = [];
    const positionals = [];
    for (let index = 0; index < args.length; index++) {
        const arg = args[index];
        switch (arg) {
            case '--app':
                if (!options.allowApp)
                    throw new Error(`Unknown option: ${arg}`);
                appPath = requiredValue(args, ++index, arg);
                break;
            case '--description':
            case '-d':
                description = requiredValue(args, ++index, arg);
                break;
            case '--migrations-dir':
                migrationsDir = requiredValue(args, ++index, arg);
                break;
            case '--pg-schema':
                pgSchema = requiredNonEmptyValue(args, ++index, arg);
                break;
            case '--table':
                tableNames.push(parseTableName(requiredValue(args, ++index, arg), arg));
                break;
            case '--tables':
                tableNames.push(...splitTableNames(requiredValue(args, ++index, arg)));
                break;
            default:
                if (options.allowApp && arg.startsWith('--app='))
                    appPath = arg.slice('--app='.length);
                else if (arg.startsWith('--description='))
                    description = arg.slice('--description='.length);
                else if (arg.startsWith('--migrations-dir='))
                    migrationsDir = arg.slice('--migrations-dir='.length);
                else if (arg.startsWith('--pg-schema='))
                    pgSchema = parseNonEmptyValue(arg.slice('--pg-schema='.length), '--pg-schema');
                else if (arg.startsWith('--table='))
                    tableNames.push(parseTableName(arg.slice('--table='.length), '--table'));
                else if (arg.startsWith('--tables='))
                    tableNames.push(...splitTableNames(arg.slice('--tables='.length)));
                else if (command === 'charset' && !arg.startsWith('-'))
                    positionals.push(arg);
                else
                    throw new Error(`Unknown option: ${arg}`);
        }
    }
    if (command === 'charset' && positionals.length > 2)
        throw new Error('charset accepts at most charset and collation arguments');
    return {
        appPath: appPath ? (0, node_path_1.resolve)(appPath) : undefined,
        description,
        migrationsDir: (0, node_path_1.resolve)(migrationsDir),
        pgSchema,
        tableNames: tableNames.length ? [...new Set(tableNames)] : undefined,
        positionals
    };
}
async function executeMigrationCommand(app, command, options) {
    const db = app.get(database_1.BaseDatabase);
    try {
        switch (command) {
            case 'create':
                await createMigration(db, options);
                return;
            case 'run':
                await runMigrations(app, db, options);
                return;
            case 'reset':
                await resetMigrationFiles(db, options);
                return;
            case 'charset':
                await standardizeCharset(db, options);
                return;
        }
    }
    finally {
        if (command === 'run' && app.options.enableWorker)
            await app.get(services_1.WorkerQueueRegistry).shutdown();
        await db.driver.close();
    }
}
async function createMigration(db, options) {
    const plan = await (0, database_1.createMigrationPlan)(db, {
        pgSchema: options.pgSchema,
        tableNames: options.tableNames
    });
    if (!plan.hasChanges) {
        console.log('No schema changes detected.');
        return;
    }
    const file = (0, database_1.writeMigrationFile)(plan.statements, options.description, {
        migrationsDir: options.migrationsDir
    });
    console.log(`Created migration: ${file}`);
}
async function runMigrations(app, db, options) {
    const migrations = await (0, database_1.loadMigrationsFromDirectory)(options.migrationsDir);
    const executions = await new database_1.MigrationRunner(db).run(migrations);
    if (app.options.enableWorker)
        await app.get(services_1.WorkerRunnerService).removeStaleBullMqCronJobs();
    console.log(`Ran ${executions.length} migration(s).`);
}
async function resetMigrationFiles(db, options) {
    const result = await (0, database_1.resetMigrations)(db, {
        migrationsDir: options.migrationsDir,
        pgSchema: options.pgSchema
    });
    console.log(`Removed ${result.removedFiles.length} migration file(s).`);
    if (result.migrationPath) {
        console.log(`Created base migration: ${result.migrationPath}`);
    }
    else {
        console.log('No entity tables found; no base migration created.');
    }
}
async function standardizeCharset(db, options) {
    const result = await (0, database_1.standardizeDbCollation)(db, {
        charset: options.positionals[0],
        collation: options.positionals[1]
    });
    if (!result.skipped)
        console.log(`Standardized ${result.tables.length} table(s) in ${result.databaseName}.`);
}
function splitTableNames(value) {
    const parts = value.split(',').map(table => table.trim());
    if (!parts.length || parts.some(table => !table))
        throw new Error('--tables requires one or more non-empty table names');
    return parts;
}
function requiredValue(args, index, flag) {
    const value = args[index];
    if (!value)
        throw new Error(`${flag} requires a value`);
    return value;
}
function requiredNonEmptyValue(args, index, flag) {
    return parseNonEmptyValue(requiredValue(args, index, flag), flag);
}
function parseTableName(value, flag) {
    return parseNonEmptyValue(value, flag);
}
function parseNonEmptyValue(value, flag) {
    const trimmed = value.trim();
    if (!trimmed)
        throw new Error(`${flag} requires a non-empty value`);
    return trimmed;
}
exports.__tsfTypeAliases = JSON.parse("[1,{\"MigrationCommandOptions\":{\"kind\":18,\"typeName\":\"MigrationCommandOptions\",\"types\":[{\"kind\":20,\"name\":\"appPath\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"description\",\"type\":{\"kind\":6},\"optional\":false},{\"kind\":20,\"name\":\"migrationsDir\",\"type\":{\"kind\":6},\"optional\":false},{\"kind\":20,\"name\":\"pgSchema\",\"type\":{\"kind\":12,\"types\":[{\"kind\":6},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"tableNames\",\"type\":{\"kind\":12,\"types\":[{\"kind\":14,\"type\":{\"kind\":6}},{\"kind\":4}]},\"optional\":true},{\"kind\":20,\"name\":\"positionals\",\"type\":{\"kind\":14,\"type\":{\"kind\":6}},\"optional\":false}]},\"MigrationEntrypointCommand\":{\"kind\":12,\"types\":[{\"kind\":10,\"literal\":\"create\"},{\"kind\":10,\"literal\":\"run\"},{\"kind\":10,\"literal\":\"reset\"},{\"kind\":10,\"literal\":\"charset\"}],\"typeName\":\"MigrationEntrypointCommand\"}}]")[1];
//# sourceMappingURL=migrations-entrypoint.js.map