import { FormPageState, isMobileDevice, } from '@wix/bex-core';
import { action, computed, makeObservable, observable } from 'mobx';
import { EntityPageStateBIReporter } from './EntityPageStateBIReporter';
import { EventEmitter } from '@wix/bex-core/events';
export class EntityPageState {
    constructor(params) {
        this._entity = null;
        this._routerState = null;
        this.events = new EventEmitter();
        this.fetch = params.fetch;
        this.onSave = params.onSave;
        this.saveSuccessToast = params.saveSuccessToast;
        this.saveErrorToast = params.saveErrorToast;
        this.formPage = new FormPageState({ form: params.form });
        this._parentPageId = params.parentPageId;
        this.transformEntityToCollectionItem =
            params.transformEntityToCollectionItem || ((anEntity) => anEntity);
        this._parentPath = params.parentPath;
        this.container = params.container;
        this._routerState = params.routerState ?? null;
        if (this._routerState) {
            this._entity = this._routerState.currentState?._chosenEntity?.entity;
        }
        this.reportBI = this.container.createBILogger({
            componentType: 'Entity page',
            pageType: 'Entity',
            route: window.location.pathname,
        });
        this.bi = new EntityPageStateBIReporter({
            reportBI: this.reportBI,
            entityPageState: this,
        });
        this.bi.init();
        makeObservable(this, {
            handleSubmit: action,
            _entity: observable.ref,
            setEntity: action,
            isFormDirty: computed,
            _withinRouter: computed,
        });
    }
    init() {
        this._checkPageParams();
        const { formPage: { initTask }, container, } = this;
        const { onBeforeUnload } = container;
        const onBeforeUnloadSubscription = onBeforeUnload?.(action((event) => {
            if (isMobileDevice()) {
                return;
            }
            const { form } = this;
            // Check both react-hook-form's state AND the explicitly set flag
            if (form.formState.isSubmitSuccessful ||
                this.formPage._isSubmitSuccessful ||
                !this.isFormDirty) {
                return;
            }
            event.preventDefault();
            this.bi.reportOnBeforeUnload();
        }));
        initTask.runOnce(async () => {
            const [data] = await Promise.all([
                this.fetch(),
                container.initTask.status.promise,
            ]);
            this.setEntity(data.entity ?? null);
            this.bi.appLoaded?.();
        });
        return () => {
            onBeforeUnloadSubscription?.remove();
        };
    }
    retryFetch() {
        this.formPage.retryFetch();
    }
    setEntity(newEntity) {
        this._entity = newEntity;
    }
    get entity() {
        return this._entity;
    }
    get isFetching() {
        return this.formPage.isFetching;
    }
    get form() {
        return this.formPage.form;
    }
    set isSubmitSuccessful(flag) {
        this.formPage.isSubmitSuccessful = flag;
    }
    get isFormDirty() {
        return this.formPage.isDirty;
    }
    // backwards compatibility
    set _isFormDirty(val) {
        this.formPage._isFormDirty = val;
    }
    get _withinRouter() {
        return !!this._routerState;
    }
    onCancel() {
        this.bi.reportButtonClick({
            ctaName: 'Cancel',
            additionalInfo: this.actionsBarConfig?.cancelCta?.biAdditionalInfo,
        });
        this.navigateToParent();
    }
    navigateToParent(updatedEntity) {
        const entityStringKey = this._entity ? '_updatedEntity' : '_createdEntity';
        const entityObject = { [entityStringKey]: updatedEntity };
        if (this._withinRouter) {
            this._routerState.navigate(this._parentPath, { state: entityObject });
        }
        else {
            this.container.navigateTo({
                pageId: this._parentPageId,
            });
        }
    }
    _showErrorToast(err, e) {
        const errorToast = this.saveErrorToast?.(err, {
            retry: () => this.handleSubmit(e),
        });
        const message = typeof errorToast === 'string' ? errorToast : errorToast?.message;
        const showTryAgain = typeof errorToast === 'string' ? true : errorToast?.tryAgain !== false;
        const action = typeof errorToast === 'string' ? undefined : errorToast?.action;
        this.container.showToast?.({
            type: 'ERROR',
            biName: 'cairo-entity-page-save-error-toast',
            message: message ??
                this.container.translate(err?.code === 'ERR_NETWORK'
                    ? 'cairo.entityPage.saveError-offline.toast.description'
                    : 'cairo.entityPage.saveError-technical.toast.description'),
            action: action || showTryAgain
                ? {
                    uiType: 'LINK',
                    text: action?.text ?? this.container.translate('cairo.toast.retry'),
                    onClick: () => {
                        if (action?.onClick) {
                            action.onClick();
                        }
                        else {
                            this.bi.reportSaveTryAgain();
                            this.handleSubmit(e);
                        }
                    },
                    removeToastOnClick: true,
                }
                : undefined,
        });
    }
    _showSuccessToast() {
        const message = typeof this.saveSuccessToast === 'string'
            ? this.saveSuccessToast
            : this.saveSuccessToast?.message;
        this.container.showToast?.({
            type: 'SUCCESS',
            biName: 'cairo-entity-page-save-success-toast',
            message: message ?? this.container.translate('cairo.entityPage.success.toast'),
        });
    }
    async handleSubmit(e) {
        if (this.formPage.submitTask.status.isLoading) {
            return;
        }
        this.events.emit('save');
        const { isValid, data: widgetsFormData } = await this.formPage.validate();
        if (!isValid) {
            this.bi.reportButtonClick({
                ctaName: 'Save',
                isValid: false,
                additionalInfo: this.actionsBarConfig?.saveCta?.biAdditionalInfo,
            });
            return;
        }
        const { form, formPage: { submitTask }, bi, } = this;
        submitTask.run(async () => {
            let savedEntity;
            let submitSuccessful = false;
            await form.handleSubmit(async () => {
                bi.reportButtonClick({
                    ctaName: 'Save',
                    isValid: true,
                    additionalInfo: this.actionsBarConfig?.saveCta?.biAdditionalInfo,
                });
                try {
                    if (!this.isFetching) {
                        const onSaveResult = await this.onSave({
                            widgetsFormData,
                        });
                        savedEntity = onSaveResult?.updatedEntity;
                    }
                    this._showSuccessToast();
                    submitSuccessful = true; // Mark as successful locally
                    // Explicitly set isSubmitSuccessful to prevent onBeforeUnload from triggering
                    this.isSubmitSuccessful = true;
                }
                catch (err) {
                    this._showErrorToast(err, e);
                    this.container.errorMonitor.captureException(err);
                    this.events.emit('saveError', err);
                    form.setError('root.serverError', {}); // https://react-hook-form.com/docs/useform/seterror
                }
            }, () => {
                bi.reportButtonClick({
                    ctaName: 'Save',
                    isValid: false,
                    additionalInfo: this.actionsBarConfig?.saveCta?.biAdditionalInfo,
                });
            })(e);
            if (!submitSuccessful) {
                return;
            }
            const transformedItem = savedEntity && this.transformEntityToCollectionItem
                ? this.transformEntityToCollectionItem(savedEntity)
                : savedEntity;
            this.navigateToParent(transformedItem);
        });
        await this.formPage.submitTask.status.promise;
    }
    get initTask() {
        return this.formPage.initTask;
    }
    get submitTask() {
        return this.formPage.submitTask;
    }
    _checkPageParams() {
        if (this._withinRouter) {
            if (this._parentPath === undefined) {
                throw new Error('parentPath was not defined in useEntityPage');
            }
        }
        else {
            if (this._parentPageId === undefined) {
                throw new Error('parentPageId was not defined in useEntityPage');
            }
            if (!this.container.navigateTo) {
                throw new Error('navigateTo was not defined in Patterns Provider');
            }
        }
    }
}
//# sourceMappingURL=EntityPageState.js.map