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

define([
    'jquery',
    'underscore',
    'ko',
    'mage/translate',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/error-messages'
], function (
    $,
    _,
    ko,
    $t,
    keywordAnalysis,
    errorMessagesModel
) {
    'use strict';

    /**
     * Set active trigger settings value
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function setActiveTriggerSettingsValue(self, pipelineId, difficulty)
    {
        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);
        var triggers = pipeline.triggers;
        var option = '';
        var action = '';
        var textTypes = [];
        var defaultNdays = self['triggerActionNDays' + difficulty];
        var defaultNposition = self['triggerActionNPosition' + difficulty];

        const apiOptionEquivalent = {
            'WhenRanking': 'when_page_is_ranking',
            'AfterSetDays': 'after_n_days',
            'None': 'none'
        };
        const apiActionEquivalent = {
            'AutomaticRewrite': 'auto_rewrite_and_queue',
            'FlagForRewrite': 'flag',
            'FullAutomation': 'auto_rewrite_and_transfer'
        };

        if (triggers[difficulty] !== undefined) {
            option = apiOptionEquivalent[triggers[difficulty].option];

            if (option === 'when_page_is_ranking') {
                defaultNposition = triggers[difficulty].value;
            } else if (option === 'after_n_days') {
                defaultNdays = triggers[difficulty].value;
            }

            action = apiActionEquivalent[triggers[difficulty].action];
            textTypes = triggers[difficulty].textTypes;

            if (!self.isCustomOpenGraphEnabled) {
                /** remove open graph from textTypes if there is one */
                textTypes = textTypes.filter(textType => textType !== 'open graph text');
            }
        }

        self.tsActiveTriggerAction('');
        self.tsActiveTriggerActionDays('');
        self.tsActiveTriggerActionPosition('');
        self.tsActiveAutoOptimize('');
        self.tsActiveTextFields([]);

        self.tsActiveTriggerAction(option);
        self.tsActiveTriggerActionDays(defaultNdays);
        self.tsActiveTriggerActionPosition(defaultNposition);
        self.tsActiveAutoOptimize(action);
        self.tsActiveTextFields(textTypes);
    }

    /**
     * adjustPosition of trigger settings popup
     *
     * @param {Object} self
     * @param {Object} activeButton
     *
     * @returns {void}
     */
    function adjustPositionTriggerSettings(self, activeButton)
    {
        /** Get DOM elements */
        var button = activeButton[0];
        var container = document.querySelector('.wtai-pipelines-content');
        var popup = $(self.tsSelectors.activeContent);

        /** Get dimensions and positions */
        var buttonRect = button.getBoundingClientRect();
        var containerRect = container.getBoundingClientRect();
        var popupWidth = popup.outerWidth(true);
        var popupHeight = popup.outerHeight(true);
        
        /** Calculate available space */
        var spaceTop = buttonRect.top - containerRect.top;
        var spaceBottom = containerRect.bottom - buttonRect.bottom;
        var spaceLeft = buttonRect.left - containerRect.left;
        var spaceRight = containerRect.right - buttonRect.right;

        if (spaceBottom > popupHeight ) {
            var classStr = spaceRight > popupWidth ? 'wtai-bottom-right' : 'wtai-bottom-left';
            self.tsContainerClass(classStr);
        } else {
            var classStr = '';
            if (spaceTop > popupHeight) {
                if (spaceRight > popupWidth) {
                    self.tsContainerClass("wtai-top-right");
                }
                if (spaceLeft > popupWidth) {
                    self.tsContainerClass("wtai-top-left");
                }
            } else {
                classStr = spaceRight > spaceLeft ? 'wtai-right-middle' : 'wtai-left-middle';
                
                /** Calculate percentages relative to container height
                 * These are the adjustments after updates on popup content affecting its height
                 */
                var containerHeight = containerRect.height;
                var spaceTopPercent = (spaceTop / containerHeight) * 100;
                var spaceBottomPercent = (spaceBottom / containerHeight) * 100;
                
                if (spaceTopPercent < 40) {
                    classStr += ' wtai-adjust-top';
                } else if (spaceBottomPercent < 40) {
                    classStr += ' wtai-adjust-bottom';
                }
                
                self.tsContainerClass(classStr);
            }
        }
    }

    /**
     * Apply trigger action request
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {array} difficulties
     * @param {string} option
     * @param {string} value
     * @param {string} action
     * @param {array} textTypes
     *
     * @returns {void}
     */
    function applyTriggerActionRequest(
        self,
        pipelineId,
        difficulties,
        option,
        value,
        action,
        textTypes
    ) {
        self.triggerUpdating(true);
        $('#wtai-loader-' + pipelineId).addClass('wtai-show');
        let pipeline_ids = [];
        pipeline_ids.push(pipelineId);

        $.ajax({
            url: self.applyTriggerActionUrl,
            type: 'POST',
            data: {
                'store_id': self.storeId(),
                'record_id': self.recordId(),
                'entity_type': self.entityType,
                'pipeline_ids': pipeline_ids,
                'difficulties': difficulties,
                'option': option,
                'value': value,
                'action': action,
                'text_types': textTypes
            },
            dataType: 'json',
            showLoader: false,
            success: function (response) {
                if (response.success) {
                    var optimizationData = keywordAnalysis.optimizationData();
                    var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);
                    for (var key in response.api_response) {
                        if (pipeline.triggers[key] !== undefined) {
                            pipeline.triggers[key] = response.api_response[key];
                        }
                    }
                    optimizationData.pipelines = optimizationData.pipelines.map(p => {
                        if (p.id === pipelineId) {
                            return pipeline;
                        }
                        return p;
                    });
                    keywordAnalysis.optimizationData(optimizationData);
                } else {
                    if (typeof response.error !== 'undefined') {
                        errorMessagesModel.messages.push(response.error);
                    }
                }
            }
        }).always(function () {
            $('#wtai-loader-' + pipelineId).removeClass('wtai-show');
            self.triggerUpdating(false);
        });
    }

    /**
     * Apply multiple trigger action request
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {array} difficulties
     * @param {string} option
     * @param {string} value
     * @param {string} action
     * @param {array} textTypes
     * @param {boolean} includeLocked
     *
     * @returns {void}
     */
    function applyMultipleTriggerActionRequest(
        self,
        pipelineId,
        difficulties,
        option,
        value,
        action,
        textTypes,
        includeLocked = false
    ) {
        self.triggerUpdating(true);
        $('#wtai-loader-' + pipelineId).addClass('wtai-show');
        var optimizationData = keywordAnalysis.optimizationData();
        var pipelines = optimizationData.pipelines;
        let pipelinesToupdate = [];
        if (includeLocked) {
            pipelinesToupdate = pipelines
            .map(item => ({
                id: item.id,
                keywords: Object.fromEntries(
                    Object.entries(item.keywords).map(([difficulty, keywordData]) => {
                        /* Destructure to exclude serpItems */
                        const { serpItems, ...rest } = keywordData;
                        return [difficulty, rest];
                    })
                )
            }));
        } else {
            pipelinesToupdate = pipelines
            .filter(item => item.locked === false)
            .map(item => ({
                id: item.id,
                keywords: Object.fromEntries(
                    Object.entries(item.keywords).map(([difficulty, keywordData]) => {
                        /* Destructure to exclude serpItems */
                        const { serpItems, ...rest } = keywordData;
                        return [difficulty, rest];
                    })
                )
            }));
        }

        $.ajax({
            url: self.applyTriggerActionMultipleUrl,
            type: 'POST',
            data: {
                'store_id': self.storeId(),
                'record_id': self.recordId(),
                'entity_type': self.entityType,
                'difficulties': difficulties,
                'option': option,
                'value': value,
                'action': action,
                'text_types': textTypes,
                'pipelines': pipelinesToupdate
            },
            dataType: 'json',
            showLoader: false,
            success: function (response) {
                if (response.success) {
                    var optimizationData = keywordAnalysis.optimizationData();
                    var pipelines = optimizationData.pipelines;
                    var filtered = [];
                    if (includeLocked) {
                        filtered = pipelines;
                    } else {
                        filtered = pipelines.filter(item => item.locked === false)
                    }
                    filtered.forEach(pipeline => {
                        let updatedPipeline = response.api_response.find(item => item.id === pipeline.id);
                        if (updatedPipeline) {
                            for (let difficulty of difficulties) {
                                if (pipeline.triggers[difficulty] !== undefined) {
                                    pipeline.triggers[difficulty] = updatedPipeline.triggers[difficulty];
                                }
                            }
                        }
                    });
                    optimizationData.pipelines = pipelines;
                    keywordAnalysis.optimizationData(optimizationData);
                } else {
                    if (typeof response.error !== 'undefined') {
                        errorMessagesModel.messages.push(response.error);
                    }
                }
            }
        }).always(function () {
            $('#wtai-loader-' + pipelineId).removeClass('wtai-show');
            self.triggerUpdating(false);
        });
    }

    /**
     * Select trigger action
     *
     * @param {Object} self
     *
     * @returns {boolean}
     */
    function selectTriggerAction(self)
    {
        var countSelected = $(self.tsSelectors.checkedOption).length;
        self.tsActiveTriggerAction($(self.tsSelectors.checkedOption).val());
        return countSelected > 0;
    }

    /**
     * Apply trigger action
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function applyTriggerAction(self, pipelineId, difficulty)
    {
        $(self.tsSelectors.errorMessage).html('');

        var difficulties = [];

        var updatedValues = getUpdatedTriggerValues(self, pipelineId, difficulty);

        if (updatedValues.textTypes.length === 0 && self.tsActiveAutoOptimize() === 'auto_rewrite_and_queue') {
            $(self.tsSelectors.textFieldErrorMessage)
                .html(self.customValidationMessage
                    .replace(
                        '%s',
                        $t('You must select at least one text type when automatic text optimization is enabled.')
                    ));
            return;
        }

        difficulties.push(difficulty);

        self.closeDropdown($(self.tsSelectors.dropdownActive));

        applyTriggerActionRequest(
            self,
            pipelineId,
            difficulties,
            updatedValues.option,
            updatedValues.value,
            updatedValues.action,
            updatedValues.textTypes
        );
    }

    /**
     * Apply trigger action to the all triggers of pipeline
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function applyTriggerActionToPipeline(self, pipelineId, difficulty)
    {
        $(self.tsSelectors.errorMessage).html('');

        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);
        var triggers = pipeline.triggers;
        var difficulties = [];
        
        var updatedValues = getUpdatedTriggerValues(self, pipelineId, difficulty);

        if (updatedValues.textTypes.length === 0) {
            $(self.tsSelectors.textFieldErrorMessage)
            .html(self.customValidationMessage.replace('%s', $t('Please select at least one field')));
            return;
        }

        for (var key in triggers) {
            difficulties.push(key);
        }

        self.closeDropdown($(self.tsSelectors.dropdownActive));

        applyTriggerActionRequest(
            self,
            pipelineId,
            difficulties,
            updatedValues.option,
            updatedValues.value,
            updatedValues.action,
            updatedValues.textTypes
        );
    }

    /**
     * Apply trigger action to all triggers
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function applyTriggerActionToAll(
        self,
        pipelineId,
        difficulty
    ) {
        $(self.tsSelectors.errorMessage).html('');

        var difficulties = [];

        var updatedValues = getUpdatedTriggerValues(self, pipelineId, difficulty);

        if (updatedValues.textTypes.length === 0) {
            $(self.tsSelectors.textFieldErrorMessage)
                .html(self.customValidationMessage.replace('%s', $t('Please select at least one field')));
            return;
        }

        for (var i = 0; i < self.pipelineDifficulties.length; i++) {
            if (self.pipelineDifficulties[i] === 'High') {
                continue;
            }
            difficulties.push(self.pipelineDifficulties[i]);
        }

        self.closeDropdown($(self.tsSelectors.dropdownActive));

        applyMultipleTriggerActionRequest(
            self,
            pipelineId,
            difficulties,
            updatedValues.option,
            updatedValues.value,
            updatedValues.action,
            updatedValues.textTypes,
            true
        );
    }

    /**
     * Apply trigger action to same difficulty
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {void}
     */
    function applyTriggerActionToSameDifficulty(
        self,
        pipelineId,
        difficulty
    ) {
        $(self.tsSelectors.errorMessage).html('');

        var difficulties = [];
        
        var updatedValues = getUpdatedTriggerValues(self, pipelineId, difficulty);

        if (updatedValues.textTypes.length === 0) {
            $(self.tsSelectors.textFieldErrorMessage)
            .html(self.customValidationMessage.replace('%s', $t('Please select at least one field')));
            return;
        }

        difficulties.push(difficulty);

        self.closeDropdown($(self.tsSelectors.dropdownActive));

        applyMultipleTriggerActionRequest(
            self,
            pipelineId,
            difficulties,
            updatedValues.option,
            updatedValues.value,
            updatedValues.action,
            updatedValues.textTypes,
            true
        );
    }

    /**
     * Get updated trigger values
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {Object}
     */
    function getUpdatedTriggerValues(self, pipelineId, difficulty)
    {
        var textFieldMapping = self.textFieldMapping;
        var updatedValues = {};
        var option = $(self.tsSelectors.checkedOption).val();
        var value = 0;
        var action = $(self.tsSelectors.checkedAction).val();

        if (option === 'when_page_is_ranking') {
            value = $(self.tsSelectors.nPositionValue).val();
        } else {
            value = $(self.tsSelectors.nDaysValue).val();
        }

        var textTypes = [];
        $(self.tsSelectors.active + ' input[name="text_fields_'+pipelineId+difficulty+'"]:checked').each(function () {
            let textTypeEquivalent = textFieldMapping[$(this).val()];
            textTypes.push(textTypeEquivalent);
        });

        updatedValues['option'] = option;
        updatedValues['value'] = value;
        updatedValues['action'] = action;
        updatedValues['textTypes'] = textTypes;

        return updatedValues;
    }

    /**
     * Get trigger action n position value
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {number}
     */
    function getTriggerActionNPosition(self, pipelineId, difficulty)
    {
        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);

        if (!pipeline) {
            return 0;
        }

        let triggers = pipeline.triggers;

        if (triggers[difficulty] === undefined) {
            return 0;
        }

        if (triggers[difficulty].option === 'WhenRanking') {
            return triggers[difficulty].value;
        } else {
            return self['triggerActionNPosition'+difficulty];
        }
    }

    /**
     * Get trigger action n days value
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {number}
     */
    function getTriggerActionNDays(self, pipelineId, difficulty)
    {
        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);

        if (!pipeline) {
            return 0;
        }

        let triggers = pipeline.triggers;

        if (triggers[difficulty] === undefined) {
            return 0;
        }

        if (triggers[difficulty].option === 'AfterSetDays') {
            return triggers[difficulty].value;
        } else {
            return self['triggerActionNPosition'+difficulty];
        }
    }

    /**
     * Get trigger dropdown label
     *
     * @param {Object} self
     * @param {*} pipeline
     * @param {string} difficulty
     *
     * @returns {string}
     */
    function getTriggerDropdownLabel(self, pipelineId, difficulty)
    {
        var label = '';
        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);

        if (!pipeline) {
            return label;
        }

        let triggers = pipeline.triggers;

        if (triggers[difficulty] === undefined) {
            return label;
        }
        
        switch (triggers[difficulty].option) {
            case 'WhenRanking':
                label = $t('When page is ranking');
                break;
            case 'AfterSetDays':
                if (triggers[difficulty].value > 1) {
                    label = $t('After %s days').replace('%s', triggers[difficulty].value);
                } else {
                    label = $t('After %s day').replace('%s', triggers[difficulty].value);
                }
                break;
            case 'None':;
                label = $t('None');
                break;
            default:
                label = '';
                break;
        }
        
        return label;
    }

    /**
     * Is trigger action selected
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} option
     * @param {string} difficulty
     *
     * @returns {boolean}
     */
    function isTriggerActionSelected(self, pipelineId, option, difficulty)
    {
        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);

        if (!pipeline) {
            return false;
        }

        let triggers = pipeline.triggers;

        if (triggers[difficulty] === undefined) {
            return false;
        }

        return triggers[difficulty].option === option;
    }

    /**
     * Is text fields selected
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} field
     * @param {string} difficulty
     *
     * @returns {boolean}
     */
    function isTextFieldSelected(self, pipelineId, field, difficulty)
    {
        var textFieldMapping = self.textFieldMapping;
        var textEquivalent = textFieldMapping[field];

        var optimizationData = keywordAnalysis.optimizationData();
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);
        
        if (!pipeline) {
            return false;
        }

        let triggers = pipeline.triggers;

        if (triggers[difficulty] === undefined) {
            return false;
        }

        let textTypesFromApi =  triggers[difficulty].textTypes || [];
        return textTypesFromApi.includes(textEquivalent);
    }

    /**
     * Is all text fields selected
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {boolean}
     */
    function isAllTextFieldsSelected(self, pipelineId, difficulty)
    {
        return ko.pureComputed(function () {
            var optimizationData = keywordAnalysis.optimizationData();
            var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);
            
            if (!pipeline) {
                return false;
            }

            let triggers = pipeline.triggers;

            if (triggers[difficulty] === undefined) {
                return false;
            }
            let countAllTextFields = Object.keys(self.textFieldMapping).length;
            var textTypes = triggers[difficulty].textTypes || [];
            if (!self.isCustomOpenGraphEnabled) {
                /** remove open graph from textTypes if there is one */
                textTypes = textTypes.filter(textType => textType !== 'open graph text');
            }
            let countSelectedTextFields = textTypes.length;
            return countAllTextFields === countSelectedTextFields;
        });
    }

    /**
     * Is automatic text optimization selected
     *
     * @param {Object} self
     * @param {string} pipelineId
     * @param {string} action
     * @param {string} difficulty
     *
     * @returns {boolean}
     */
    function isAutomaticTextOptimizationSelected(self, pipelineId, action, difficulty)
    {
        let actionEquivalent = '';
        if (action === 'auto_rewrite_and_queue') {
            actionEquivalent = 'AutomaticRewrite';
        } else if (action === 'flag') {
            actionEquivalent = 'FlagForRewrite';
        } else if (action === 'auto_rewrite_and_transfer') {
            actionEquivalent = 'FullAutomation';
        }
        var optimizationData = keywordAnalysis.optimizationData();
        if (!optimizationData.pipelines) {
            return false;
        }
        var pipeline = optimizationData.pipelines.find(pipeline => pipeline.id === pipelineId);

        if (!pipeline) {
            return false;
        }

        let triggers = pipeline.triggers;

        if (triggers[difficulty] === undefined) {
            return false;
        }

        return triggers[difficulty].action === actionEquivalent;
    }

    /**
     * Action when user select a field
     *
     * @param {Object} self
     * @param {Object} data
     * @param {Object} event
     * @param {string} pipelineId
     * @param {string} difficulty
     *
     * @returns {boolean}
     */
    function selectTextField(self, data, event, pipelineId, difficulty)
    {
        var countAllTextFields = Object.keys(self.textFieldMapping).length;
        var selector = self.tsSelectors.active + ' input[name="text_fields_' + pipelineId + difficulty + '"]:checked';
        var countSelectedTextFields = $(selector).length;
        if (countAllTextFields === countSelectedTextFields) {
            $(self.tsSelectors.active + ' #wtaiAllTextFields' + pipelineId + difficulty).prop('checked', true);
        } else {
            $(self.tsSelectors.active + ' #wtaiAllTextFields' + pipelineId + difficulty).prop('checked', false);
        }
        return true;
    }

    /**
     * select all text fields
     *
     * @param {Object} self
     * @param {Object} data
     * @param {Object} event
     * @param {string} pipelineId
     * @param {string} difficulty
     */
    function selectAllFields(self, data, event, pipelineId, difficulty)
    {
        var isChecked = $(event.currentTarget).prop('checked');
        if (isChecked) {
            $(self.tsSelectors.active + ' input[name="text_fields_'+pipelineId+difficulty + '"]').prop('checked', true);
        } else {
            $(self.tsSelectors.active + ' input[name="text_fields_'+pipelineId+difficulty + '"]').prop('checked', false);
        }
        return true;
    }

    return {
        setActiveTriggerSettingsValue: setActiveTriggerSettingsValue,
        adjustPositionTriggerSettings: adjustPositionTriggerSettings,
        applyMultipleTriggerActionRequest: applyMultipleTriggerActionRequest,
        selectTriggerAction: selectTriggerAction,
        applyTriggerAction: applyTriggerAction,
        applyTriggerActionToPipeline: applyTriggerActionToPipeline,
        applyTriggerActionToAll: applyTriggerActionToAll,
        applyTriggerActionToSameDifficulty: applyTriggerActionToSameDifficulty,
        getUpdatedTriggerValues: getUpdatedTriggerValues,
        getTriggerActionNPosition: getTriggerActionNPosition,
        getTriggerActionNDays: getTriggerActionNDays,
        getTriggerDropdownLabel: getTriggerDropdownLabel,
        isTriggerActionSelected: isTriggerActionSelected,
        isTextFieldSelected: isTextFieldSelected,
        isAllTextFieldsSelected: isAllTextFieldsSelected,
        isAutomaticTextOptimizationSelected: isAutomaticTextOptimizationSelected,
        selectTextField: selectTextField,
        selectAllFields: selectAllFields
    }
});
