/**
 * @author 1902 Software
 * @copyright Copyright © 2023 1902 Software (https://1902software.com/magento/)
 * @package WriteTextAI_WriteTextAI
 */

define([
    'jquery',
    'ko',
    'uiComponent',
    'WriteTextAI_WriteTextAI/js/model/edit',
    'WriteTextAI_WriteTextAI/js/model/edit/feedback',
    'WriteTextAI_WriteTextAI/js/model/edit/attributes',
    'WriteTextAI_WriteTextAI/js/model/edit/additional-prompt',
    'WriteTextAI_WriteTextAI/js/model/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/mark-reviewed',
    'WriteTextAI_WriteTextAI/js/model/edit/product',
    'WriteTextAI_WriteTextAI/js/model/edit/audience',
    'WriteTextAI_WriteTextAI/js/model/edit/custom-tone-style',
    'WriteTextAI_WriteTextAI/js/model/edit/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/error-messages',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keywords',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-pipelines',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/grid/reload',
    'WriteTextAI_WriteTextAI/js/model/grid/notifications',
    'WriteTextAI_WriteTextAI/js/model/history-log',
    'WriteTextAI_WriteTextAI/js/utils/edit/gallery',
    'WriteTextAI_WriteTextAI/js/model/edit/review-status',
    'WriteTextAI_WriteTextAI/js/signalr',
    'WriteTextAI_WriteTextAI/js/grid/popups/progressbar',
    'WriteTextAI_WriteTextAI/js/model/grid/reference-products',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/triggers',
    'WriteTextAI_WriteTextAI/js/model/edit/select-template',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/currently-generating',
    'mage/backend/notification',
    'WriteTextAI_WriteTextAI/js/modal/modal',
    'Magento_Ui/js/modal/modal',
    'mage/calendar',
    'accordion'
], function (
    $,
    ko,
    Component,
    editData,
    feedback,
    attributes,
    additionalPrompt,
    textfields,
    markReviewed,
    product,
    audience,
    customToneStyle,
    settings,
    errorMessagesModel,
    genKeywordAnalysis,
    keywordsData,
    keywordPipelinesData,
    keywordAnalysisData,
    reloadGrid,
    notifications,
    historyLog,
    galleryUtils,
    reviewStatus,
    signalRComponent,
    progressbarComponent,
    gridReferenceProducts,
    triggers,
    selectTemplateModel,
    currentlyGeneratingModel,
    notification
) {
    'use strict';

    /**
     * @var {Component} self
     */
    var self;

    return Component.extend({
        defaults: {
            modalSelector: '',
            modal: null,
            accordionsInitialized: false,
            tooltipsInitialized: false,
            widgetsInitialized: false,
            ajaxRequests: 0,
            pageTitleAjaxRequests: 0,
            pageDescriptionAjaxRequests: 0,
            productDescriptionAjaxRequests: 0,
            shortDescriptionAjaxRequests: 0,
            openGraphAjaxRequests: 0,
            galleryAjaxRequests: 0,
            analysisAjaxRequests: 0,
            audienceAjaxRequests: 0,
            editPipelineAjaxRequests: 0,
            productId: '',
            storeId: '',
            isLoading: false,
            selectors: {
                mainModalSelector: '.wtai-edit-modal.wtai-edit-main',
                keywordsAnalysisModalSelector: '.wtai-edit-modal.wtai-edit-keyword-analysis',
                mainModalClass: 'wtai-edit-modal wtai-edit-main',
                accordionSelector: '.wtai-edit-modal-wrapper .wtai-accordions',
                tooltipSelector:
                    '.wtai-edit-modal-wrapper .admin__field-tooltip-action',
                reviewStatusPopupSelector: '.wtai-review_status-tooltip .tooltip-toggle',
                collapsibleSelector:
                    '.wtai-wtai-toolbar .wtai-custom-action-select-wrap',
                toggleSelectAllSelector:
                    '.wtai-wtai-toolbar input[name=select_all]',
                targetCheckboxSelector:
                    '.wtai-edit-modal-wrapper .wtai-fieldset.wtai-text-editor input[type=checkbox]'
            },
            statusRunning: 'Running',
            statuses: []
        },

        gettingData: null,
        isCurrentProductChange: false,

        /** @inheritdoc */
        initialize: function () {
            this._super();

            self = this;

            this.initModal();

            $(document).on({
                ajaxSend: this._onAjaxSend.bind(this),
                ajaxComplete: this._onAjaxComplete.bind(this),
                ajaxError: this._onAjaxError.bind(this)
            });

            this.storeId.subscribe(function (storeId) {
                if (!this.isCurrentProductChange) {
                    let currentProduct = editData.currentProduct();

                    currentProduct.storeId = storeId;
                    editData.currentProduct(currentProduct);
                    product.storeId(storeId);
                }
            }, this);

            this.productId.subscribe(function (productId) {
                if (!this.isCurrentProductChange) {
                    let currentProduct = editData.currentProduct();

                    currentProduct.productId = productId;
                    editData.currentProduct(currentProduct);
                    product.productId(productId);
                }
            }, this);

            editData.currentProduct.subscribe(function (currentProduct) {
                this.isCurrentProductChange = true;
                self.productId(currentProduct.productId);
                self.storeId(currentProduct.storeId);
                this.isCurrentProductChange = false;
                
                if (!$(self.selectors.mainModalSelector).hasClass('_show')) {
                    $(self.modalSelector).editModal('openModal');
                }
            });

            notifications.statuses.subscribe(function (statuses) {
                this.statuses(statuses);

                let productId = self.productId(),
                    disabled = statuses.some((status) => {
                        try {
                            let isQueued =
                                status.status === self.statusRunning &&
                                (status.queuedIds.indexOf(productId) !== -1 ||
                                    status.runningIds.indexOf(productId) !== -1);

                            return isQueued;
                        } catch (e) {
                            return false;
                        }
                    });

                if (disabled) {
                    self.showLoader();
                    self.showAllFieldLoaders();
                } else {
                    self.hideLoader();
                    self.hideAllFieldLoaders();
                }
            }, this);
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe([
                'productId',
                'storeId',
                'statuses',
                'isLoading'
            ]);

            this.isCurrentlyGenerating = ko.computed(function () {
                var identifier = 'Product' + '_' +  this.productId() + '_' + this.storeId();
                var recordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                if (recordIdentifiers.includes(identifier)) {
                    return true;
                }
                return false;
            }, this);

            return this;
        },

        /**
         * Initialize edit modal.
         */
        initModal: function () {
            var prev = 1,
                next = 1;

            this.modal = $(this.modalSelector).editModal({
                type: 'slide',
                title: 'WriteText.ai',
                modalClass: self.selectors.mainModalClass,
                overlayClass: 'modals-overlay wtai-edit-modal-overlay',
                innerScroll: true,
                buttons: [
                    {
                        class: 'wtai-link-preview action',
                        attr: {
                            title: $.mage.__('View')
                        },
                        click: function () {
                            self.linkPreview(this);
                        }
                }, {
                    class: 'wtai-history-log action',
                    attr: {
                        title: $.mage.__('History log')
                    },
                    click: function () {
                        self.openHistoryLog();
                    }
                }, {
                    text: $.mage.__('Previous'),
                    class: 'action-previous action-default',
                    attr: {
                        'data-prev': prev,
                        'data-bind': 'disable: 1'
                    },
                    click: function () {
                        self.showPrevious();
                    }
                }, {
                    text: $.mage.__('Next'),
                    class: 'action-next action-default',
                    attr: { 'data-next': next },
                    click: function () {
                        self.showNext();
                    }
                }
                ],
                opened: function () {
                    self.afterOpen();
                },
                closed: function () {
                    self.afterClose();
                }
            });

            $(self.selectors.mainModalSelector + ' .page-main-actions .page-actions-buttons')
                .append('<div class="wtai-edit-loading-mask wtai-show"></div>');
        },

        /**
         * Reload grid.
         */
        gridReload: function () {
            var showLoader = false;
            var debounce = true;

            reloadGrid.reloadUIComponent(
                'wtai_products_grid_listing.wtai_products_grid_listing_data_source',
                showLoader,
                debounce
            );
        },

        /**
         * Open preview.
         *
         * @param {Object} modal
         * @returns {void}
         */
        linkPreview: function (modal) {
            $.each(modal.buttons, function (index, button) {
                if ($(button).is('.wtai-link-preview')) {
                    let link = $(button).data('link');

                    window.open(link, '_blank');
                }
            });
        },

        /**
         * Open history log modal.
         */
        openHistoryLog: function () {
            $('.wtai-history-log-modal').modal('openModal');
        },

        /**
         * Show previous product.
         *
         * @returns {void}
         */
        showPrevious: function () {
            var prevProductId = this.getProductByIndex('prev');

            self.resetPage();

            if (prevProductId) {
                self.productId(prevProductId);
                self.getModalData();
            }
        },

        /**
         * Show next product.
         *
         * @returns {void}
         */
        showNext: function () {
            var nextProductId = this.getProductByIndex('next');

            self.resetPage();

            if (nextProductId) {
                self.productId(nextProductId);
                self.getModalData();
            }
        },

        /**
         * Disable generating product.
         *
         * @param {String} productId
         * @returns {void}
         */
        disableGeneratingProduct: function (productId) {
            var disabled = self.statuses().some((status) => {
                try {
                    let isQueued =
                        status.status === self.statusRunning &&
                        (status.queuedIds.indexOf(productId) !== -1 ||
                            status.runningIds.indexOf(productId) !== -1);

                    return isQueued;
                } catch (e) {
                    return false;
                }
            });

            if (disabled) {
                self.showLoader();
            } else {
                self.hideLoader();
            }
        },

        /**
         * After open edit modal actions.
         */
        afterOpen: function () {
            progressbarComponent.prototype.seeLess();
            $('.modal-content').trigger('contentUpdated');

            if (!this.widgetsInitialized) {
                this.initAccordion();
                this.initTooltip();
                editData.opened(true);
            }

            this.ajaxRequests = 0;
            this.pageTitleAjaxRequests = 0;
            this.pageDescriptionAjaxRequests = 0;
            this.productDescriptionAjaxRequests = 0;
            this.shortDescriptionAjaxRequests = 0;
            this.openGraphAjaxRequests = 0;
            this.galleryAjaxRequests = 0;
            this.analysisAjaxRequests = 0;
            this.audienceAjaxRequests = 0;
            this.editPipelineAjaxRequests = 0;
            this.getModalData();

            genKeywordAnalysis.views(0);

            editData.initialized(true);
        },

        /**
         * After closing edit modal actions.
         */
        afterClose: function () {
            $('.wtai-edit-modal-overlay').remove();
            editData.initialized(false); /** IMPORTANT: Make sure to call this first before resetPage for user preference*/
            self.resetPage();

            /** IMPORTANT: Make sure to call this first before gridReload as grid reload is disabled when edit page is open */
            editData.opened(false);
            self.gridReload();

            signalRComponent.prototype.hideMessage();
            self.showPreloader();
        },

        /**
         * Clear messages.
         */
        clearMessages: function () {
            $('body').notification('clear');
            $('body').find('div[data-role="messages"]').parent().remove();
        },

        /**
         * Get edit modal data.
         */
        getModalData: function () {
            var productId = self.productId();

            self.showPreloader();
            self.clearMessages();
            
            /** Placed here to remove optimization failed on edit close while keeping the grid progress */
            var statuses = keywordAnalysisData.statuses();
            keywordAnalysisData.statuses(statuses.filter(function (status) {
                return Number(status.storeId) !== Number(self.storeId()) || status.recordId !== self.productId();
            }));

            errorMessagesModel.messages([]);

            self.disableGeneratingProduct(productId);

            historyLog.update(false);

            if (self.gettingData !== null) {
                self.gettingData.abort();
            }

            self.gettingData = $.ajax({
                url: self.editUrl,
                dataType: 'json',
                data: {
                    form_key: window.FORM_KEY,
                    id: productId,
                    store_id: self.storeId()
                },
                showWriteTextAILoader: true,
                hideWriteTextTitleLoader: true,
                success: function (response) {
                    if (response.success) {
                        self.updateModal(response);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                    
                    self.hidePreloader();
                },
                error: function (xhr, status, error) {
                    if (status !== 'abort') {
                        errorMessagesModel.messages.push(error);
                    }
                }
            });
        },

        /**
         * Update edit modal data.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateModal: function (data) {
            $(self.selectors.mainModalSelector + ' .wtai-product-name').html(
                data.product_name
            );
            $(self.selectors.mainModalSelector + ' .wtai-sku').text(data.sku);

            /**
             * IMPORTANT: Update product first before texts
             */
            self.updateProduct(data);
            self.updateButtons(data);
            self.updateTextFields(data);
            self.updateTextfieldsStatuses(data);
            self.updateKeywordsUsed(data);
            self.updateUseDefault(data);
            self.updatePronouns(data);
            self.updateKeywordAnalysis(data); /** IMPORTANT: Make sure to update analysis first before keywords for checking of thumbnail */
            self.updateAttributes(data);
            self.updateHistoryLog(data);
            self.updateNewTextFields(data);
            self.updateMarkReviewed(data);
            self.updateAudience(data);
            self.updateCustomToneStyle(data);
            self.updateSelectedFields(data); /** IMPORTANT: Make sure to update selected fields first before keywords for checking of auto generate after KO */
            self.updateSettings(data);
            self.updateReviewStatus(data);
            self.updateFeedbacks(data);
            self.updateAdditionalPrompt(data);
            self.updateTemplatesUsed(data);
            self.bindStoreSwitcher();
            galleryUtils.updateImages(
                data.gallery,
                data.images
            );
            self.updateKeywords(data);

            $('.wtai-edit-modal-wrapper').trigger('contentUpdated');
        },

        /**
         * Bind store switcher.
         */
        bindStoreSwitcher: function () {
            $('.wtai-store-scope li a').on('click', function () {
                self.resetPage();
                self.storeId($(this).data('value'));
                self.getModalData();
                $('.wtai-store-scope .dropdown').collapsible(
                    'deactivate'
                );
            });
        },

        /**
         * Update keywords analysis.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateKeywordAnalysis: function (data) {
            keywordPipelinesData.forceResetEditPipeline(false); /** set to false first */
            keywordPipelinesData.forceResetEditPipeline(true);
            keywordPipelinesData.editKeywordRankingVisible(false);
            keywordPipelinesData.editKeywordRankingVisible.valueHasMutated();
            var optimizationData = data.optimization || {};
            keywordAnalysisData.optimizationData(optimizationData);
            keywordAnalysisData.snapshotData(optimizationData.snapshots || {});

            var isRefreshOngoing = optimizationData.refreshStatus === 'InProgress';
            keywordAnalysisData.refreshingData(isRefreshOngoing);

            triggers.defaultTriggers(data.global_triggers);
        },

        /**
         * Update feedbacks.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateFeedbacks: function (data) {
            feedback.feedbacks(data.feedback);
        },

        /**
         * Update review status.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateReviewStatus: function (data) {
            reviewStatus.reviewStatus(data.review_status);
        },

        /**
         * Update use default data.
         *
         * @param {*} data
         * @returns {void}
         */
        updateUseDefault: function (data) {
            textfields.useDefault({
                pageTitle: data.use_default.page_title,
                pageDescription: data.use_default.page_description,
                productDescription: data.use_default.product_description,
                productShortDescription: data.use_default.short_product_description,
                openGraph: data.use_default.open_graph
            });
        },

        /**
         * Update settings.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateSettings: function (data) {
            /**
             * IMPORTANT: Always updates styles first before tones
             * to prioritize in redering
             */
            settings.disallowedCombinations(data.disallowed_combinations);
            settings.styles(data.styles);
            settings.tones(data.tones);
            settings.audience(data.audience);
            settings.descMin(data.desc_min);
            settings.descMax(data.desc_max);
            settings.excMin(data.exc_min);
            settings.excMax(data.exc_max);
            settings.credits(data.credits);
            settings.formalLanguageSupport(data.formal_language_support);
            settings.formalLanguages(data.formal_languages);
            settings.guideSteps(data.guide_steps);
        },

        /**
         * Update custom tone and style.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateCustomToneStyle: function (data) {
            customToneStyle.customTone(data.custom_tone);
            customToneStyle.customStyle(data.custom_style);
        },
        
        /**
         * Update selected fields.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateSelectedFields: function (data) {
            textfields.selectedFields([]);
            for (let key in data.selected_fields) {
                if (data.selected_fields.hasOwnProperty(key)) {
                    textfields.selectedFields.push(data.selected_fields[key]);
                }
            }
        },

        /**
         * Update textfields statuses.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateTextfieldsStatuses: function (data) {
            textfields.statuses({
                pageTitleGenerateStatus: data.textfields_statuses.page_title_generated,
                pageDescriptionGenerateStatus: data.textfields_statuses.page_description_generated,
                productDescriptionGenerateStatus: data.textfields_statuses.product_description_generated,
                productShortDescriptionGenerateStatus: data.textfields_statuses.short_product_description_generated,
                openGraphGenerateStatus: data.textfields_statuses.open_graph_generated,
                pageTitleTransferStatus: data.textfields_statuses.page_title_transferred,
                pageDescriptionTransferStatus: data.textfields_statuses.page_description_transferred,
                productDescriptionTransferStatus: data.textfields_statuses.product_description_transferred,
                productShortDescriptionTransferStatus: data.textfields_statuses.short_product_description_transferred,
                openGraphTransferStatus: data.textfields_statuses.open_graph_transferred
            });
        },

        /**
         * Update keywords used.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateKeywordsUsed: function (data) {
            textfields.keywordsUsed({
                pageTitle: data.keywords_used.page_title,
                pageDescription: data.keywords_used.page_description,
                productDescription: data.keywords_used.product_description,
                shortProductDescription: data.keywords_used.short_product_description,
                openGraph: data.keywords_used.open_graph
            });
        },

        /**
         * Update templates used.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateTemplatesUsed: function (data) {
            selectTemplateModel.selectedTemplates.page_title(data.templates_used.page_title);
            selectTemplateModel.selectedTemplates.product_description(data.templates_used.product_description);
            selectTemplateModel.selectedTemplates.short_product_description(data.templates_used.short_product_description);
        },

        /**
         * Update audience.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateAudience: function (data) {
            audience.selectedAudience(data.selected_audience.shift());
            audience.suggestedAudience(data.suggested_audience);
        },

        /**
         * Update product.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateProduct: function (data) {
            product.productId(data.product_id);
            product.productName($($.parseHTML(data.product_name)).text());
            product.storeId(data.store_id);
            product.storeScope(data.store_scope);
            product.language(data.language.toLowerCase());
            product.stores(data.stores);
            product.directiveRegex(data.directiveRegex);
            product.descriptionDirectiveExists(
                data.product_description_directive_exists
            );
            product.shortDescriptionDirectiveExists(
                data.product_short_description_directive_exists
            );
            product.productUrl(data.link_preview_url);
        },

        /**
         * Update mark reviewed.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateMarkReviewed: function (data) {
            markReviewed.reviewed(data.reviewed);
        },

        /**
         * Update Magento texts.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateNewTextFields: function (data) {
            textfields.pageTitle(data.text_fields.page_title);
            textfields.pageDescription(data.text_fields.page_description);
            textfields.productDescription(data.text_fields.product_description);
            textfields.productShortDescription(
                data.text_fields.short_product_description
            );
            textfields.openGraph(data.text_fields.open_graph);
            textfields.originalPageTitle(data.text_fields.page_title);
            textfields.originalPageDescription(
                data.text_fields.page_description
            );
            textfields.originalProductDescription(
                data.text_fields.product_description
            );
            textfields.originalProductShortDescription(
                data.text_fields.short_product_description
            );
            textfields.originalOpenGraph(data.text_fields.open_graph);
        },

        /**
         * Update pronouns.
         *
         * @param {Object} data
         * @returns {void}
         */
        updatePronouns: function (data) {
            textfields.highlightPronouns(
                JSON.parse(data.highlight_pronouns.toLowerCase())
            );
        },

        /**
         * Update keywords.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateKeywords: function (data) {
            keywordsData.searchIntentSelected(data.search_intent_selected);
            keywordsData.language(data.language);
            keywordsData.country(data.country);
            keywordsData.location(data.location);
            keywordsData.selectedKeywords(data.selected_keywords);
            keywordsData.thumbnail(data.thumbnail);
            keywordsData.thumbnailId(data.thumbnail_id);
            keywordsData.apiThumbnail(data.api_thumbnail);
            keywordsData.autoGenerateRewriteAfterKo(data.auto_generate_after_ko);
        },

        /**
         * Update attributes.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateAttributes: function (data) {
            attributes.otherProductDetails(data.other_details);
            attributes.otherProductDetailsChecked(data.other_details_checked);
            attributes.productAttributes([]);
            for (let key in data.product_attributes) {
                if (data.product_attributes.hasOwnProperty(key)) {
                    attributes.productAttributes.push(
                        data.product_attributes[key]
                    );
                }
            }
            /**
             * IMPORTANT: Always update product attribute list first before the selected
             * to prioritize preference over global settings
             */
            attributes.productAttributesSelected(data.product_attributes_selected);
        },

        /**
         * Update additional prompt.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateAdditionalPrompt: function (data) {
            additionalPrompt.promptValue(data.additional_prompt);
        },

        /**
         * Update text fields.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateTextFields: function (data) {
            textfields.mgPageTitle(data.product_meta_title);
            textfields.mgProductDescription(data.product_description);
            textfields.mgProductShortDescription(
                data.product_short_description
            );
            textfields.mgPageDescription(data.product_meta_description);
            textfields.mgOpenGraph(data.open_graph);
        },

        /**
         * Update history log.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateHistoryLog: function (data) {
            historyLog.recordId(self.productId());
            historyLog.storeId(self.storeId());
            historyLog.users([]);

            for (let key in data.users) {
                if (data.users.hasOwnProperty(key)) {
                    historyLog.users.push(data.users[key]);
                }
            }
        },

        /**
         * Update buttons.
         *
         * @param {Object} data
         * @returns {void}
         */
        updateButtons: function (data) {
            /**
             * next
             */
            if (this.getProductByIndex('next')) {
                $(this.selectors.mainModalSelector + ' .action-next').prop(
                    'disabled',
                    false
                );
            } else {
                $(this.selectors.mainModalSelector + ' .action-next').prop(
                    'disabled',
                    true
                );
            }

            /**
             * prev
             */
            if (this.getProductByIndex('prev')) {
                $(this.selectors.mainModalSelector + ' .action-previous').prop(
                    'disabled',
                    false
                );
            } else {
                $(this.selectors.mainModalSelector + ' .action-previous').prop(
                    'disabled',
                    true
                );
            }

            /**
             * link preview
             */
            $(this.selectors.mainModalSelector + ' .wtai-link-preview').data(
                'link',
                data.link_preview_url
            );

            $(this.selectors.keywordsAnalysisModalSelector + ' .wtai-link-preview').data(
                'link',
                data.link_preview_url
            );

            /**
             * preview changes
             */
            $(this.selectors.mainModalSelector + ' .wtai-preview-button').data(
                'link',
                data.preview_changes_url
            );

            /**
             * Toggle preview visibility
             */
            if (data.visibility) {
                $(this.selectors.mainModalSelector + ' .wtai-link-preview').removeClass('wtai-no-display');
                $(this.selectors.mainModalSelector + ' .wtai-preview-button').removeClass('wtai-no-display');
                $(this.selectors.mainModalSelector + ' .wtai-preview-button + .wtai-tooltip-wrapper').removeClass('wtai-no-display');
            } else {
                $(this.selectors.mainModalSelector + ' .wtai-link-preview').addClass('wtai-no-display');
                $(this.selectors.mainModalSelector + ' .wtai-preview-button').addClass('wtai-no-display');
                $(this.selectors.mainModalSelector + ' .wtai-preview-button + .wtai-tooltip-wrapper').addClass('wtai-no-display');
            }
        },

        /**
         * Reset edit modal.
         */
        resetPage: function () {
            var data = {
                product_name: '',
                text_fields: {
                    page_title: '',
                    page_description: '',
                    product_description: '',
                    short_product_description: '',
                    open_graph: ''
                },
                product_meta_title: '',
                product_description: '',
                product_short_description: '',
                product_meta_description: '',
                open_graph: ''
            };

            $(self.selectors.mainModalSelector + ' .wtai-product-name').html('');
            $(self.selectors.mainModalSelector + ' .wtai-sku').html('');

            self.updateTextFields(data);
            self.updateNewTextFields(data);

            historyLog.recordId(null);
            historyLog.storeId(gridReferenceProducts.storeId());
            historyLog.update(false);
            markReviewed.reviewed(false);
            keywordsData.resetKeywordInput(true);
            keywordsData.resetKeywordInput.valueHasMutated(); /** force to update keyword error */
            product.storeScope('');
            keywordsData.showProgress(false);
        },

        /**
         * Initialize edit modal accordions.
         */
        initAccordion: function () {
            $(self.selectors.accordionSelector).each(function () {
                var active = [],
                    activeValues = {
                        'wtai-keywords-attributes': [0, 1],
                        'wtai-fieldset': [0, 1, 2, 3, 4],
                        'wtai-gallery': [0]
                },
                    elementClasses = $(this).attr('class').split(/\s+/);
                    
                $.each(elementClasses, function (index, className) {
                    if (activeValues.hasOwnProperty(className)) {
                        active = activeValues[className];
                    }
                });

                $(this).accordion({
                    active: active,
                    collapsible: true,
                    openedState: '_show',
                    closedState: '_hide',
                    multipleCollapsible: true
                });
            });
        },

        /**
         * Initialize edit modal tooltips.
         */
        initTooltip: function () {
            $(self.selectors.tooltipSelector).dropdown({
                parent: '.admin__field-tooltip',
                autoclose: true
            });
            $(self.selectors.reviewStatusPopupSelector).dropdown({
                parent: '.wtai-review_status-tooltip',
                autoclose: true
            });
        },

        /**
         * Get product by index.
         *
         * @param {String} type
         * @returns {Boolean|String}
         */
        getProductByIndex: function (type) {
            var ids = editData.ids(),
                currentIndex = ids.indexOf(self.productId());

            if (!ids || ids.length === 0) {
                return false;
            }

            let offset = (type === 'next') ? 1 : (type === 'prev') ? -1 : 0;
            let product = ids[currentIndex + offset];

            return product || false;
        },

        /**
         * Show preloader
         */
        showPreloader: function () {
            self.isLoading(true);
        },

        /**
         * Hide preloader
         */
        hidePreloader: function () {
            self.isLoading(false);
        },

        /**
         * Show field loader
         *
         * @param {String} field
         * @returns {void}
         */
        showFieldLoader: function (field) {
            $('.wtai-' + field + '-loading-mask').addClass('wtai-show');
        },

        /**
         * Hide field loader
         *
         * @param {String} field
         * @returns {void}
         */
        hideFieldLoader: function (field) {
            $('.wtai-' + field + '-loading-mask').removeClass('wtai-show');
        },

        /**
         * Show all field loaders
         */
        showAllFieldLoaders: function () {
            self.showFieldLoader('page-title');
            self.showFieldLoader('page-description');
            self.showFieldLoader('product-description');
            self.showFieldLoader('short-description');
            self.showFieldLoader('open-graph');
            self.showFieldLoader('gallery');
        },

        /**
         * Hide all field loaders
         */
        hideAllFieldLoaders: function () {
            self.hideFieldLoader('page-title');
            self.hideFieldLoader('page-description');
            self.hideFieldLoader('product-description');
            self.hideFieldLoader('short-description');
            self.hideFieldLoader('open-graph');
            self.hideFieldLoader('gallery');
        },

        /**
         * Show loader
         *
         * @param {Boolean} loadTitle
         * @returns {void}
         */
        showLoader: function (loadTitle = true) {
            $('.wtai-edit-loading-mask').addClass('wtai-show');
            if (loadTitle) {
                $('.wtai-edit-modal .modal-title').addClass('wtai-loading');
            }
        },

        /**
         * hide loader
         */
        hideLoader: function () {
            if (self.isCurrentlyGenerating()) {
                return;
            }
            $('.wtai-edit-modal .modal-title').removeClass('wtai-loading');
            $('.wtai-edit-loading-mask').removeClass('wtai-show');
        },

        /**
         * On ajax send.
         *
         * @param {Object} event
         * @param {Object} xhr
         * @param {Object} config
         *
         * @returns {void}
         */
        _onAjaxSend: function (event, xhr, config) {
            if (this.modal && config && config.showWriteTextAILoader) {
                this.showLoader(!config.hideWriteTextTitleLoader);
                this.ajaxRequests++;

                if (config.showPageTitleLoader) {
                    self.showFieldLoader('page-title');
                    this.pageTitleAjaxRequests++;
                }
                if (config.showPageDescriptionLoader) {
                    self.showFieldLoader('page-description');
                    this.pageDescriptionAjaxRequests++;
                }
                if (config.showProductDescriptionLoader) {
                    self.showFieldLoader('product-description');
                    this.productDescriptionAjaxRequests++;
                }
                if (config.showShortDescriptionLoader) {
                    self.showFieldLoader('short-description');
                    this.shortDescriptionAjaxRequests++;
                }
                if (config.showOpenGraphLoader) {
                    self.showFieldLoader('open-graph');
                    this.openGraphAjaxRequests++;
                }
                if (config.showGalleryLoader) {
                    self.showFieldLoader('gallery');
                    this.galleryAjaxRequests++;
                }
                if (config.showAnalysisLoader) {
                    self.showFieldLoader('analysis');
                    this.analysisAjaxRequests++;
                }
                if (config.showAudienceLoader) {
                    self.showFieldLoader('audience');
                    this.audienceAjaxRequests++;
                }
                if (config.showEditPipelineLoader) {
                    self.showFieldLoader('edit-pipeline');
                    this.editPipelineAjaxRequests++;
                }
            }
        },

        /**
         * On ajax complete.
         *
         * @param {Object} event
         * @param {Object} xhr
         * @param {Object} config
         *
         * @returns {void}
         */
        _onAjaxComplete: function (event, xhr, config) {
            this._handleAjaxCompletion(config);
        },

        /**
         * Handle AJAX request completion (shared logic for complete/error)
         *
         * @param {Object} config
         */
        _handleAjaxCompletion: function (config) {
            if (!this.modal || !config || !config.showWriteTextAILoader) {
                return;
            }

            /** Decrement main counter */
            if (this.ajaxRequests > 0) {
                this.ajaxRequests--;
            }

            setTimeout(function () {
                if (self.ajaxRequests === 0) {
                    self.hideLoader();
                }
            }, 200);

            /** Field-specific loaders configuration */
            var loaderConfigs = [
                {flag: 'showPageTitleLoader', counter: 'pageTitleAjaxRequests', field: 'page-title'},
                {flag: 'showPageDescriptionLoader', counter: 'pageDescriptionAjaxRequests', field: 'page-description'},
                {flag: 'showProductDescriptionLoader', counter: 'productDescriptionAjaxRequests', field: 'product-description'},
                {flag: 'showShortDescriptionLoader', counter: 'shortDescriptionAjaxRequests', field: 'short-description'},
                {flag: 'showOpenGraphLoader', counter: 'openGraphAjaxRequests', field: 'open-graph'},
                {flag: 'showGalleryLoader', counter: 'galleryAjaxRequests', field: 'gallery'},
                {flag: 'showAnalysisLoader', counter: 'analysisAjaxRequests', field: 'analysis'},
                {flag: 'showAudienceLoader', counter: 'audienceAjaxRequests', field: 'audience'},
                {flag: 'showEditPipelineLoader', counter: 'editPipelineAjaxRequests', field: 'edit-pipeline'}
            ];

            /** Process each loader configuration */
            loaderConfigs.forEach(function(loaderConfig) {
                if (config[loaderConfig.flag] && self[loaderConfig.counter] > 0) {
                    self[loaderConfig.counter]--;
                }
                if (config[loaderConfig.flag] && self[loaderConfig.counter] === 0) {
                    self.hideFieldLoader(loaderConfig.field);
                }
            });
        },

        /**
         * Handle AJAX errors (including aborted requests)
         *
         * @param {Object} event
         * @param {Object} xhr
         * @param {Object} config
         */
        _onAjaxError: function (event, xhr, config) {
            this._handleAjaxCompletion(config);
        }
    });
});
