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

define([
    'jquery',
    'underscore',
    'ko',
    'uiComponent',
    'WriteTextAI_WriteTextAI/js/model/edit/product',
    'WriteTextAI_WriteTextAI/js/categories/model/edit',
    'WriteTextAI_WriteTextAI/js/categories/model/signalr',
    'WriteTextAI_WriteTextAI/js/categories/model/edit/category',
    'WriteTextAI_WriteTextAI/js/categories/model/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/additional-prompt',
    'WriteTextAI_WriteTextAI/js/utils/edit/toolbar',
    'WriteTextAI_WriteTextAI/js/utils/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/audience',
    'WriteTextAI_WriteTextAI/js/model/total-credits',
    'WriteTextAI_WriteTextAI/js/model/edit/custom-tone-style',
    'WriteTextAI_WriteTextAI/js/model/edit/error-messages',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keywords',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/preferences',
    'mage/translate',
    'accordion'
], function (
    $,
    _,
    ko,
    Component,
    product,
    editData,
    categoriesSignalRModel,
    category,
    textfields,
    additionalPrompt,
    toolbarUtils,
    textfieldsUtils,
    settings,
    audience,
    totalCredits,
    customToneStyle,
    errorMessagesModel,
    keywordsData,
    keywordAnalysisData,
    preferences,
    $t
) {
    'use strict';

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

    return Component.extend({
        defaults: {
            toggleSelectAllSelector: 'input[name=select_all]',
            accordionSelector: '.wtai-edit-modal-wrapper .wtai-accordions',
            accordionToggleSelector: '.wtai-wtai-toolbar .wtai-toggle-accordion',
            accordionTargetSelector: '.wtai-fieldset.wtai-text-editor',
            accordionKeywordAttributesSelector: '.wtai-keywords-attributes',
            tonesSelected: [],
            stylesSelected: '',
            suggestedAudience: [],
            selectedAudience: '',
            audienceSelected: [],
            additionalPrompt: '',
            selectAllTonesValue: null,
            selectAllAudienceValue: null,
            customTone: '',
            customStyle: '',
            guideSteps: false,
            defaultTones: [],
            defaultStyle: '',
            highlightPronouns: false,
            entityType: 'category',
            useAiModel: false,
            selectedAiModel: '',
            hasAiModels: false,
            genToneStyleMode: 'manual'
        },

        isTonesSelectedChanged: false,
        widgetsInitialized: false,
        accordionExpanded: true,
        canUpdateTones: true,
        canUpdateAudience: true,
        isAudienceChange: false,
        isHighlightPronounsChange: false,
        isGenToneStyleModeChange: false,
        typingTimer: null,
        getAudienceRequest: null,
        isGenerateAllowed: false,

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

            self = this;
            this.isViewerUser = ko.pureComputed(function () {
                return !self.isGenerateAllowed;
            });

            this.isProcessRunning = ko.pureComputed(function () {
                return Boolean(
                    (categoriesSignalRModel.generating && categoriesSignalRModel.generating()) ||
                    (keywordAnalysisData.optimizing && keywordAnalysisData.optimizing()) ||
                    (keywordAnalysisData.isUploading && keywordAnalysisData.isUploading()) ||
                    (keywordAnalysisData.refreshingData && keywordAnalysisData.refreshingData())
                );
            });

            if (settings.genToneStyleMode) {
                self.isGenToneStyleModeChange = true;
                self.genToneStyleMode(settings.genToneStyleMode());
                self.isGenToneStyleModeChange = false;
            }

            if (self.hasAiModels === false) {
                self.isGenToneStyleModeChange = true;
                self.genToneStyleMode('manual');
                self.useAiModel(false);
                self.selectedAiModel('');
                if (settings.genToneStyleMode) {
                    settings.genToneStyleMode('manual');
                }
                if (settings.useAiModel) {
                    settings.useAiModel(false);
                }
                if (settings.selectedAiModel) {
                    settings.selectedAiModel('');
                }
                self.isGenToneStyleModeChange = false;
            }

            this.tonesSelected.subscribe(
                function (changes) {
                    if (!self.isTonesSelectedChanged) {
                        self.isTonesSelectedChanged = true;

                        _.each(changes, function (change) {
                            if (change.status === 'added'
                                && change.value === 'custom'
                            ) {
                                self.tonesSelected.remove(self.isNotCustom);
                                self.selectAllTonesValue(false);
                            }
                            if (change.status === 'added'
                                && change.value !== 'custom'
                            ) {
                                self.tonesSelected.remove('custom');
                                self.customTone('');
                            }
                        }, self);

                        if (self.canUpdateTones) {
                            self.observeTonesSelected();
                        }

                        textfields.formal(
                            self.tonesSelected().indexOf('Formal') !== -1
                        );

                        self.isTonesSelectedChanged = false;
                    }
                    
                    preferences.tonesSelected(self.tonesSelected());
                },
                this,
                'arrayChange'
            );

            this.stylesSelected.subscribe(function (style) {
                if (style !== 'custom') {
                    this.customStyle('');
                }
                preferences.stylesSelected(style);
            }, this);

            preferences.tonesSelected.subscribe(function (tones) {
                if (self.isTonesSelectedChanged) {
                    return;
                }

                if (Array.isArray(tones)) {
                    self.isTonesSelectedChanged = true;
                    self.tonesSelected(tones);
                    self.isTonesSelectedChanged = false;
                }
            });

            preferences.stylesSelected.subscribe(function (style) {
                if (style !== undefined && style !== null) {
                    self.stylesSelected(style);
                }
            });

            this.audienceSelected.subscribe(function (audienceSelected) {
                if (!self.isGenerateAllowed) {
                    return;
                }
                if (this.canUpdateAudience) {
                    this.observeAudienceSelected();
                }
                preferences.audienceSelected(audienceSelected);
                if (!this.isAudienceChange) {
                    this.savePreferences('audiences', audienceSelected, 'global', 'grid');
                }
            }, this);

            this.customTone.subscribe(function (customTone) {
                if (customTone) {
                    this.tonesSelected(['custom']);
                }
                preferences.customTone(customTone);
                customToneStyle.customTone(customTone);
            }, this);

            this.customStyle.subscribe(function (customStyle) {
                this.stylesSelected('custom');
                preferences.customStyle(customStyle);
                customToneStyle.customStyle(customStyle);
            }, this);

            editData.opened.subscribe(function (opened) {
                if (opened) {
                    /* reset accordions */
                    $(this.accordionKeywordAttributesSelector).accordion('activate', 0);
                    $(this.accordionKeywordAttributesSelector).accordion('activate', 1);
                    $(this.accordionKeywordAttributesSelector).accordion('activate', 2);
                    $(this.accordionSelector).each(function () {
                        if ($(this).hasClass('wtai-fieldset')) {
                            $(this).accordion('activate');
                        }
                    });
                } else {
                    self.isGenToneStyleModeChange = true;
                    self.genToneStyleMode('manual');
                    settings.genToneStyleMode('manual');
                    self.isGenToneStyleModeChange = false;
                }
                if (opened && !this.widgetsInitialized) {
                    this.bindCollapsible();
                    this.bindCheckboxToggle();
                    this.bindAccordionToggle();
                    this.widgetsInitialized = true;
                }
            }, this);

            settings.guideSteps.subscribe(function (guideSteps) {
                self.guideSteps(guideSteps);
            });

            self.highlightPronouns.subscribe(function (highlightPronouns) {
                if (!self.isHighlightPronounsChange) {
                    textfields.highlightPronouns(highlightPronouns);
                    self.saveHighlightPronouns(highlightPronouns);
                }
            });

            textfields.highlightPronouns.subscribe(
                function (highlightPronouns) {
                    self.isHighlightPronounsChange = true;
                    self.highlightPronouns(highlightPronouns);
                    self.isHighlightPronounsChange = false;
                }
            );
            
            if (settings.genToneStyleMode) {
                settings.genToneStyleMode.subscribe(function (mode) {
                    self.isGenToneStyleModeChange = true;
                    self.genToneStyleMode(mode);
                    self.isGenToneStyleModeChange = false;
                });
            }

            this.genToneStyleMode.subscribe(function (mode) {
                if (settings.genToneStyleMode && !self.isGenToneStyleModeChange) {
                    settings.genToneStyleMode(mode);
                }

                this.useAiModel(mode === 'ai_model');

                if (mode === 'manual') {
                    this.selectedAiModel(null);
                }
            }.bind(this));

            self.selectedAudience.subscribe(function (selectedAudience) {
                if (!self.selectedAudiencechanged) {
                    audience.selectedAudience(selectedAudience);
                }
            });

            audience.selectedAudience.subscribe(function (selectedAudience) {
                self.selectedAudiencechanged = true;
                self.selectedAudience(selectedAudience);
                self.selectedAudiencechanged = false;
            });

            audience.suggestedAudience.subscribe(function (suggestedAudience) {
                self.suggestedAudience(suggestedAudience);
            });

            customToneStyle.customTone.subscribe(function (customTone) {
                self.customTone(customTone);
            });

            customToneStyle.customStyle.subscribe(function (customStyle) {
                self.customStyle(customStyle);
            });

            additionalPrompt.promptValue.subscribe(function (promptValue) {
                self.additionalPrompt(promptValue);
            });

            settings.useAiModel.subscribe(function (useAiModel) {
                this.useAiModel(useAiModel);
            }, this);

            settings.selectedAiModel.subscribe(function (selectedAiModel) {
                this.selectedAiModel(selectedAiModel);
                if (this.selectedAiModel()) {
                    this.genToneStyleMode("ai_model");
                }
            }, this);

            this.useAiModel.subscribe(function (useAiModel) {
                settings.useAiModel(useAiModel);
            });

            this.selectedAiModel.subscribe(function (selectedAiModel) {
                settings.selectedAiModel(selectedAiModel ? selectedAiModel : '');
            });

            this.hasProAccess.subscribe(function (hasProAccess) {
                if (!hasProAccess) {
                    this.useAiModel(false);
                    this.selectedAiModel(null);
                }
            }, this);
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe([
                'suggestedAudience',
                'selectedAudience',
                'tonesSelected',
                'stylesSelected',
                'audienceSelected',
                'selectAllTonesValue',
                'selectAllAudienceValue',
                'customTone',
                'customStyle',
                'guideSteps',
                'highlightPronouns',
                'additionalPrompt',
                'useAiModel',
                'selectedAiModel',
                'genToneStyleMode'
            ]);

            this.keywords = ko.computed(function () {
                var optimizingKeywords = keywordAnalysisData.optimizationData().allOptimizingKeywords || [];
                
                if (optimizingKeywords && optimizingKeywords.length > 0) {
                    return optimizingKeywords;
                } else {
                    return keywordsData.selectedKeywords();
                }
            }, this);

            this.formalLanguageSupport = ko.computed(function () {
                return settings.formalLanguageSupport();
            });
            
            this.formalLanguages = ko.computed(function () {
                return settings.formalLanguages();
            });

            this.language = ko.computed(function () {
                return product.language();
            });

            this.disallowedCombinations = ko.computed(function () {
                return settings.disallowedCombinations();
            });

            this.tones = ko.computed(function () {
                var tones = settings.tones(),
                    selected = tones
                        .filter(function (tone) {
                            return tone.default;
                        })
                        .map(function (tone) {
                            return tone.id;
                        });

                if (selected.length > 0) {
                    this.tonesSelected(selected);
                }

                return tones;
            }, this);

            this.styles = ko.computed(function () {
                var styles = settings.styles(),
                    selected = styles
                        .filter(function (style) {
                            return style.default;
                        })
                        .map(function (style) {
                            return style.id;
                        });

                if (!this.stylesSelected() && selected.length > 0) {
                    this.stylesSelected(selected.shift());
                }

                return styles;
            }, this);

            this.audience = ko.computed(function () {
                var audiences = settings.audience(),
                    selected = audiences
                        .filter(function (item) {
                            return item.default;
                        })
                        .map(function (item) {
                            return item.id;
                        });

                this.isAudienceChange = true;
                this.audienceSelected(selected);
                this.isAudienceChange = false;
                    
                return audiences;
            }, this);

            this.getTonesStylesSelected = ko.computed(function () {
                var tonesCount = this.tonesSelected() ? this.tonesSelected().length : 0,
                    stylesCount = this.stylesSelected() ? 1 : 0,
                    total = tonesCount + stylesCount;

                return total + ' ' + $t('selected');
            }, this);

            this.getAudienceSelected = ko.computed(function () {
                var audienceCount = this.audienceSelected() ? this.audienceSelected().length : 0;

                return audienceCount + ' ' + $t('selected');
            }, this);
            
            this.getCustomStyleLength = ko.computed(function () {
                return textfieldsUtils.getCharCount(this.customStyle(), this.rules.maxCustomStyleLength);
            },  this);

            this.getCustomToneLength = ko.computed(function () {
                return textfieldsUtils.getCharCount(this.customTone(), this.rules.maxCustomToneLength);
            },  this);

            this.getCustomAudienceLength = ko.computed(function () {
                return textfieldsUtils.getCharCount(this.selectedAudience(), this.rules.maxCustomAudienceLength);
            },  this);

            this.selectedFields = ko.computed(function () {
                return textfields.selectedFields();
            });

            this.allFieldsSelected = ko.computed(function () {
                var allFields = [
                    'page_title',
                    'page_description',
                    'category_description'
                ];
                return allFields.every(field => this.selectedFields().includes(field));
            }, this);

            this.rewriteAvailable = ko.computed(function () {
                var isProductOptimizing = Number(keywordAnalysisData.optimizingId()) === Number(editData.currentCategory().categoryId) &&
                    Number(keywordAnalysisData.optimizingStoreId()) === Number(editData.currentCategory().storeId),
                keywordAnalysisOngoing = (keywordAnalysisData.optimizing() ||
                    keywordAnalysisData.isUploading()) &&
                    !keywordAnalysisData.optimized() &&
                    !keywordAnalysisData.optimizationFailed() &&
                    !keywordAnalysisData.imageUploadFailed();

                if (keywordAnalysisOngoing && isProductOptimizing) {
                    return false;
                }

                var mapping = {
                    'page_title': textfields.mgPageTitle(),
                    'page_description': textfields.mgPageDescription(),
                    'category_description': textfields.mgCategoryDescription()
                };
                return textfields.selectedFields.some(field => mapping[field] !== '');
            }, this);

            this.enableHighlightPronouns = ko.computed(function () {
                return this.tonesSelected().indexOf('Formal') !== -1;
            }, this);

            this.isTrainedModelEnabled = ko.computed(function () {
                return this.useAiModel();
            }, this);

            this.hasProAccess = ko.computed(function () {
                return totalCredits.hasProAccess();
            });

            return this;
        },

        /**
         * Process click functionality of select all
         * Important to always return true
         * in order for checked binding to continue working
         *
         * @returns {boolean}
         */
        processClick: function () {
            return true;
        },

        /**
         * Bind select text fields checkbox toggle.
         */
        bindCheckboxToggle: function () {
            const fields = [
                'page_title',
                'page_description',
                'category_description'
            ];
        
            $(this.toggleSelectAllSelector).on('click', (event) => {
                let value = [];
        
                if (event.target.checked) {
                    value = fields;
                }
                
                textfields.selectedFields(value);
                self.savePreferences('single_editor', value, self.entityType, 'edit');
            });
        },

        /**
         * Bind settings dropdown toggle.
         */
        bindCollapsible: function () {
            toolbarUtils.bindCollapsible(self);
        },

        /**
         * Bind text field accordion toggle.
         */
        bindAccordionToggle: function () {
            $(self.accordionToggleSelector).on('click', function () {
                if (self.accordionExpanded) {
                    $(self.accordionTargetSelector).accordion('deactivate');
                    $(self.accordionKeywordAttributesSelector).accordion('deactivate');
                    self.accordionExpanded = false;
                } else {
                    $(self.accordionTargetSelector).accordion('activate');
                    $(self.accordionKeywordAttributesSelector).accordion('activate');
                    self.accordionExpanded = true;
                }
            });
        },

        /**
         * Get tooltip text based on disallowed combination
         *
         * @param {string} id
         * @param {string} type
         *
         * @returns {string}
         */
        getToolTipCombinationDisallowed: function (id, type) {
            if (this.isCombinationDisallowed(id, type)) {
                return this.getTooltipCombinationDisallowedText(id, type);
            }
            return '';
        },

        /**
         * Check if combination is not allowed
         *
         * @param {string} id
         * @param {string} type
         *
         * @returns {boolean}
         */
        isCombinationDisallowed: function (id, type) {
            return toolbarUtils.isCombinationDisallowed(id, type, self);
        },

        /**
         * Select a suggested audience.
         *
         * @param {string} selected
         * @return void
         */
        selectAudience: function (selected = null) {
            if (!self.isGenerateAllowed) {
                return;
            }

            var url = self.audienceSelectUrl,
                storeId = editData.currentCategory().storeId,
                categoryId = editData.currentCategory().categoryId;

            selected = selected || self.selectedAudience();
            
            errorMessagesModel.messages([]);

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    category_id: categoryId,
                    store_id: storeId,
                    selected: selected,
                    category_name: category.categoryName()
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showAudienceLoader: true,
                success: function (response) {
                    if (response.success) {
                        self.selectedAudience(response.selected.shift());
                        self.suggestedAudience(response.values);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                }
            });
        },

        /**
         * Regenerate suggested audience.
         */
        regenerateAudience: function () {
            self.getAudience(true);
        },

        /**
         * Regenerate suggested audience.
         */
        getAudience: function (regenerate = false) {
            var url = self.audienceGetUrl,
                storeId = editData.currentCategory().storeId,
                categoryId = editData.currentCategory().categoryId;

            self.selectedAudience('');
            self.suggestedAudience('');

            errorMessagesModel.messages([]);
            if (self.getAudienceRequest) {
                self.getAudienceRequest.abort();
            }

            self.getAudienceRequest = $.ajax({
                url: url,
                type: 'POST',
                data: {
                    category_id: categoryId,
                    store_id: storeId,
                    keywords: self.keywords(),
                    category_name: category.categoryName(),
                    regenerate: regenerate
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showAudienceLoader: true,
                success: function (response) {
                    if (response.success) {
                        self.selectedAudience(response.selected.shift());
                        self.suggestedAudience(response.values);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                },
                error: function (xhr, status, error) {
                    if (status !== 'abort') {
                        errorMessagesModel.messages.push(error);
                    }
                }
            });
        },

        /**
         * Get tooltip text based on disallowed combination
         *
         * @param {string} id
         * @param {string} type
         *
         * @returns {string}
         */
        getTooltipCombinationDisallowedText: function (id, type) {
            return toolbarUtils.getTooltipCombinationDisallowedText(id, type, self);
        },

        /**
         * Select all tones.
         */
        selectAllTones: function () {
            var tones = self.tones().map(function (tone) {
                if (!$('[name="tones[]"][value="' + tone.id + '"]').attr('disabled')
                    && !$('[name="tones[]"][value="' + tone.id + '"]').hasClass('wtai-disabled')) {
                    return tone.id;
                }
            }).filter(function (element) {
                return element != null;
            });

            this.canUpdateTones = false;
            if (this.selectAllTonesValue()) {
                self.tonesSelected(tones);
            } else {
                self.tonesSelected([]);
            }
            this.canUpdateTones = true;

            self.saveTonesAndStyles();
        },

        /**
         * Observe tones selected.
         */
        observeTonesSelected: function () {
            var tonesSelectedCount = self.tonesSelected() ? self.tonesSelected().length : 0;

            if (settings.tones().length === tonesSelectedCount) {
                this.selectAllTonesValue(true);
            } else {
                this.selectAllTonesValue(false);
            }
        },

        /**
         * Handle input custom audience.
         */
        handleInputAudience: function () {
            if (!self.isGenerateAllowed) {
                return;
            }
            clearTimeout(self.typingTimer);

            self.typingTimer = setTimeout(function () {
                self.selectAudience();
            }, 2000);
        },

        /**
         * Select all audience.
         */
        selectAllAudience: function () {
            if (!self.isGenerateAllowed) {
                return;
            }
            var allAudience = self.audience().map(function (data) {
                if (!$('[name="audience[]"][value="' + data.id + '"]').attr('disabled')) {
                    return data.id;
                }
            });

            this.canUpdateAudience = false;
            if (this.selectAllAudienceValue()) {
                self.audienceSelected(allAudience);
            } else {
                self.audienceSelected([]);
            }
            this.canUpdateAudience = true;
        },

        /**
         * Observe audience selected.
         */
        observeAudienceSelected: function () {
            var audienceSelectedCount = self.audienceSelected() ? self.audienceSelected().length : 0;

            if (settings.audience().length === audienceSelectedCount &&
                settings.audience().length > 0
            ) {
                this.selectAllAudienceValue(true);
            } else {
                this.selectAllAudienceValue(false);
            }
        },

        /**
         * Check if not custom
         *
         * @param {string} value
         * @returns {boolean}
         */
        isNotCustom: function (value) {
            return value !== 'custom';
        },

        /**
         * Save user settings for highlighted pronouns.
         *
         * @param {boolean} highlighted
         * @returns {void}
         */
        saveHighlightPronouns: function (highlighted) {
            $.ajax({
                url: self.highlightPronounsUrl,
                type: 'POST',
                data: {
                    highlighted: highlighted,
                    entity_type: self.entityType
                },
                dataType: 'json',
                showWriteTextAILoader: false,
                success: function (response) {
                    if (!response.success) {
                        console.log(response.message);
                    }
                }
            });
        },

        /**
         * Handle custom tone and style typing
         */
        handleCustomToneStyle: function () {
            clearTimeout(self.typingTimer);

            self.typingTimer = setTimeout(function () {
                self.saveTonesAndStyles();
            }, 2000);
        },

        /**
         * Save user preferences for tones and styles
         */
        saveTonesAndStyles: function () {
            var url = self.saveUrl,
                tones = self.tonesSelected(),
                customTone = self.customTone(),
                styles = self.stylesSelected(),
                customStyle = self.customStyle();
            
            if (tones.length <= 0) {
                tones = '';
            }

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    tones: tones,
                    style: styles,
                    custom_tone: customTone,
                    custom_style: customStyle,
                    entity_type: 'global',
                    scope: 'grid'
                },
                dataType: 'json',
                showWriteTextAILoader: false,
                success: function (response) {
                    if (!response.success) {
                        console.log(response);
                    }
                }
            });
        },

        /**
         * Save user preferences
         *
         * @param {string} field
         * @param {string} selected
         * @param {string} entityType
         *
         * @returns {void}
         */
        savePreferences: function (field, selected, entityType = '', scope = '') {
            var value = selected;
            
            if (value.length <= 0) {
                value = '';
            }
            
            $.ajax({
                url: self.saveUrl,
                type: 'POST',
                data: {
                    [field]: value,
                    entity_type: entityType,
                    scope: scope
                },
                dataType: 'json',
                showLoader: false,
                success: function (response) {
                    if (!response.success) {
                        console.log(response);
                    }
                }
            });
        },

        /**
         * Reset settings.
         *
         * @param {string} type
         * @returns {void}
         */
        reset: function (type) {
            if (type === 'tones') {
                self.tonesSelected(self.defaultTones);
                self.stylesSelected(self.defaultStyle);
                self.saveTonesAndStyles();
            }

            if (type === 'audience') {
                if (!self.isGenerateAllowed) {
                    return;
                }
                self.audienceSelected([...self.defaultAudiences]);
            }
        }
    });
});
