import executeAccess from '../../auth/executeAccess.js';
import { afterChange } from '../../fields/hooks/afterChange/index.js';
import { afterRead } from '../../fields/hooks/afterRead/index.js';
import { beforeChange } from '../../fields/hooks/beforeChange/index.js';
import { beforeValidate } from '../../fields/hooks/beforeValidate/index.js';
import { deepCopyObjectSimple } from '../../index.js';
import { checkDocumentLockStatus } from '../../utilities/checkDocumentLockStatus.js';
import { commitTransaction } from '../../utilities/commitTransaction.js';
import { getSelectMode } from '../../utilities/getSelectMode.js';
import { initTransaction } from '../../utilities/initTransaction.js';
import { killTransaction } from '../../utilities/killTransaction.js';
import { getLatestGlobalVersion } from '../../versions/getLatestGlobalVersion.js';
import { saveVersion } from '../../versions/saveVersion.js';
export const updateOperation = async (args)=>{
    if (args.publishSpecificLocale) {
        args.req.locale = args.publishSpecificLocale;
    }
    const { slug, autosave, depth, disableTransaction, draft: draftArg, globalConfig, overrideAccess, overrideLock, populate, publishSpecificLocale, req: { fallbackLocale, locale, payload }, req, select, showHiddenFields } = args;
    try {
        const shouldCommit = !disableTransaction && await initTransaction(req);
        let { data } = args;
        const shouldSaveDraft = Boolean(draftArg && globalConfig.versions?.drafts);
        // /////////////////////////////////////
        // 1. Retrieve and execute access
        // /////////////////////////////////////
        const accessResults = !overrideAccess ? await executeAccess({
            data,
            req
        }, globalConfig.access.update) : true;
        // /////////////////////////////////////
        // Retrieve document
        // /////////////////////////////////////
        const query = overrideAccess ? undefined : accessResults;
        // /////////////////////////////////////
        // 2. Retrieve document
        // /////////////////////////////////////
        const globalVersion = await getLatestGlobalVersion({
            slug,
            config: globalConfig,
            locale,
            payload,
            req,
            where: query
        });
        const { global, globalExists } = globalVersion || {};
        let globalJSON = {};
        if (globalVersion && globalVersion.global) {
            globalJSON = deepCopyObjectSimple(global);
            if (globalJSON._id) {
                delete globalJSON._id;
            }
        }
        const originalDoc = await afterRead({
            collection: null,
            context: req.context,
            depth: 0,
            doc: globalJSON,
            draft: draftArg,
            fallbackLocale,
            global: globalConfig,
            locale,
            overrideAccess: true,
            req,
            showHiddenFields
        });
        // ///////////////////////////////////////////
        // Handle potentially locked global documents
        // ///////////////////////////////////////////
        await checkDocumentLockStatus({
            globalSlug: slug,
            lockErrorMessage: `Global with slug "${slug}" is currently locked by another user and cannot be updated.`,
            overrideLock,
            req
        });
        // /////////////////////////////////////
        // beforeValidate - Fields
        // /////////////////////////////////////
        data = await beforeValidate({
            collection: null,
            context: req.context,
            data,
            doc: originalDoc,
            global: globalConfig,
            operation: 'update',
            overrideAccess,
            req
        });
        // /////////////////////////////////////
        // beforeValidate - Global
        // /////////////////////////////////////
        await globalConfig.hooks.beforeValidate.reduce(async (priorHook, hook)=>{
            await priorHook;
            data = await hook({
                context: req.context,
                data,
                global: globalConfig,
                originalDoc,
                req
            }) || data;
        }, Promise.resolve());
        // /////////////////////////////////////
        // beforeChange - Global
        // /////////////////////////////////////
        await globalConfig.hooks.beforeChange.reduce(async (priorHook, hook)=>{
            await priorHook;
            data = await hook({
                context: req.context,
                data,
                global: globalConfig,
                originalDoc,
                req
            }) || data;
        }, Promise.resolve());
        // /////////////////////////////////////
        // beforeChange - Fields
        // /////////////////////////////////////
        let publishedDocWithLocales = globalJSON;
        let versionSnapshotResult;
        const beforeChangeArgs = {
            collection: null,
            context: req.context,
            data,
            doc: originalDoc,
            docWithLocales: undefined,
            global: globalConfig,
            operation: 'update',
            req,
            skipValidation: shouldSaveDraft && globalConfig.versions.drafts && !globalConfig.versions.drafts.validate
        };
        if (publishSpecificLocale) {
            const latestVersion = await getLatestGlobalVersion({
                slug,
                config: globalConfig,
                payload,
                published: true,
                req,
                where: query
            });
            publishedDocWithLocales = latestVersion?.global || {};
            versionSnapshotResult = await beforeChange({
                ...beforeChangeArgs,
                docWithLocales: globalJSON
            });
        }
        let result = await beforeChange({
            ...beforeChangeArgs,
            docWithLocales: publishedDocWithLocales
        });
        // /////////////////////////////////////
        // Update
        // /////////////////////////////////////
        if (!shouldSaveDraft) {
            if (globalExists) {
                result = await payload.db.updateGlobal({
                    slug,
                    data: result,
                    req,
                    select
                });
            } else {
                result = await payload.db.createGlobal({
                    slug,
                    data: result,
                    req
                });
            }
        }
        // /////////////////////////////////////
        // Create version
        // /////////////////////////////////////
        if (globalConfig.versions) {
            const { globalType } = result;
            result = await saveVersion({
                autosave,
                docWithLocales: result,
                draft: shouldSaveDraft,
                global: globalConfig,
                payload,
                publishSpecificLocale,
                req,
                select,
                snapshot: versionSnapshotResult
            });
            result = {
                ...result,
                globalType
            };
        }
        // /////////////////////////////////////
        // Execute globalType field if not selected
        // /////////////////////////////////////
        if (select && result.globalType) {
            const selectMode = getSelectMode(select);
            if (selectMode === 'include' && !select['globalType'] || selectMode === 'exclude' && select['globalType'] === false) {
                delete result['globalType'];
            }
        }
        // /////////////////////////////////////
        // afterRead - Fields
        // /////////////////////////////////////
        result = await afterRead({
            collection: null,
            context: req.context,
            depth,
            doc: result,
            draft: draftArg,
            fallbackLocale: null,
            global: globalConfig,
            locale,
            overrideAccess,
            populate,
            req,
            select,
            showHiddenFields
        });
        // /////////////////////////////////////
        // afterRead - Global
        // /////////////////////////////////////
        await globalConfig.hooks.afterRead.reduce(async (priorHook, hook)=>{
            await priorHook;
            result = await hook({
                context: req.context,
                doc: result,
                global: globalConfig,
                req
            }) || result;
        }, Promise.resolve());
        // /////////////////////////////////////
        // afterChange - Fields
        // /////////////////////////////////////
        result = await afterChange({
            collection: null,
            context: req.context,
            data,
            doc: result,
            global: globalConfig,
            operation: 'update',
            previousDoc: originalDoc,
            req
        });
        // /////////////////////////////////////
        // afterChange - Global
        // /////////////////////////////////////
        await globalConfig.hooks.afterChange.reduce(async (priorHook, hook)=>{
            await priorHook;
            result = await hook({
                context: req.context,
                doc: result,
                global: globalConfig,
                previousDoc: originalDoc,
                req
            }) || result;
        }, Promise.resolve());
        // /////////////////////////////////////
        // Return results
        // /////////////////////////////////////
        if (shouldCommit) {
            await commitTransaction(req);
        }
        return result;
    } catch (error) {
        await killTransaction(req);
        throw error;
    }
};

//# sourceMappingURL=update.js.map