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

define([
    'jquery',
    'uiComponent',
    'underscore',
    'ko',
    'mage/translate',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-pipelines',
    'WriteTextAI_WriteTextAI/js/edit/keywords/keyword-pipelines',
    "jquery/ui",
    "Magento_Theme/js/sortable",
    "wtaiJqueryUiTouchPunch",
    'mage/dropdown'
], function (
    $,
    Component,
    _,
    ko,
    $t,
    keywordAnalysis,
    keywordPipelines,
    keywordPipelinesComponent
) {
    'use strict';

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

    ko.bindingHandlers.aboveTheCenter = {
        update: function (element, valueAccessor) {
            var values = valueAccessor(),
            allKeywords = values.visibleKeywords();
            const container = $('.wtai-keyword-pool-container.wtai-with-data');
            const ulContainer = $('#wtaiKeywordPoolList');
            /** Function to check position and add/remove class */
            function updatePosition()
            {
                if (allKeywords.length > 0 && allKeywords.length < 21) {
                    let currentHeight = ulContainer[0].scrollHeight;
                    if (currentHeight < 173) {
                        $(container).addClass('wtai-two-lines');
                    } else {
                        if ($(container).attr('wtai-maxheight-set') === undefined) {
                            $(container).attr('wtai-maxheight-set', 'true');
                            $(container).css('max-height', currentHeight);
                            $(container).css('height', currentHeight);
                        }
                    }
                } else {
                    $(container).removeClass('wtai-two-lines');
                }
                const containerRect = container[0].getBoundingClientRect();
                const containerCenterY = containerRect.top + containerRect.height / 2;

                const elementRect = element.getBoundingClientRect();
                const elementCenterY = elementRect.top + elementRect.height / 2;

                /** Check if the element is above the container's center */
                if (elementCenterY < containerCenterY) {
                    $(element).addClass('wtai-above-the-center');
                } else {
                    $(element).removeClass('wtai-above-the-center');
                }

                /** Check if the element is within 20px of the far-right edge of the container */
                const distanceToRightEdge = containerRect.right - elementRect.right; /** Calculate distance to the right edge */

                if (distanceToRightEdge <= 240 && distanceToRightEdge >= 0) {
                    $(element).addClass('wtai-right-positioned');
                } else {
                    $(element).removeClass('wtai-right-positioned');
                }
            }
            /** Every update on visibleKeywords  */
            if (allKeywords.length !== 0) {
                setTimeout(() => {
                    updatePosition();
                }, 500);
            }
            /** Update position after scroll not during, to prevent lag */
            let scrollTimeout;
            let scrolling = false;

            ulContainer.on('scroll', function () {
                /** Throttle the update during scroll */
                if (!scrolling) {
                    scrolling = true;
                    requestAnimationFrame(() => {
                        updatePosition();
                        scrolling = false;
                    });
                }

                /** Debounce to trigger update after scroll stops */
                clearTimeout(scrollTimeout);
            });
        }
    };

    return Component.extend({
        defaults: {
            selectedDifficultyFilter: [],
            selectedVolumeFilter: '{"min": 0, "max": null}',
            defaultFilterBySearchVolume: '{"min": 0, "max": null}',
            selectors: {
                keywordPoolList: '#wtaiKeywordPoolList',
                keywordEditPipeline: '.wtai-pipeline-edit.wtai-keyword-edit-pipeline',
                keywordPoolDifficultyDialog: '#wtaiDifficultyFilterDialog',
                keywordPoolDifficultyDialogBtn: '.wtai-pool-action-btn.wtai-difficulty-btn',
                keywordPoolVolumeDialog: '#wtaiVolumeFilterDialog',
                keywordPoolVolumeDialogBtn: '.wtai-pool-action-btn.wtai-volume-btn',
                keywordEmptyPipeline: '.wtai-custom-pipeline-empty'
            },
            classes: {
                keywordPoolPlaceholder: 'wtai-keyword-pool-placeholder'
            },
            initialNumberOfKeywordsVisible: 20,
            maxNumberOfKeywordPipeline: 6,
            loadMoreCount: 30,
            visibleKeywords: [],
            difficulties: [],
            sortableStateEnabled: true,
            isEditPipelineVisible: false,
            currentNumberOfPipelines: 0,
            refreshingData: false
        },

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

            self = this;

            this.keywordPoolItems.subscribe(function () {
                this.getInitialKeywords();
            }, this);

            this.sortableStateEnabled.subscribe(function (sortableStateEnabled) {
                if (sortableStateEnabled) {
                    $(self.selectors.keywordPoolList).sortable("enable");
                } else {
                    $(self.selectors.keywordPoolList).sortable("disable");
                }
            });

            keywordPipelines.editKeywordPipelineVisible.subscribe(function (editKeywordPipelineVisible) {
                self.isEditPipelineVisible = editKeywordPipelineVisible;
            });

            keywordAnalysis.historyMode.subscribe(function (historyMode) {
                if (historyMode) {
                    self.sortableStateEnabled(false);
                } else {
                    self.sortableStateEnabled(true);
                }
            });

            keywordAnalysis.optimizationData.subscribe(function (optimizationData) {
                if (optimizationData.pipelines) {
                    self.currentNumberOfPipelines = optimizationData.pipelines.length;
                }
            });

            keywordAnalysis.refreshingData.subscribe(function (refreshingData) {
                this.refreshingData(refreshingData);
            }, this);
            
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe([
                'selectedVolumeFilter',
                'selectedDifficultyFilter',
                'initialNumberOfKeywordsVisible',
                'loadMoreCount',
                'visibleKeywords',
                'difficulties',
                'sortableStateEnabled',
                'refreshingData'
            ]);

            this.keywordPoolItems = ko.computed(function () {
                if (keywordAnalysis.optimizationData().keywords === undefined) {
                    return [];
                }

                var filtered = keywordAnalysis.optimizationData().keywords.filter(function (keyword) {
                    return this.filterKeywords(keyword);
                }, this);

                /** Remove duplicate keywords */
                var filtered = filtered.filter(
                    (keyword, index, self) =>
                    index === self.findIndex(k => k.keyword.toLowerCase() === keyword.keyword.toLowerCase())
                );

                /** Get keywords from pipelines */
                var keywordsFromPipelines = keywordAnalysis.optimizationData().pipelines
                .filter(function (pipeline) {
                    if (keywordPipelines.editKeywordPipelineVisible() === true) {
                        if (keywordPipelines.editKeywordPipeline().id === pipeline.id) {
                            return false;
                        }
                    }
                    return true;
                }).map(function (pipeline) {
                    return Object.values(pipeline.keywords).map(function (keywordObj) {
                        return keywordObj.keyword;
                    });
                }).flat();

                /** Get keywords from ranking */
                var keywordsFromRanking = keywordAnalysis.optimizationData().rankingKeywords.map(function (keyword) {
                    return keyword.keyword;
                });
                if (keywordAnalysis.editKeywordRankingVisible() === true) {
                    keywordsFromRanking = keywordAnalysis.editKeywordRankingItems().filter(function (keyword) {
                        return keyword.removed !== true;
                    }).map(function (keyword) {
                        return keyword.keyword;
                    });
                }

                /** Filter out keywords from pipelines */
                var pipelinesFiltered = filtered.filter(function (keyword) {
                    return !keywordsFromPipelines.some(k => k.toLowerCase() === keyword.keyword.toLowerCase());
                });

                /** Filter out keywords from ranking */
                var pipelinesFiltered = pipelinesFiltered.filter(function (keyword) {
                    return !keywordsFromRanking.some(k => k.toLowerCase() === keyword.keyword.toLowerCase());
                });
                
                if (keywordPipelines.editKeywordPipeline().keywords !== undefined) {
                    var keywordsFromEdit = Object.values(keywordPipelines.editKeywordPipeline().keywords).map(function (keywordObj) {
                        return keywordObj.keyword;
                    });
                    var finalArr = pipelinesFiltered.filter(function (keyword) {
                        return !keywordsFromEdit.some(editKeyword => {
                            var editKeywordLower = editKeyword ? editKeyword.toLowerCase() : '';
                            var keywordLower = keyword.keyword ? keyword.keyword.toLowerCase() : '';
                            return editKeywordLower === keywordLower;
                        });
                    });

                    return this.sortBySearchVolume(finalArr);
                }

                if (keywordAnalysis.editKeywordRankingVisible() && keywordAnalysis.editKeywordRankingItems().length > 0) {
                    var keywordsFromRanking = keywordAnalysis.editKeywordRankingItems().filter(function (keyword) {
                        return keyword.removed !== true;
                    }).map(function (keyword) {
                        return keyword.keyword;
                    });

                    var finalArr = pipelinesFiltered.filter(function (keyword) {
                        return !keywordsFromRanking.some(k => {
                            var kLower = k ? k.toLowerCase() : '';
                            var keywordLower = keyword.keyword ? keyword.keyword.toLowerCase() : '';
                            return kLower === keywordLower;
                        });
                    });

                    return this.sortBySearchVolume(finalArr);
                }
                
                return this.sortBySearchVolume(pipelinesFiltered);
            }, this);

            this.filterDifficultyLabel = ko.computed(function () {
                var filter = this.selectedDifficultyFilter();

                if (Array.isArray(filter) &&
                    (filter.length === 5 || filter.length === 0)) {
                    return $t('All difficulty');
                }
                if (Array.isArray(filter)) {
                    return $t('%s selected').replace('%s', filter.length);
                }

                return '';
            }, this);

            this.filterVolumeLabel = ko.computed(function () {
                var filter = JSON.parse(this.selectedVolumeFilter());
                if (filter.min === 0 && filter.max === null) {
                    return $t('All search volume');
                }
                return $t('%s selected').replace('%s', 1);

            }, this);

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

            this.isHistoryMode = ko.computed(function () {
                return keywordAnalysis.historyMode();
            });

            this.getPrimaryKeyword = ko.computed(function () {
                if (keywordAnalysis.optimizationData() &&
                    keywordAnalysis.optimizationData().optimizingKeywords &&
                    keywordAnalysis.optimizationData().optimizingKeywords.length > 0) {
                    return keywordAnalysis.optimizationData().optimizingKeywords[0];
                }
                return null;
            }, this);

            return this;
        },

        /**
         * Initialize sortable.
         */
        initSortable: function () {
            $(this.selectors.keywordPoolList).sortable({
                tolerance: 'pointer',
                items: 'li',
                revert: true,
                scroll: true,
                placeholder: this.classes.keywordPoolPlaceholder,
                connectWith: "#wtaiKeywordEditPipeline",
                sort: function (event, ui) {
                    /** scroll to top if the item is near the top of the container */
                    const customScrollParent = $('.wtai-edit-keyword-analysis .modal-content');
                    const itemTop = ui.helper.offset().top;
                    const parentOffset = customScrollParent.offset();
                    const scrollTop = customScrollParent.scrollTop();
                    if (self.sortableStateEnabled()) {
                        if (itemTop < parentOffset.top + 20) {
                            customScrollParent.scrollTop(scrollTop - 10);
                        }
                    }
                },
                out: function (event, ui) {
                    /** ui.item.addClass('wtai-not-allowed'); **/
                },
                over: function (event, ui) {
                    /** force to move the placehoder back to the item being dragged */
                    ui.helper.after(ui.placeholder);
                    
                    ui.item.addClass('wtai-not-allowed');
                },
                start: function (event, ui) {
                    keywordPipelines.preventInputBlur(true);
                    $('.wtai-edit-keyword-item.wtai-input-active:not(.wtai-saving-keyword)').find('.admin__control-text').blur();
                    if (self.currentNumberOfPipelines >= self.maxNumberOfKeywordPipeline && !self.isEditPipelineVisible) {
                        setTimeout(() => {
                            $('.wtai-keyword-pool-container.wtai-with-data').addClass('wtai-show-tooltip');
                            $(this).sortable("option", "revert", false);
                            $(this).sortable("cancel");
                        }, 10);
                    }

                    ui.item.addClass("wtai-dragging");
                    $(this).sortable("option", "items", "li.wtai-dragging");
                    $(this).sortable("refresh");
                    keywordPipelines.forceNewPipeline(true);
                    keywordPipelines.forceNewPipeline.valueHasMutated();
                    $(self.selectors.keywordEditPipeline).sortable("refresh");
                    /*if ($('.wtai-edit-pipeline-container').length > 0) {
                        $('.wtai-edit-pipeline-container')[0].scrollIntoView({behavior: 'smooth', block: 'start'});
                    }*/
                },
                stop: function (event, ui) {
                    ui.item.removeClass("wtai-dragging");
                    $(this).sortable("option", "items", "li");
                    $(this).sortable("refresh");
                    keywordPipelines.forceNewPipeline(false);
                    keywordPipelines.forceNewPipeline.valueHasMutated();
                }
            });
        },

        /**
         * Initialize dropdown dialogs.
         */
        initDropdownDialogs: function () {
            $(this.selectors.keywordPoolDifficultyDialogBtn).dropdown({
                parent: '.wtai-difficulty-filter',
                autoclose: true
            }).on('click.toggleDropdown', function () {
                self.closeDropdown($(self.selectors.keywordPoolVolumeDialogBtn));
            });
            $(this.selectors.keywordPoolVolumeDialogBtn).dropdown({
                parent: '.wtai-search-volume-filter',
                autoclose: true
            }).on('click.toggleDropdown', function () {
                self.closeDropdown($(self.selectors.keywordPoolDifficultyDialogBtn));
            });
            
                
            $(document).on('click', function (event) {
                const $dropdownDifficulty = $(self.selectors.keywordPoolDifficultyDialogBtn).closest('.wtai-difficulty-filter.active');
                const isClickInsideDifficulty = $dropdownDifficulty.is(event.target) || $dropdownDifficulty.has(event.target).length > 0;

                const $dropdownVolume = $(self.selectors.keywordPoolVolumeDialogBtn).closest('.wtai-search-volume-filter.active');
                const isClickInsideVolume = $dropdownVolume.is(event.target) || $dropdownVolume.has(event.target).length > 0;

                if (!isClickInsideDifficulty) {
                    self.closeDropdown($(self.selectors.keywordPoolDifficultyDialogBtn));
                }

                if (!isClickInsideVolume) {
                    self.closeDropdown($(self.selectors.keywordPoolVolumeDialogBtn));
                }
            });
        },

        /**
         * Initialize pool disable action.
         */
        initPoolDisableAction: function () {
            $(document).on('click', function () {
                self.closePoolTooltip();
            });
        },

        /**
         * Initialize resize.
         */
        initResize: function () {
            var resizeTimer;
            $(window).on('resize', function () {
                clearTimeout(resizeTimer);
                resizeTimer = setTimeout(function () {
                    self.visibleKeywords.valueHasMutated();
                }, 300);
            });
        },

        /**
         * After render
         */
        afterRender: function () {
            self.initSortable();
            self.initDropdownDialogs();
            self.initPoolDisableAction();
            self.initResize();
        },

        /**
         * Get initial keywords.
         */
        getInitialKeywords: function () {
            var initialKeywords = self.keywordPoolItems().slice(0, self.initialNumberOfKeywordsVisible());
            self.visibleKeywords(initialKeywords);
        },

        /**
         * Add keyword to keyword pool.
         */
        loadMore: function () {
            $('.wtai-keyword-pool-container.wtai-with-data').attr('wtai-maxheight-set', 'true');
            var visibleKeywords = self.visibleKeywords();
            var newKeywords = self.keywordPoolItems().slice(
                visibleKeywords.length,
                visibleKeywords.length + self.loadMoreCount()
            );
            self.initialNumberOfKeywordsVisible(visibleKeywords.length + self.loadMoreCount());
            self.visibleKeywords(visibleKeywords.concat(newKeywords));
        },

        /**
         * Get difficulty in text.
         *
         * @param {int} difficulty
         * @returns {string}
         */
        getDifficulty: function (difficulty) {
            if (!this.ranges()) {
                return '';
            }
            
            var range = this.ranges().find(function (range) {
                return difficulty >= range.min && difficulty <= range.max;
            });

            if (!range) {
                return difficulty;
            }

            return range.type;
        },

        /**
         * Get formatted difficulty.
         *
         * @param {string} difficulty
         * @returns {string}
         */
        getFormattedDifficulty: function (difficulty) {
            var difficulty = this.getDifficulty(difficulty);
            switch (difficulty) {
                case 'High':
                    return $t('HIGH');
                case 'MidHigh':
                    return $t('MID HIGH');
                case 'Mid':
                    return $t('MID');
                case 'LowMid':
                    return $t('LOW MID');
                case 'Low':
                    return $t('LOW');
                default:
                    return difficulty;
            }
        },

        /**
         * Filter keywords
         *
         * @param {array} keyword
         *
         * return boolean
         */
        filterKeywords: function (keyword) {
            var difficulty = this.getDifficulty(keyword.difficulty);
            var volume = keyword.searchVolume;
            var filterBySearchVolume = JSON.parse(this.selectedVolumeFilter());
            var filterByDifficulty = this.selectedDifficultyFilter();
            var isFilteredBySearchVolume = volume >= filterBySearchVolume.min && (
                filterBySearchVolume.max === null || volume <= filterBySearchVolume.max
            );
            var isFilteredByDifficulty = true;
            if (filterByDifficulty.length > 0) {
                isFilteredByDifficulty = filterByDifficulty.includes(difficulty);
            }

            return isFilteredBySearchVolume && isFilteredByDifficulty;
        },

        /**
         * Sot keyword by search volume.
         *
         * @param {array} keywords
         *
         * @returns {array}
         */
        sortBySearchVolume: function (keywords) {
            /** Filter out manual: true items and sort the remaining ones */
            var sortedData = keywords
                .sort((a, b) => {
                    if (a.isSeed && !b.isSeed) {
                        return -1; /** a goes before b */
                    }                    if (!a.isSeed && b.isSeed) {
                        return 1;  /** b goes before a */
                    }
                    /** Handle items with missing or null searchVolume */
                    var aVolume = a.searchVolume ?? -1; /** Default to -1 if missing or null */
                    var bVolume = b.searchVolume ?? -1; /** Default to -1 if missing or null */
                    if (aVolume === -1) {
                        return 1; /** Place items with missing/null searchVolume at the end */
                    }                    if (bVolume === -1) {
                        return -1;
                    }

                    var aRangeDifficulty = self.getDifficulty(a.difficulty);
                    var bRangeDifficulty = self.getDifficulty(b.difficulty);

                    /** Sort by searchVolume in descending order */
                    if (bVolume !== aVolume) {
                        return bVolume - aVolume;
                    }

                    /** Sort by difficulty in descending order */
                    if (bRangeDifficulty !== aRangeDifficulty) {
                        return bRangeDifficulty - aRangeDifficulty;
                    }

                    /** Sort by keyword length in ascending order */
                    if (a.keyword.length !== b.keyword.length) {
                        return a.keyword.length - b.keyword.length;
                    }

                    /** Sort alphabetically in ascending order */
                    return a.keyword.localeCompare(b.keyword);
                });
            return sortedData;
        },
        
        /**
         * Manually close dropdown
         *
         * @param {*} elem
         */
        closeDropdown: function (elem) {
            self.closePoolTooltip();
            elem.removeClass('active')
                .parent()
                    .removeClass('active');
        },

        /**
         * Close pool tooltip
         */
        closePoolTooltip: function () {
            $(self.selectors.keywordPoolList).sortable("option", "revert", true);
            $('.wtai-keyword-pool-container.wtai-with-data').removeClass('wtai-show-tooltip');
        },

        /**
         * Is primary keyword
         *
         * @param {string} keyword
         *
         * @returns {boolean}
         */
        isPrimaryKeyword: function (keyword) {
            return self.getPrimaryKeyword() === keyword;
        }
    });
});
