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

define([
    'jquery',
    'uiComponent',
    'underscore',
    'ko',
    'WriteTextAI_WriteTextAI/js/model/edit/product',
    'WriteTextAI_WriteTextAI/js/model/total-credits',
    'WriteTextAI_WriteTextAI/js/categories/model/edit',
    'WriteTextAI_WriteTextAI/js/categories/model/edit/textfields',
    'WriteTextAI_WriteTextAI/js/utils/edit/textfields',
    'WriteTextAI_WriteTextAI/js/model/edit/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/error-messages',
    'WriteTextAI_WriteTextAI/js/model/edit/transfer/settings',
    'WriteTextAI_WriteTextAI/js/model/edit/review-status',
    'WriteTextAI_WriteTextAI/js/model/edit/mark-reviewed',
    'WriteTextAI_WriteTextAI/js/model/edit/preferences',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keywords',
    'WriteTextAI_WriteTextAI/js/categories/model/signalr',
    'wysiwygAdapter',
    'Magento_Ui/js/modal/confirm',
    'mage/translate',
    'mage/adminhtml/wysiwyg/tiny_mce/setup',
    'wtaiOwlCarousel'
], function (
    $,
    Component,
    _,
    ko,
    product,
    totalCredits,
    editData,
    textfields,
    textfieldsUtils,
    settings,
    generateSettings,
    errorMessagesModel,
    transferSettings,
    reviewStatus,
    markReviewed,
    preferences,
    keywordAnalysisData,
    keywordsData,
    signalRModel,
    wysiwygAdapter,
    confirm,
    $t
) {
    'use strict';

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

    /**
     * Highlight words in a textarea
     */
    ko.bindingHandlers.highlightWords = {
        update: textfieldsUtils.highlightWords
    };

    return Component.extend({
        defaults: {
            pageTitle: '',
            pageDescription: '',
            categoryDescription: '',
            descMin: 0,
            descMax: 0,
            selectedFields: [],
            reviewStatus: []
        },

        isSelectedFieldsChange: false,
        isPageTitleChange: false,
        isPageDescriptionChange: false,
        isCategoryDescriptionChange: false,
        wysiwygInitialized: false,
        carouselInitialized: false,
        isDescMinChange: false,
        isDescMaxChange: false,
        isEditAllowed: false,

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

            self = this;

            const el = document.querySelector('.wtai-textfields');
            if (el) {
                $('.wtai-textfields > *').applyBindings(this);
            }

            textfields.pageTitle.subscribe(function (pageTitle) {
                this.isPageTitleChange = true;
                this.pageTitle(pageTitle);
                this.isPageTitleChange = false;
            }, this);

            this.pageTitle.subscribe(function (pageTitle) {
                if (!this.isPageTitleChange) {
                    textfields.pageTitle(pageTitle);
                }
            }, this);

            textfields.pageDescription.subscribe(function (pageDescription) {
                this.isPageDescriptionChange = true;
                this.pageDescription(pageDescription);
                this.isPageDescriptionChange = false;
            }, this);

            this.pageDescription.subscribe(function (pageDescription) {
                if (!this.isPageDescriptionChange) {
                    textfields.pageDescription(pageDescription);
                }
            }, this);

            textfields.categoryDescription.subscribe(function (categoryDescription) {
                var wysiwyg = wysiwygAdapter.get('wtaiNewCategoryDescription');

                if (categoryDescription !== this.categoryDescription()) {
                    this.isCategoryDescriptionChange = true;

                    /* categoryDescription = textfieldsUtils.convertNewLinesToBr(categoryDescription); */

                    /* Set description */
                    this.categoryDescription(categoryDescription);

                    if (!wysiwyg) {
                        return;
                    }

                    /* Sync scroll */
                    $(wysiwyg.getWin()).on('scroll', function (event) {
                        $('#wtaiCategoryDescMask').scrollTop(event.currentTarget.scrollY);
                        $('#wtaiCategoryDescMask').scrollLeft(event.currentTarget.scrollX);
                        if (wysiwygAdapter.get('wtaiCategoryDescMask') !== null) {
                            wysiwygAdapter.get('wtaiCategoryDescMask').contentWindow.scrollTo(
                                event.currentTarget.scrollX,
                                event.currentTarget.scrollY
                            );
                        }
                    });

                    /* Set wywiwyg content */
                    wysiwyg.setContent(categoryDescription);

                    /* Disable wysiwyg editor */
                    if ((!this.wysiwygInitialized &&
                        $('#wtaiNewProductDescription').prop('readonly') &&
                        wysiwyg.getBody()) || !this.isEditAllowed
                    ) {
                        wysiwyg.getBody().setAttribute('contenteditable', false);
                        this.wysiwygInitialized = true;
                    }

                    this.isCategoryDescriptionChange = false;
                }
            }, this);

            this.categoryDescription.subscribe(function (categoryDescription) {
                if (!this.isCategoryDescriptionChange) {
                    textfields.categoryDescription(categoryDescription);
                }
            }, this);

            this.descMin.subscribe(function (descMin) {
                generateSettings.descMin(descMin);
                settings.descMin(descMin);
                if (!self.isDescMinChange) {
                    self.savePreferences('desc_min', descMin);
                }
            }, this);

            this.descMax.subscribe(function (descMax) {
                generateSettings.descMax(descMax);
                settings.descMax(descMax);
                if (!self.isDescMaxChange) {
                    self.savePreferences('desc_max', descMax);
                }
            }, this);

            this.selectedFields.subscribe(function (selectedFields) {
                if (!this.isSelectedFieldsChange) {
                    let value = selectedFields.filter(function (field) {
                        return field !== null;
                    });

                    textfields.selectedFields(value);
                    self.savePreferences('single_editor', value, 'category', 'edit');
                }
            }, this);

            textfields.selectedFields.subscribe(function (selectedFields) {
                this.isSelectedFieldsChange = true;
                this.selectedFields([]);
                for (let key in selectedFields) {
                    if (selectedFields.hasOwnProperty(key)) {
                        this.selectedFields.push(selectedFields[key]);
                    }
                }
                this.isSelectedFieldsChange = false;
            }, this);

            editData.opened.subscribe(function (opened) {
                if (opened) {
                    $('.wtai-edit-modal .wtai-input-number').spinner({
                        numberFormat: 'n',
                        min: self.rules.minOutputWords,
                        max: self.rules.maxOutputWords,
                        disabled: !self.wordsAllowed,
                        spin: function (event, ui) {
                            var value = ui.value,
                                name = $(event.target).attr('name');
                            
                            switch (name) {
                                case 'category_description_min':
                                    self.isDescMinChange = true;
                                    self.descMin(value);
                                    self.isDescMinChange = false;
                                    break;
                                case 'category_description_max':
                                    self.isDescMaxChange = true;
                                    self.descMax(value);
                                    self.isDescMaxChange = false;
                                    break;
                            }
                        },
                        change: function (event) {
                            var value = event.target.value,
                                name = $(event.target).attr('name');
                            
                            switch (name) {
                                case 'category_description_min':
                                    self.descMin(value);
                                    break;
                                case 'category_description_max':
                                    self.descMax(value);
                                    break;
                            }
                        }
                    });

                    self.initEditors();
                    self.initUnsavedChanges();
                }
            });

            settings.descMin.subscribe(function (descMin) {
                self.isDescMinChange = true;
                self.descMin(descMin);
                self.isDescMinChange = false;
            });

            settings.descMax.subscribe(function (descMax) {
                self.isDescMaxChange = true;
                self.descMax(descMax);
                self.isDescMaxChange = false;
            });

            reviewStatus.reviewStatus.subscribe(function (reviewStatus) {
                if (self.carouselInitialized) {
                    $(".wtai-review_status-tooltip .owl-carousel").trigger('destroy.owl.carousel');
                    $(".wtai-review_status-tooltip .owl-carousel").html('');
                }
                self.reviewStatus(reviewStatus);
                self.initReviewCarousel();
            });
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super()
                .observe([
                    'pageTitle',
                    'pageDescription',
                    'categoryDescription',
                    'descMin',
                    'descMax',
                    'selectedFields',
                    'reviewStatus'
                ]);

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

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

                return keywordAnalysisOngoing && isProductOptimizing;
            }, this);

            this.getFieldReviewStatus = function (textType) {
                var self = this;
                var result = ko.computed(function () {
                    let statuses = [];

                    if (self.reviewStatus()) {
                        self.reviewStatus().forEach(function (store) {
                            if (!store.reviews) {
                                return;
                            }
                            store.reviews.forEach(function (status) {
                                if (!status.fields) {
                                    return;
                                }
    
                                let fieldReview = status.fields.filter(function (field) {
                                    return field.field === textType && field.status >= 1;
                                });
    
                                if (fieldReview.length <= 0) {
                                    return;
                                }
    
                                statuses.push(fieldReview.shift().status);
                            });
                        });
                    }

                    let uniqueStatuses = [...new Set(statuses)];
                    switch (uniqueStatuses.length) {
                        case 1: return uniqueStatuses[0];
                        case 0: return 0;
                        default: return 3;
                    }
                });
                    
                return result();
            }.bind(this);

            this.storeId = ko.computed(function () {
                return product.storeId();
            });
            
            this.isAllStoreView = ko.computed(function () {
                return Number(this.storeId()) === Number(this.defaultStoreId);
            }, this);

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

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

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

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

            this.informal = ko.computed(function () {
                return preferences.stylesSelected() === 'Internet-speak';
            });

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

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

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

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

            this.mgCategoryDescription = ko.computed(function () {
                var wysiwyg = wysiwygAdapter.get('wtaiCategoryDescription'),
                    mgProductDescription = textfields.mgCategoryDescription();

                if (wysiwyg !== null) {
                    if (mgProductDescription) {
                        /** mgProductDescription = textfieldsUtils.convertNewLinesToBr(mgProductDescription); */
                        wysiwyg.setContent(mgProductDescription);
                    } else {
                        wysiwyg.setContent('');
                    }
                }

                return mgProductDescription;
            });

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

            this.keywords = ko.computed(function () {
                return [];
            });

            this.highlighted = ko.computed(function () {
                return true;
            });

            this.optimizationData = ko.computed(function () {
                return keywordAnalysisData.optimizationData();
            });

            this.selectedKeywords = ko.computed(function () {
                return keywordsData.selectedKeywords();
            });

            return this;
        },

        /**
         * Init unsaved changes validator
         */
        initUnsavedChanges: function () {
            $(window).on('beforeunload', function () {
                if (textfields.originalPageTitle() !== textfields.pageTitle() ||
                    textfields.originalPageDescription() !== textfields.pageDescription() ||
                    textfields.originalCategoryDescription() !== textfields.categoryDescription()
                ) {
                    return $t('You have unsaved changes. Are you sure you want to leave this page?');
                }
            });
        },

        /**
         * Check if field is not editable.
         *
         * @param {Boolean} status
         * @returns {Boolean}
         */
        isNotEditable: function (status) {
            if (self.keywordAnalysisOngoing()) {
                return true;
            }

            return status;
        },
    
        /**
         * Update review status
         *
         * @param {String} textType
         * @returns {void}
         */
        updateReviewStatus: function (textType) {
            errorMessagesModel.messages([]);
            $.ajax({
                url: self.reviewUrl,
                type: 'POST',
                data: {
                    text_type: textType,
                    category_id: product.productId(),
                    store_id: product.storeId()
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                success: function (response) {
                    if (!response.success) {
                        errorMessagesModel.messages.push(response.message);
                    } else {
                        reviewStatus.reviewStatus(response.updatedReview);
                    }
                }
            });
        },

        /**
         * Initialize review carousel
         */
        initReviewCarousel: function () {
            $(".wtai-review_status-tooltip .owl-carousel").owlCarousel({
                nav : true,
                dots: false,
                loop: true,
                items : 1,
                mouseDrag: false,
                touchDrag: false,
                pullDrag: false,
                onInitialized: this.carouselCounter,
                onChanged: this.carouselCounter
            });

            this.carouselInitialized = true;
        },

        /**
         * Carousel counter
         *
         * @param {Object} event
         * @returns {void}
         */
        carouselCounter: function (event) {
            var slides = event.relatedTarget;

            if (!event.namespace) {
                return;
            }

            $('.wtai-review_status-tooltip .owl-carousel-counter').text(
                slides.relative(slides.current()) + 1
                + ' ' + $t('of') + ' '
                + slides.items().length
            );
        },

        /**
         * Get status' status
         *
         * @param {Array} fields
         * @param {String} textType
         *
         * @returns {Number}
         */
        getStatusStatus: function (fields, textType) {
            let fieldReview = fields.filter(function (field) {
                return field.field === textType;
            });

            if (fieldReview.length <= 0) {
                return;
            }

            return fieldReview.shift().status;
        },

        /**
         * Show store review
         *
         * @param {Object} store
         * @param {String} textType
         *
         * @returns {Boolean}
         */
        showStoreReview: function (store, textType) {
            if (store.reviews.length <= 0) {
                return false;
            }

            for (let i = 0; i < store.reviews.length; i++) {
                if (self.getStatusStatus(store.reviews[i].fields, textType) >= 1) {
                    return true;
                }
            }
        },

        /**
         * Transfer text to Magento.
         *
         * @param {String} field
         * @param {String} value
         *
         * @returns {void}
         */
        transfer: function (field, value) {
            confirm({
                title: $.mage.__('Transfer selected to Magento'),
                content: self.confirmContent,
                modalClass: 'wtai-modal wtai-bulk-transfer-popup wtai-transfer wtai-edit',
                actions: {
                    confirm: function () {
                        self._transfer(field, value);
                    }
                },
                buttons: [{
                    text: $.mage.__('Cancel'),
                    class: 'action-secondary action-dismiss',
                    click: function (event) {
                        this.closeModal(event);
                    }
                }, {
                    text: $.mage.__('OK'),
                    class: 'action-primary action-accept',
                    click: function (event) {
                        if (
                            $('#wtaiEditTransferForm').data('validator') &&
                            $('#wtaiEditTransferForm').validation() &&
                            $('#wtaiEditTransferForm').validation('isValid')
                        ) {
                            this.closeModal(event, true);
                        }
                    }
                }]
            });
        },

        /**
         * Transfer field generated to live
         *
         * @param {String} field
         * @param {String} value
         *
         * @returns {void}
         */
        _transfer: function (field, value) {
            var url = self.transferUrl;

            errorMessagesModel.messages([]);

            signalRModel.editTitleStatusText($t('Transferring...'));

            $.ajax({
                url: url,
                type: 'POST',
                data: {
                    category_id: editData.currentCategory().categoryId,
                    store_id: editData.currentCategory().storeId,
                    selected_fields: {
                        [field]: value
                    },
                    selected_stores: transferSettings.selectedStores()
                },
                dataType: 'json',
                showWriteTextAILoader: true,
                showPageTitleLoader: field === 'page_title',
                showPageDescriptionLoader: field === 'page_description',
                showCategoryDescriptionLoader: field === 'category_description',
                success: function (response) {
                    var fields = {},
                        writeTextFields = {};
                        
                    fields[field] = value;
                    writeTextFields[field] = value;

                    if (response.success) {
                        var responseFields = response.fields;
                        if (response.use_default) {
                            textfields.useDefault({
                                pageTitle: field === 'page_title' ?
                                    response.use_default.page_title : textfields.useDefault().pageTitle,
                                pageDescription: field === 'page_description' ?
                                    response.use_default.page_description : textfields.useDefault().pageDescription,
                                categoryDescription: field === 'category_description' ?
                                    response.use_default.category_description : textfields.useDefault().categoryDescription
                            });
                        }
                        markReviewed.reviewed(response.reviewed);
                        if (transferSettings.selectedStores().map(String).includes(String(editData.currentCategory().storeId))) {
                            textfieldsUtils.updateCategoryCurrentFields(responseFields, [field], writeTextFields);
                        }
                        reviewStatus.reviewStatus(response.updatedReview);
                    } else {
                        errorMessagesModel.messages.push(response.message);
                    }
                    signalRModel.editTitleStatusText('');
                },
                error: function () {
                    signalRModel.editTitleStatusText('');
                }
            });
        },

        /**
         * Sync scroll
         *
         * @param {Object} data
         * @param {Object} event
         * @param {String} elementId
         *
         * @returns {void}
         */
        syncScroll: function (data, event, elementId) {
            var elementSelector = '#' + elementId,
                scrollAmount = event.target.scrollTop,
                scrollXAmount = event.target.scrollLeft;

            $(elementSelector).scrollTop(scrollAmount);
            $(elementSelector).scrollLeft(scrollXAmount);
        },

        /**
         * Get char count.
         *
         * @param {String} html
         * @param {Number} limit
         *
         * @returns {Number}
         */
        getCharCount: function (html, limit = null) {
            return textfieldsUtils.getCharCount(html, limit);
        },

        /**
         * Get word count.
         *
         * @param {String} html
         * @returns {Number}
         */
        getWordCount: function (html) {
            return textfieldsUtils.getWordCount(html);
        },

        /**
         * Validate number.
         *
         * @param {Object} data
         * @param {Object} event
         *
         * @returns {Boolean}
         */
        ensureNumerical: function (data, event) {
            return textfieldsUtils.ensureNumerical(event.key);
        },

        /**
         * Validate min and max fields.
         *
         * @param {Object} data
         * @param {Object} event
         *
         * @returns {void}
         */
        validateMinMax: function (data, event) {
            var target = event.target,
                value = Number(target.value),
                min = Number(target.min),
                max = Number(target.max),
                name = target.name;

            const mapping = {
                category_description_min: self.descMin,
                category_description_max: self.descMax
            };

            if (value < min || value > max) {
                const func = mapping[name],
                    val = value < min ? min : max;

                $(target).val(val);
                func(val);
            }
        },

        /**
         * Check if text is over limit.
         *
         * @param {String} html
         * @param {Number} limit
         *
         * @returns {Boolean}
         */
        isOverLimit: function (html, limit) {
             return textfieldsUtils.isOverLimit(html, limit);
        },

        /**
         * Initialize wysiwyg editors.
         */
        initEditors: function () {
            var config = this.wysiwygConfig,
                disabledConfig = this.disabledWysiwygConfig,
                wtaIds = ['wtaiNewCategoryDescription'],
                mgIds = ['wtaiCategoryDescription'],
                maskIds = ['wtaiCategoryDescMask'];

            function setupEditors(ids, config, additionalClasses = '')
            {
                ids.forEach(function (id) {
                    try {
                        let editor = new wysiwygSetup(id, config);
                        editor.setup('exact');
                        $(id).addClass('wtai-wysiwyg-editor ' + additionalClasses).data('wysiwygEditor', editor);
                    } catch (e) {
                        console.log('wysiwyg failed', e);
                    }
                });
            }

            setupEditors(wtaIds, config);
            setupEditors(maskIds, config, 'wtai-wysiwyg-mask');
            setupEditors(mgIds, disabledConfig);

            if (wysiwygAdapter.get('wtaiNewCategoryDescription') !== null) {
                wysiwygAdapter.get('wtaiNewCategoryDescription').on("change", function () {
                    if (!self.isCategoryDescriptionChange) {
                        textfields.categoryDescription(self.categoryDescription());
                    }
                });
            }
        },

        /**
         * Save user preferences
         *
         * @param {String} field
         * @param {String} selected
         *
         * @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);
                    }
                }
            });
        },
    });
});
