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

define([
    'jquery',
    'underscore',
    'mage/translate',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-pipelines',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/error-messages'
], function (
    $,
    _,
    $t,
    keywordAnalysis,
    keywordPipelines,
    errorMessagesModel
) {
    'use strict';
    
    /**
     * Add keywords to pool
     *
     * @param {Object} self
     * @param {string} keyword
     * @param {string} difficulty
     * @param {Object} event
     *
     * @returns {void}
     */
    function addKeywordsToPool(self, keyword, difficulty, event)
    {
        if (self.savingToPool()) {
            return;
        }

        self.savingToPool(true);
        $(event.currentTarget).closest('.wtai-edit-keyword-item').find('.wtai-edit-keyword-loading-mask').addClass('wtai-show');
        $(event.currentTarget).closest('.wtai-edit-keyword-item').addClass('wtai-saving-keyword');
        self.newKeywordRequestCount(self.newKeywordRequestCount() + 1);
        self.disableCloseAction(true);

        $.ajax({
            url: self.addKeywordsToPoolUrl,
            type: 'POST',
            data: {
                'store_id': self.storeId(),
                'record_id': self.recordId(),
                'entity_type': self.entityType,
                'keyword': keyword
            },
            dataType: 'json',
            showLoader: false,
            success: function (response) {
                if (response.api_response !== undefined
                    && response.api_response.keyword !== undefined
                ) {
                    var optimizationData = keywordAnalysis.optimizationData();
                    optimizationData.keywords.push(response.api_response.keyword);
                    keywordAnalysis.optimizationData(optimizationData);
                    
                    /**
                     * Add the replaced keyword to the pool
                     */
                    var editKeywordPipeline = self.editKeywordPipeline();
                    if (editKeywordPipeline.keywords) {
                        let keywordReplaced = editKeywordPipeline.keywords[difficulty];
                        let keywordPool = optimizationData.keywords;
                        if (!keywordPool.some(keyword => keyword.keyword === keywordReplaced.keyword)) {
                            if (keywordReplaced.keyword !== '' && keywordReplaced.manual !== true) {
                                keywordPool.push(keywordReplaced);
                            }
                        }

                        editKeywordPipeline.keywords[difficulty] = response.api_response.keyword;
                        self.editKeywordPipeline([]);
                        self.editKeywordPipeline(editKeywordPipeline);
                    }
                    
                    $(event.currentTarget).closest('.wtai-edit-keyword-item').removeClass('wtai-input-active');
                    self.newKeywordLength(0);
                    self.inputActive(false);
                }
                
                if (response.error !== undefined) {
                    /**delete error first */
                    errorMessagesModel.messages([]);
                    errorMessagesModel.messages.push(response.error);
                }
            }
        }).always(function () {
            $(event.currentTarget).closest('.wtai-edit-keyword-item').find('.wtai-edit-keyword-loading-mask').removeClass('wtai-show');
            $(event.currentTarget).closest('.wtai-edit-keyword-item').removeClass('wtai-saving-keyword');
            self.newKeywordRequestCount(self.newKeywordRequestCount() - 1);
            self.disableCloseAction(false);
            self.savingToPool(false);
        });
    }

    /**
     * Update keyword on blur
     *
     * @param {Object} self
     * @param {Object} data
     * @param {Object} event
     * @param {string} difficulty
     *
     * @returns {boolean}
     */
    function updateKeywordOnBlur(self, data, event, difficulty)
    {
        let currentKeyword = self.getKeywordToEdit(difficulty);
        if (!self.preventInputBlur) {
            if (event.currentTarget.value !== currentKeyword) {
                    processUpdateKeyword(self, data, event, difficulty);
                    keywordPipelines.preventInputBlur(false);
            } else {
                if (currentKeyword.length === 0) {
                    /**
                     * this is for manually added keyword
                     * if the keyword is manually added and the input is empty
                     * remove the keyword from the pipeline to revert back to placeholder
                     */
                    var editKeywordPipeline = self.editKeywordPipeline();
                    let keywordReplaced = editKeywordPipeline.keywords[difficulty];
                    if (keywordReplaced && keywordReplaced.manually_added) {
                        self.removeKeyword(difficulty);
                    }
                }
                $(event.currentTarget).closest('.wtai-edit-keyword-item').removeClass('wtai-input-active');
                self.newKeywordLength(0);
                self.inputActive(false);
            }
        } else {
            if (currentKeyword.length === 0) {
                /**
                 * this is for manually added keyword
                 * if the keyword is manually added and the input is empty
                 * remove the keyword from the pipeline to revert back to placeholder
                 */
                var editKeywordPipeline = self.editKeywordPipeline();
                let keywordReplaced = editKeywordPipeline.keywords[difficulty];
                if (keywordReplaced && keywordReplaced.manually_added) {
                    self.removeKeyword(difficulty);
                }
            }
            event.currentTarget.value = '';
            $(event.currentTarget).closest('.wtai-edit-keyword-item').removeClass('wtai-input-active');
            self.newKeywordLength(0);
            self.inputActive(false);
            keywordPipelines.preventInputBlur(false);
        }
        return true;
    }

    /**
     * Process update keyword
     *
     * @param {Object} self
     * @param {Object} data
     * @param {Object} event
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function processUpdateKeyword(self, data, event, difficulty)
    {
        var editKeywordPipeline = self.editKeywordPipeline();
        var pipelineList = keywordAnalysis.optimizationData().pipelines;
        var keywordsList = keywordAnalysis.optimizationData().keywords;
        var rankingKeywords = keywordAnalysis.optimizationData().rankingKeywords;
        var keyword = event.currentTarget.value.toLowerCase().trim();
        let keywordReplaced = editKeywordPipeline.keywords[difficulty];
        var errorElem = $(event.currentTarget)
            .closest('.wtai-edit-keyword-item')
            .find('.wtai-input-keywords-error');
        var invalidChars = /[,.!@%^*()={};~`<>?\\|]/g;

        errorElem.removeClass('wtai-active').text('');

        if (keyword.length === 0) {
            if (keywordReplaced.manually_added) {
                /**
                 * this is for manually added keyword
                 * if the keyword is manually added and the input is empty
                 * remove the keyword from the pipeline to revert back to placeholder
                 */
                self.removeKeyword(difficulty);
            }
            $(event.currentTarget).closest('.wtai-edit-keyword-item').removeClass('wtai-input-active');
            self.newKeywordLength(0);
            self.inputActive(false);
            return false;
        }

        var invalidCharList = [];
        var matchedChars = keyword.match(invalidChars) || [];
        if (matchedChars.length > 0) {
            matchedChars.forEach(function (char) {
                if (!invalidCharList.includes(char)) {
                    invalidCharList.push(char);
                }
            });
            if (invalidCharList.length === 1) {
                errorElem.addClass('wtai-active')
                    .text($t('"%s" is an invalid character.').replace('%s', invalidCharList[0]));
            } else {
                errorElem.addClass('wtai-active')
                    .text($t('"%s" are invalid characters.').replace('%s', invalidCharList.join(' ')));
            }

            event.currentTarget.value = event.currentTarget.value.replace(invalidChars, '');

            return false;
        }
        var isKeywordExistInEdit = Object.values(editKeywordPipeline.keywords).some(keywordData => {
            return keywordData.keyword === keyword;
        });
        var isKeywordExistsInRanking = rankingKeywords.some(keywordData => {
            return keywordData.keyword === keyword;
        });
        if (isKeywordExistInEdit || isKeywordExistsInRanking) {
            /** Keyword exists in the current pipeline */
            errorElem.addClass('wtai-active')
                .text($t('The keyword already exists.'));
            return false;
        }

        if (pipelineList) {
            var isKeywordExist = pipelineList.some(pipeline => {
                if (pipeline.id === editKeywordPipeline.id) {
                    return false;
                }
                
                return Object.values(pipeline.keywords).some(keywordData => {
                    return keywordData.keyword === keyword;
                });
            });

            if (isKeywordExist) {
                /** Keyword exists in the another pipeline */
                errorElem.addClass('wtai-active')
                    .text($t("The keyword already exists."));
                return false;
            }
        }
        if (keywordsList) {
            var isKeywordExist = keywordsList.some(keywordData => {
                return keywordData.keyword === keyword;
            });
            if (!isKeywordExist) {
                addKeywordsToPool(self, keyword, difficulty, event);
                return;
            } else {
                /**
                 * Add the replaced keyword to the pool
                 */
                if (!keywordsList.some(keyword => keyword.keyword === keywordReplaced.keyword)) {
                    keywordsList.push(keywordReplaced);
                }

                /**
                 * Get the existing keyword to pool
                 */
                editKeywordPipeline.keywords[difficulty] = keywordsList.find(keywordData => keywordData.keyword === keyword);
                self.editKeywordPipeline([]);
                self.editKeywordPipeline(editKeywordPipeline);
                $(event.currentTarget).closest('.wtai-edit-keyword-item').removeClass('wtai-input-active');
                self.newKeywordLength(0);
                self.inputActive(false);
            }
        }
    }

    /**
     * Edit keyword item initial process
     *
     * @param {Object} self
     * @param {Object} currentTarget
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function editkeywordItemInitialProcess(self, currentTarget, difficulty)
    {
        keywordPipelines.preventInputBlur(false);
        var currentKeword = self.getKeywordToEdit(difficulty);
        self.inputActive(true);
        self.newKeywordLength(currentKeword.length);
        $(currentTarget)
            .find('.wtai-input-keywords-error').removeClass('wtai-active')
            .text('');
        $(currentTarget).addClass('wtai-input-active');
        $(currentTarget).find('.admin__control-text').val(currentKeword).focus();
    }

    /**
     * Get converted serp date text
     *
     * @param {Object} self
     * @param {string} difficulty
     * @param {string} keywords
     *
     * @returns {string}
     */
    function getSerpDateText(self, difficulty, keywords)
    {
        var rawDate = self.getKeywordData(difficulty, keywords, 'serpDate');
        var dateFormat = rawDate || new Date();
        var datePrepare = new Date(dateFormat)
        var formatDate = new Intl.DateTimeFormat('en-US', {
            year: 'numeric',
            month: 'long',
            day: 'numeric',
            hour: '2-digit',
            minute: '2-digit',
            hour12: false,
            timeZone: self.timezone
        }).format(datePrepare);
        formatDate = formatDate.replace(' at ', ' ').trim();
        return $t('SERP data as of %s').replace('%s', formatDate)
    }

    return {
        updateKeywordOnBlur: updateKeywordOnBlur,
        processUpdateKeyword: processUpdateKeyword,
        editkeywordItemInitialProcess: editkeywordItemInitialProcess,
        getSerpDateText: getSerpDateText
    }
});