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

define([
    'jquery',
    'ko',
    'uiComponent',
    'WriteTextAI_WriteTextAI/js/categories/model/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/product',
    'WriteTextAI_WriteTextAI/js/categories/model/signalr',
    'WriteTextAI_WriteTextAI/js/model/edit',
    'WriteTextAI_WriteTextAI/js/model/edit/feedback',
    'WriteTextAI_WriteTextAI/js/model/edit/mark-reviewed',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keywords',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/currently-generating',
    'WriteTextAI_WriteTextAI/js/categories/model/edit/invalid-image',
    'WriteTextAI_WriteTextAI/js/grid/reload',
    'WriteTextAI_WriteTextAI/js/model/edit/audience',
    'wtaiSignalR',
    'mage/translate'
], function (
    $,
    ko,
    Component,
    textfields,
    product,
    signalRModel,
    editData,
    feedbackData,
    markReviewed,
    keywordAnalysis,
    keywords,
    currentlyGeneratingModel,
    invalidImageModel,
    reloadGrid,
    audience,
    signalR,
    $t
) {
    'use strict';

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

    return Component.extend({
        defaults: {
            productId: '',
            storeId: '',
            connection: null,
            retryReconnectAttempt: 0,
            enableMaxRetryAttempt: false,
            maxRetryAttempt: 10,
            accessToken: '',
            signalRUrl: '',
            singleGenerate: 0,
            fieldStatus: 2,
            optimization: 4,
            snapshot: 5,
            openAnalysis: 6,
            bulkGenerate: 1,
            message: $t('Text generation completed'),
            showMessage: false,
            messageSuccess: false,
            successMessage: $t('Text generation completed'),
            pageTitle: '',
            pageDescription: '',
            categoryDescription: '',
            errorMessage: '',
            statusFailed: 'Failed',
            statusCompleted: 'Completed',
            
            /** SignalR Connection Status Constants */
            connectionStatusDisconnected: 'Disconnected',
            connectionStatusConnecting: 'Connecting',
            connectionStatusConnected: 'Connected',
            connectionStatusReconnecting: 'Reconnecting',
            connectionStatusFailed: 'Failed'
        },

        isGettingNewToken: false,
        gettingData: [],

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

            self = this;
            
            /** Initialize connection status in model */
            this.updateConnectionStatus(this.connectionStatusDisconnected, '', false, 'Not initialized');

            this.connectTostream();

            product.productId.subscribe(function (productId) {
                self.productId(productId);
            });

            product.storeId.subscribe(function (storeId) {
                self.storeId(storeId);
            });

            signalRModel.showMessage.subscribe(function (show) {
                self.showMessage(show);
            });

            signalRModel.message.subscribe(function (message) {
                self.message(message);
            });
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe([
                'productId',
                'storeId',
                'accessToken',
                'signalRUrl',
                'message',
                'showMessage',
                'messageSuccess',
                'errorMessage'
            ]);

            this.generateComplete = ko.computed(function () {
                var fieldsGenerated = signalRModel.fieldsGenerated(),
                    fieldsValues = Object.values(fieldsGenerated),
                    hasTrue = fieldsValues.includes(true),
                    hasFalse = fieldsValues.includes(false);

                var isGenerating = signalRModel.generating(),
                    isTextsGenerating = hasTrue || hasFalse,
                    isTextsGenerated = hasTrue && !hasFalse;

                if (isGenerating && isTextsGenerating && isTextsGenerated) {
                    return true;
                }

                return false;
            });

            this.generateComplete.subscribe(function (generateComplete) {
                if (generateComplete) {
                    self.catchFieldsError();
                    self.getGenerated();
                }
            });

            return this;
        },

        /**
         * Catch fields error.
         */
        catchFieldsError: function () {
            self.errorMessage('');
            self.messageSuccess(true);
            self.getNormalTextsError();
        },

        /**
         * Get normal texts error.
         */
        getNormalTextsError: function () {
            var errorFields = signalRModel.errorFields(),
                selectedFields = signalRModel.selectedFields(),
                htmlMessage = $t('Error encountered while generating the following text: %s')
                    .replace('%s', '<ul>' + errorFields.map(field => `<li>${field}</li>`).join('') + '</ul>');
                    
            htmlMessage += self.getImageFailedMessage();

            if (selectedFields.length > 0 && selectedFields.length === errorFields.length) {
                self.messageSuccess(false);
                if (signalRModel.errorMessage()) {
                    signalRModel.message(signalRModel.errorMessage());
                } else {
                    signalRModel.message(self.successMessage);
                    self.errorMessage(htmlMessage);
                }
            } else if (errorFields.length > 0) {
                signalRModel.message(self.successMessage);
                self.errorMessage(htmlMessage);
            } else {
                self.errorMessage(self.getImageFailedMessage());
            }
        },

        /**
         * Get image failed message.
         *
         * @returns {String}
         */
        getImageFailedMessage: function () {
            var subMessage = $t('Image analysis will be skipped for categories with invalid images and image descriptions may be missing.'),
                imagesHtml = $t('Error encountered while uploading some category images. %s %s')
                    .replace('%s', '<ul></ul>')
                    .replace('%s', '<span class="wtai-submessage">' + subMessage + '</span>');

            if (invalidImageModel.invalidImages().length > 0) {
                invalidImageModel.invalidImages().forEach(element => {
                    imagesHtml += '<img src="' + element + '">';
                });

                return imagesHtml;
            }
            return '';
        },

        /**
         * Hide text generation success message.
         */
        hideMessage: function () {
            signalRModel.showMessage(false);
        },

        /**
         * Connect to signalR stream.
         */
        connectTostream: function () {
            if (self.accessToken()) {
                /** Update connection status to Connecting */
                self.updateConnectionStatus(self.connectionStatusConnecting, '', false, null);
                
                self.connection = new signalR.HubConnectionBuilder()
                    .withUrl(self.signalRUrl(), {
                        accessTokenFactory: () => self.accessToken()
                    })
                    .build();
                self.connection
                    .start()
                    .then(() => self.onConnected(self.connection))
                    .catch((error) => self.onConnectionError(error));

                self.bindConnectionMessageGenerate(self.connection);

                $(window).on('focus', function () {
                    if (
                        self.connection != null &&
                        self.connection.connectionState != "Connected" &&
                        self.connection.connectionState != "Connecting"
                    ) {
                        self.updateConnectionStatus(self.connectionStatusReconnecting, self.connection.connectionState, false, null);
                        self.connection.start();
                    }
                });
            } else {
                self.updateConnectionStatus(self.connectionStatusDisconnected, '', false, 'No access token available');
            }
        },

        /**
         * Connection is established actions.
         *
         * @param {object} connection
         * @returns {void}
         */
        onConnected: function (connection) {
            /** Update connection status to Connected */
            self.updateConnectionStatus(self.connectionStatusConnected, connection.connectionState, true, null);
            /** Reset retry attempts on successful connection */
            self.retryReconnectAttempt = 0;
            signalRModel.retryAttempts(0);

            connection.send('broadcastMessage', '_SYSTEM_', 'Connected');
        },

        /**
         * Connection error actions.
         *
         * @param {object} error
         * @returns {void}
         */
        onConnectionError: function (error) {
            var doConnect = true;
            var errorMessage = error && error.message ? error.message : 'Connection error';
            
            /** Update connection status to Disconnected with error */
            self.updateConnectionStatus(self.connectionStatusDisconnected, '', false, errorMessage);

            if (error.statusCode === 401 && !self.isGettingNewToken) {
                self.getNewAccessToken();
            }

            if (self.enableMaxRetryAttempt && self.retryReconnectAttempt >= self.maxRetryAttempt) {
                doConnect = false;
                self.updateConnectionStatus(self.connectionStatusFailed, '', false, 'Max retry attempts reached');
            }

            if (doConnect) {
                /** Update retry attempts in model */
                signalRModel.retryAttempts(self.retryReconnectAttempt);
                
                if (self.retryReconnectAttempt === 0) {
                    self.connectTostream();
                } else {
                    self.updateConnectionStatus(self.connectionStatusReconnecting, '', false, 'Retrying connection in 5 seconds...');
                    setTimeout(function () {
                        self.connectTostream(); /** attempt to connect every 5 seconds */
                    }, 5000);
                }

                self.retryReconnectAttempt++;
            }
        },

        /**
         * Get new access token.
         */
        getNewAccessToken: function () {
            var url = self.getNewAccessTokenUrl;
        
            self.isGettingNewToken = true;
            $.ajax({
                url: url,
                type: 'GET',
                dataType: 'json',
                showLoader: false,
                success: function (response) {
                    if (response.success) {
                        self.accessToken(response.access_token);
                    }
                }
            }).always(function () {
                self.isGettingNewToken = false;
            });
        },

        /**
         * Update connection status in model.
         *
         * @param {String} status
         * @param {String} state
         * @param {Boolean} connected
         * @param {String} error
         * @returns {void}
         */
        updateConnectionStatus: function (status, state, connected, error) {
            signalRModel.connectionStatus(status);
            signalRModel.connectionState(state || '');
            signalRModel.isConnected(connected);
            signalRModel.connectionError(error || '');
            
            if (connected) {
                signalRModel.lastConnectionTime(new Date().toISOString());
            }
            
            console.log('Categories SignalR Connection Status Updated:', {
                status: status,
                state: state,
                connected: connected,
                error: error,
                retryAttempts: signalRModel.retryAttempts()
            });
        },

        /**
         * Bind connection messages.
         *
         * @param {Object} connection
         * @returns {void}
         */
        bindConnectionMessageGenerate: function (connection) {
            if (connection === null) {
                /* bypass */
            }

            connection.on('broadcastMessage', self.messageCallback);
            connection.onclose(self.onConnectionError);
            
            /** Monitor connection state changes */
            if (connection.onreconnecting) {
                connection.onreconnecting((error) => {
                    self.updateConnectionStatus(self.connectionStatusReconnecting, connection.connectionState, false, error ? error.message : null);
                });
            }
            
            if (connection.onreconnected) {
                connection.onreconnected((connectionId) => {
                    self.updateConnectionStatus(self.connectionStatusConnected, connection.connectionState, true, null);
                    console.log('Categories SignalR reconnected with connection ID:', connectionId);
                });
            }
        },

        /**
         * Parse message.
         *
         * @param {String} encodedName
         * @param {String} encodedMsg
         *
         * @returns {Object}
         */
        createMessageEntry: function (encodedName, encodedMsg) {
            return {
                encodedName: encodedName,
                encodedMsg: JSON.parse(encodedMsg)
            };
        },

        /**
         * Update text fields.
         *
         * @param {String} field
         * @param {String} value
         *
         * @returns {void}
         */
        updateField: function (field, value) {
            switch (field) {
                case self.pageTitle:
                    textfields.pageTitle(value);
                    break;
                case self.pageDescription:
                    textfields.pageDescription(value);
                    break;
                case self.categoryDescription:
                    /** textfields.categoryDescription(value); */
                    break;
            }
        },

        /**
         * Get text field value.
         *
         * @param {String} field
         * @returns {String}
         */
        getField: function (field) {
            var value = '';

            switch (field) {
                case self.pageTitle:
                    value = textfields.pageTitle();
                    break;
                case self.pageDescription:
                    value = textfields.pageDescription();
                    break;
                case self.categoryDescription:
                    value = textfields.categoryDescription();
                    break;
            }

            return value;
        },

        /**
         * Get index field.
         *
         * @param {String} field
         * @returns {String}
         */
        getIndexField: function (field) {
            var value = '';

            switch (field) {
                case self.pageTitle:
                    value = 'page_title';
                    break;
                case self.pageDescription:
                    value = 'page_description';
                    break;
                case self.categoryDescription:
                    value = 'category_description';
                    break;
            }

            return value;
        },

        /**
         * Process stream message.
         *
         * @param {String} name
         * @param {String} message
         *
         * @returns {void}
         */
        messageCallback: function (name, message) {
            var encodedName = name,
                encodedMsg = message
                    .replace(/&/g, '&amp;')
                    .replace(/</g, '&lt;')
                    .replace(/>/g, '&gt;'),
                messageEntry = self.createMessageEntry(encodedName, encodedMsg),
                streamRecordType = messageEntry.encodedMsg.recordType,
                streamType = messageEntry.encodedMsg.type,
                streamFieldType = messageEntry.encodedMsg.field,
                streamStop = messageEntry.encodedMsg.stop,
                streamPartialText = messageEntry.encodedMsg.partialText,
                streamRecordId = messageEntry.encodedMsg.recordId,
                streamStoreId = Number(messageEntry.encodedMsg.storeId),
                streamIndex = messageEntry.encodedMsg.index,
                generationType = messageEntry.encodedMsg.generationType,
                indexField = '',
                streamStatus = messageEntry.encodedMsg.status,
                fieldsGenerated = {},
                streamSubType = messageEntry.encodedMsg.subType,
                productId = self.productId(),
                storeId = Number(self.storeId()),
                entityType = self.entityType;

            console.log(messageEntry.encodedMsg);
            
            switch (streamType) {
                case self.bulkGenerate:
                    if (streamRecordType === 'Product') {
                        break;
                    }
                    switch (streamSubType) {
                        case 0:
                        case 1:
                             /** remove identifier from currently generating record identifiers if status is failed */
                            var identifier = entityType + '_' +  streamRecordId + '_' + streamStoreId;
                            var currentlyGeneratingRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                            if (currentlyGeneratingRecordIdentifiers.includes(identifier) && streamStatus === self.statusFailed) {
                                currentlyGeneratingRecordIdentifiers.splice(currentlyGeneratingRecordIdentifiers.indexOf(identifier), 1);
                                currentlyGeneratingModel.recordIdentifiers(currentlyGeneratingRecordIdentifiers);
                            }

                             /** Suppress bulk generate progress bar if keyword analysis is ongoing */
                            if (messageEntry.encodedMsg.id.includes('KeywordOptimization') || (
                                messageEntry.encodedMsg.total === 1
                            )) {
                                var queuedIds = messageEntry.encodedMsg.queuedIds;
                                queuedIds.forEach((id) => {
                                    var identifier = entityType + '_' +  id + '_' + streamStoreId;
                                    var currentlyGeneratingRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                                    if (!currentlyGeneratingRecordIdentifiers.includes(identifier) && streamStatus !== self.statusFailed) {
                                        currentlyGeneratingRecordIdentifiers.push(identifier);
                                        currentlyGeneratingModel.recordIdentifiers(currentlyGeneratingRecordIdentifiers);
                                    }
                                });

                                if (messageEntry.encodedMsg.status === 'Failed' || messageEntry.encodedMsg.status === 'Completed'
                                    || messageEntry.encodedMsg.status === 'Cancelled' || messageEntry.encodedMsg.status === 'TimedOut'
                                ) {
                                    var completedId = messageEntry.encodedMsg.completedIds;
                                    completedId.forEach((id) => {
                                        var identifier = entityType + '_' +  id + '_' + messageEntry.encodedMsg.storeId;
                                        var currentlyGeneratingRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                                        if (currentlyGeneratingRecordIdentifiers.includes(identifier)) {
                                            currentlyGeneratingRecordIdentifiers.splice(currentlyGeneratingRecordIdentifiers.indexOf(identifier), 1);
                                            currentlyGeneratingModel.recordIdentifiers(currentlyGeneratingRecordIdentifiers);
                                        }
                                    });
                                }
                            }

                            if (messageEntry.encodedMsg.status === 'Cancelled'
                                || messageEntry.encodedMsg.status === 'Completed'
                                || messageEntry.encodedMsg.status === 'Failed'
                            ) {
                                signalrUtils.getCredits(self);
                            }
                    }
                case self.fieldStatus:
                    if (signalRModel.generating() === true) {
                        if (streamStatus === self.statusFailed) {
                            signalRModel.errorFields.push(streamFieldType);
                            signalRModel.errorMessage(messageEntry.encodedMsg.error);
                        }
                    }

                    if (productId === streamRecordId && storeId === streamStoreId) {
                        indexField = self.getIndexField(streamFieldType);
        
                        fieldsGenerated = signalRModel.fieldsGenerated();
                        fieldsGenerated[indexField] = true;
                        signalRModel.fieldsGenerated(fieldsGenerated);
                        var statuses = textfields.statuses();
                        switch (indexField) {
                            case 'page_title':
                                $('.wtai-page-title-loading-mask').removeClass('wtai-show');
                                statuses['pageTitleGenerateStatus'] = true;
                                break;
                            case 'page_description':
                                $('.wtai-page-description-loading-mask').removeClass('wtai-show');
                                statuses['pageDescriptionGenerateStatus'] = true;
                                break;
                            case 'category_description':
                                $('.wtai-category-description-loading-mask').removeClass('wtai-show');
                                statuses['categoryDescriptionGenerateStatus'] = true;
                                break;
                        }
                        textfields.statuses(statuses);
                    }
                    break;
                case self.singleGenerate:
                    /** remove identifier from currently generating record identifiers if status is failed */
                    var identifier = entityType + '_' +  streamRecordId + '_' + streamStoreId;
                    var currentlyGeneratingRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                    if (currentlyGeneratingRecordIdentifiers.includes(identifier) && streamStatus === self.statusFailed) {
                        currentlyGeneratingRecordIdentifiers.splice(currentlyGeneratingRecordIdentifiers.indexOf(identifier), 1);
                        currentlyGeneratingModel.recordIdentifiers(currentlyGeneratingRecordIdentifiers);
                    }
                    
                    var existingIndex = signalRModel.singleGeneratingStatuses().findIndex(function (status) {
                        return status.recordId === messageEntry.encodedMsg.recordId &&
                               Number(status.storeId) === Number(messageEntry.encodedMsg.storeId) &&
                               status.generationType === messageEntry.encodedMsg.generationType &&
                               status.field === messageEntry.encodedMsg.field;
                    });
                    if (existingIndex > -1) {
                        signalRModel.singleGeneratingStatuses.splice(existingIndex, 1, messageEntry.encodedMsg);
                    } else {
                        signalRModel.singleGeneratingStatuses.push(messageEntry.encodedMsg);
                    }

                    if (signalRModel.generating() === true) {
                        
                        /** add identifier to currently generating record identifiers if status is not failed */
                        var currentRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                        var identifier = self.entityType + '_' + streamRecordId + '_' + streamStoreId;
                        if (!currentRecordIdentifiers.includes(identifier) && streamStatus !== self.statusFailed) {
                            currentRecordIdentifiers.push(identifier);
                            currentlyGeneratingModel.recordIdentifiers(currentRecordIdentifiers);
                        }
                    }

                    if (productId === streamRecordId && storeId === streamStoreId) {
                        indexField = self.getIndexField(streamFieldType);
                        /* eslint-disable max-depth */
    
                        if (streamIndex === signalRModel.index()[indexField]) {
                            self.processSingleGenerate(
                                streamFieldType,
                                streamStop,
                                streamPartialText,
                                streamIndex
                            );
                            streamIndex += 1;
                            signalRModel.index()[indexField] = streamIndex;
    
                            while (
                                typeof signalRModel.messages()[indexField][
                                    streamIndex
                                ] !== 'undefined'
                            ) {
                                self.processSingleGenerate(
                                    signalRModel.messages()[indexField][streamIndex]
                                        .encodedMsg.field,
                                    signalRModel.messages()[indexField][streamIndex]
                                        .encodedMsg.stop,
                                    signalRModel.messages()[indexField][streamIndex]
                                        .encodedMsg.partialText,
                                    signalRModel.messages()[indexField][streamIndex]
                                        .encodedMsg.index
                                );
                                streamIndex += 1;
                                signalRModel.index()[indexField] = streamIndex;
                            }
                        } else {
                            signalRModel.messages()[indexField][streamIndex] =
                                messageEntry;
                        }
    
                        if (streamStop === true) {
                            /* generate end */
                            signalRModel.index()[indexField] = 0;
                            signalRModel.messages()[indexField] = {};
                            if (signalRModel.generating() === false) {
                                self.repopulateTextFields();
                            }
                        }
                        /* eslint-enable max-depth */
                    }
                    break;
                case self.optimization:
                    if (streamRecordType === 'Product') {
                        break;
                    }
                    var statuses = keywordAnalysis.statuses(),
                        storeId = Number(messageEntry.encodedMsg.storeId),
                        recordId = messageEntry.encodedMsg.recordId,
                        existingIndex = -1;

                    statuses.forEach(function (status, index) {
                        if (Number(status.storeId) === Number(storeId) && status.recordId === recordId) {
                            existingIndex = index;
                        }
                    });

                    if (existingIndex >= 0) {
                        statuses[existingIndex] = messageEntry.encodedMsg;
                    } else {
                        statuses.push(messageEntry.encodedMsg);
                    }

                    keywordAnalysis.statuses(statuses);

                    if (messageEntry.encodedMsg.status === 'Failed'
                        && self.productId() === streamRecordId && storeId === streamStoreId
                    ) {
                        if (signalRModel.generating() === true) {
                            self.repopulateTextFields();
                        }
                        /** reset optimizing id if optimization failed
                         * This will allow the generation progress bar to continue even if optimization failed
                        */
                        keywordAnalysis.optimizingId("");
                    }
                    break;
                case self.snapshot:
                    if (productId === streamRecordId && storeId === streamStoreId) {
                        keywordAnalysis.refreshingData(true);
                        if (streamStatus === self.statusCompleted) {
                            keywordAnalysis.refreshingData(false);
                            self.getOptimization();
                            self.gridReload();
                        }
                    }
                    break;
                case self.openAnalysis:
                    /** $('.wtai-keyword-analysis').modal('openModal'); */
                    break;
            }
        },

        /**
         * Process single generate.
         *
         * @param {String} streamFieldType
         * @param {Boolean} streamStop
         * @param {String} streamPartialText
         * @param {Number} streamIndex
         *
         * @returns {void}
         */
        processSingleGenerate: function (
            streamFieldType,
            streamStop,
            streamPartialText,
            streamIndex
        ) {
            var currentValue = self.getField(streamFieldType),
                newValue = currentValue + streamPartialText;

            /* generate starts */
            if (streamIndex === 0) {
                self.updateField(streamFieldType, streamPartialText);
            }

            /* generate partial */
            if (
                streamPartialText !== null &&
                streamIndex !== null &&
                streamIndex !== 0 &&
                streamStop === false
            ) {
                self.updateField(streamFieldType, newValue);
            }
        },

        /**
         * Get generated text fields.
         */
        getGenerated: function () {
            var url = self.getGeneratedUrl,
                statuses = textfields.statuses(),
                productId = self.productId(),
                storeId = self.storeId(),
                selectedFields = signalRModel.selectedFields() || [],
                entityType = self.entityType;

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    category_id: productId,
                    store_id: storeId
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showPageTitleLoader: selectedFields.includes('page_title'),
                showPageDescriptionLoader: selectedFields.includes('page_description'),
                showCategoryDescriptionLoader: selectedFields.includes('category_description'),
                success: function (response) {
                    if (response.success) {
                        self.updateTextFields(response, selectedFields);

                        if (editData.opened()) {
                            signalRModel.showMessage(true);
                            self.showMessage(true);
                        }
                        signalRModel.generating(false);
                        
                        /** remove identifier from currently generating record identifiers if done generating */
                        var currentRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                        var identifier = self.entityType + '_' +  productId + '_' + storeId;
                        if (currentRecordIdentifiers.includes(identifier)) {
                            currentRecordIdentifiers.splice(currentRecordIdentifiers.indexOf(identifier), 1);
                            currentlyGeneratingModel.recordIdentifiers(currentRecordIdentifiers);
                        }


                        if (typeof response.feedback !== 'undefined') {
                            feedbackData.feedbacks(response.feedback);
                        }

                        if (typeof response.reviewed !== 'undefined') {
                            markReviewed.reviewed(response.reviewed);
                        }
                    } else {
                        console.log(response.message);
                    }

                    if (keywordAnalysis.autoGenerateOrRewriteChecked() &&
                        keywordAnalysis.optimizingId() === self.productId() &&
                        keywordAnalysis.optimizingStoreId() === self.storeId()
                    ) {
                        if ($('.wtai-edit-modal.wtai-edit-main').hasClass('_show')) {
                            keywords.showProgress(false);
                            self.getOptimization();
                        }
                        keywordAnalysis.autoGenerateOrRewriteChecked(false);
                    }
                }
            });
        },

        /**
         * Repopulate text fields.
         */
        repopulateTextFields: function () {
            var defaultSelectedFields = signalRModel.selectedFields();
            var url = self.getGeneratedUrl,
                statuses = textfields.statuses(),
                productId = self.productId(),
                storeId = self.storeId(),
                
                selectedFields = [
                    'page_title',
                    'page_description',
                    'category_description'
                ];

            if (self.gettingData['repopulateTextFieldsCategory'] !== undefined ||
                self.gettingData['repopulateTextFieldsCategory']) {
                self.gettingData['repopulateTextFieldsCategory'].abort();
            }

            self.gettingData['repopulateTextFieldsCategory'] = $.ajax({
                url: url,
                type: 'POST',
                data: {
                    category_id: productId,
                    store_id: storeId
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showPageTitleLoader: selectedFields.includes('page_title'),
                showPageDescriptionLoader: selectedFields.includes('page_description'),
                showCategoryDescriptionLoader: selectedFields.includes('category_description'),
                success: function (response) {
                    if (response.success) {
                        self.updateTextFields(response, selectedFields);
                        signalRModel.generating(false);
                        
                        /** remove identifier from currently generating record identifiers if failed */
                        var currentRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                        var identifier = self.entityType + '_' + productId + '_' + storeId;
                        if (currentRecordIdentifiers.includes(identifier)) {
                            currentRecordIdentifiers.splice(currentRecordIdentifiers.indexOf(identifier), 1);
                            currentlyGeneratingModel.recordIdentifiers(currentRecordIdentifiers);
                        }

                        if (typeof response.feedback !== 'undefined') {
                            feedbackData.feedbacks(response.feedback);
                        }
                    } else {
                        console.log(response.message);
                    }
                },
                error: function (xhr, status, error) {
                    if (status !== 'abort') {
                        console.log(error);
                    }
                }
            });
        },

        /**
         * Update text fields.
         *
         * @param {Object} response
         * @param {Array} selectedFields
         *
         * @returns {void}
         */
        updateTextFields: function (response, selectedFields) {
            var statuses = textfields.statuses();
            selectedFields.forEach((field) => {
                switch (field) {
                    case 'page_title':
                        if (response.generated_texts.page_title !== undefined) {
                            textfields.pageTitle(response.generated_texts.page_title);
                            textfields.originalPageTitle(response.generated_texts.page_title);
                            statuses['pageTitleGenerateStatus'] = true;
                            statuses['pageTitleTransferStatus'] = false;
                            $('#wtaiPageTitleMask').removeClass('wtai-generated');
                            $('#wtaiPageTitleMask').addClass('wtai-generated');
                        }
                        break;
                    case 'page_description':
                        if (response.generated_texts.page_description !== undefined) {
                            textfields.pageDescription(response.generated_texts.page_description);
                            textfields.originalPageDescription(response.generated_texts.page_description);
                            statuses['pageDescriptionGenerateStatus'] = true;
                            statuses['pageDescriptionTransferStatus'] = false;
                            $('#wtaiPageDescMask').removeClass('wtai-generated');
                            $('#wtaiPageDescMask').addClass('wtai-generated');
                        }
                        break;
                    case 'category_description':
                        if (response.generated_texts.category_description !== undefined) {
                            textfields.categoryDescription(response.generated_texts.category_description);
                            textfields.originalCategoryDescription(response.generated_texts.category_description);
                            statuses['categoryDescriptionGenerateStatus'] = true;
                            statuses['categoryDescriptionTransferStatus'] = false;
                            $('#wtaiCategoryDescMask + .mce-tinymce').removeClass('wtai-generated');
                            $('#wtaiCategoryDescMask + .mce-tinymce').addClass('wtai-generated');
                            $('#wtaiCategoryDescMask + .tox-tinymce').removeClass('wtai-generated');
                            $('#wtaiCategoryDescMask + .tox-tinymce').addClass('wtai-generated');
                        }
                        break;
                }
                textfields.statuses(statuses);
            });
        },

        /**
         * Get optimization.
         *
         * @returns {void}
         */
        getOptimization: function (openModal = false) {
            $.ajax({
                url: self.getOptimizationUrl,
                type: 'POST',
                data: {
                    store_id : self.storeId(),
                    record_id: self.productId(),
                    entity_type: self.entityType
                },
                dataType: 'json',
                showLoader: false,
                success: function (response) {
                    keywordAnalysis.optimizing(false);
                    keywordAnalysis.optimized(true);
                    keywordAnalysis.optimizationData(response.api_response);
                    keywordAnalysis.snapshotData(response.api_response.snapshots || {});
                    if (response.api_response.optimizingKeywords && response.api_response.optimizingKeywords.length > 0) {
                        self.getAudience(
                            response.api_response.optimizingKeywords, 
                            response.api_response.name
                        );
                    }

                    if (openModal && keywordAnalysis.optimizationData() && keywordAnalysis.optimizationData().status === 'Completed') {
                        $('.wtai-keyword-analysis').modal('openModal');
                    }
                }
            }).always(function () {
                keywords.showProgress(false);
            });
        },

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

            reloadGrid.reloadUIComponent(
                'wtai_categories_grid_listing.wtai_categories_grid_listing_data_source',
                showLoader,
                debounce
            );
        },

        /**
         * Regenerate suggested audience.
         * 
         * @param {Array} keywords
         * @param {String} categoryName
         */
        getAudience: function (keywords, categoryName) {
            var url = self.audienceGetUrl,
                storeId = self.storeId(),
                categoryId = self.productId();

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    category_id: categoryId,
                    store_id: storeId,
                    keywords: keywords,
                    category_name: categoryName
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showAudienceLoader: true,
                success: function (response) {
                    if (response.success) {
                        audience.selectedAudience(response.selected.shift());
                        audience.suggestedAudience(response.values);
                    }
                }
            });
        },
    });
});
