import { PluginDoesNotImplementFunctionError, PluginMissingError, } from "../plugin/errors.js";
export async function importFiles(args) {
    const plugin = args.plugins.find((p) => p.key === args.pluginKey);
    if (!plugin)
        throw new PluginMissingError({ plugin: args.pluginKey });
    if (!plugin.importFiles) {
        throw new PluginDoesNotImplementFunctionError({
            plugin: args.pluginKey,
            function: "importFiles",
        });
    }
    const imported = await plugin.importFiles({
        files: args.files,
        settings: structuredClone(args.settings),
    });
    await args.db.transaction().execute(async (trx) => {
        // upsert every bundle
        for (const bundle of imported.bundles) {
            await trx
                .insertInto("bundle")
                .values(bundle)
                .onConflict((oc) => oc.column("id").doUpdateSet(bundle))
                .execute();
        }
        // upsert every message
        for (const message of imported.messages) {
            // match the message by bundle id and locale if
            // no id is provided by the importer
            if (message.id === undefined) {
                const exisingMessage = await trx
                    .selectFrom("message")
                    .where("bundleId", "=", message.bundleId)
                    .where("locale", "=", message.locale)
                    .select("id")
                    .executeTakeFirst();
                message.id = exisingMessage?.id;
            }
            try {
                await trx
                    .insertInto("message")
                    .values(message)
                    .onConflict((oc) => oc.column("id").doUpdateSet(message))
                    .execute();
            }
            catch (e) {
                // 787 = SQLITE_CONSTRAINT_FOREIGNKEY
                // handle foreign key violation
                // e.g. a message references a bundle that doesn't exist
                // by creating the bundle
                if (e?.resultCode === 787) {
                    await trx
                        .insertInto("bundle")
                        .values({ id: message.bundleId })
                        .execute();
                    await trx.insertInto("message").values(message).execute();
                }
                else {
                    throw e;
                }
            }
        }
        // upsert every variant
        for (const variant of imported.variants) {
            // match the variant by message id and matches if
            // no id is provided by the importer
            if (variant.id === undefined) {
                let existingMessage = await trx
                    .selectFrom("message")
                    .where("bundleId", "=", variant.messageBundleId)
                    .where("locale", "=", variant.messageLocale)
                    .select("id")
                    .executeTakeFirst();
                // if the message does not exist, create it
                if (existingMessage === undefined) {
                    const existingBundle = await trx
                        .selectFrom("bundle")
                        .where("id", "=", variant.messageBundleId)
                        .select("id")
                        .executeTakeFirst();
                    // if the bundle does not exist, create it
                    if (existingBundle === undefined) {
                        await trx
                            .insertInto("bundle")
                            .values({ id: variant.messageBundleId })
                            .execute();
                    }
                    // insert the message
                    existingMessage = await trx
                        .insertInto("message")
                        .values({
                        bundleId: variant.messageBundleId,
                        locale: variant.messageLocale,
                    })
                        .returningAll()
                        .executeTakeFirstOrThrow();
                }
                const existingVariants = await trx
                    .selectFrom("variant")
                    .where("messageId", "=", existingMessage.id)
                    .selectAll()
                    .execute();
                const existingVariant = existingVariants.find((v) => JSON.stringify(v.matches) === JSON.stringify(variant.matches));
                // need to reset typescript's type narrowing
                variant.id = existingVariant?.id;
                variant.messageId = existingMessage.id;
            }
            const toBeInsertedVariant = {
                ...variant,
                // @ts-expect-error - bundle id is provided by VariantImport but not needed when inserting
                messageBundleId: undefined,
                messageLocale: undefined,
            };
            await trx
                .insertInto("variant")
                .values(toBeInsertedVariant)
                .onConflict((oc) => oc.column("id").doUpdateSet(toBeInsertedVariant))
                .execute();
        }
    });
}
//# sourceMappingURL=importFiles.js.map