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

define([
    'underscore',
    'ko',
    'Magento_Ui/js/grid/listing',
    'WriteTextAI_WriteTextAI/js/model/grid/notifications',
    'WriteTextAI_WriteTextAI/js/model/grid/listing',
    'WriteTextAI_WriteTextAI/js/grid/reload',
    'WriteTextAI_WriteTextAI/js/categories/model/signalr',
    'WriteTextAI_WriteTextAI/js/model/edit/keywords/keyword-analysis',
    'WriteTextAI_WriteTextAI/js/model/grid/bulk-actions',
    'WriteTextAI_WriteTextAI/js/model/edit/generate/currently-generating'
], function (
    _,
    ko,
    Listing,
    notifications,
    listingModel,
    reloadGrid,
    signalRModel,
    keywordAnalysis,
    bulkActionsData,
    currentlyGeneratingModel
) {
    'use strict';

    return Listing.extend({
        defaults: {
            gridName: 'wtai_categories_grid_listing.wtai_categories_grid_listing_data_source',
            statusRunning: 'Running',
            statuses: [],
            lastTerminalReloadAt: 0,
            rowsDisabled: []
        },

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

            this.initObservableRowsDisabled();

            this.statuses(notifications.statuses());

            notifications.statuses.subscribe(function (statuses) {
                this.statuses(statuses);
            }, this);
        },

        /** @inheritdoc */
        initObservable: function () {
            this._super().observe(['statuses']);

            this.isGridLoading = ko.computed(function () {
                return bulkActionsData.getIsLoading('Category')();
            }, this);

            this.statuses.subscribe(function (statuses) {
                try {
                    var terminalStatuses = ['Completed', 'Failed', 'Cancelled', 'TimedOut'];
                    var hasTerminal = (statuses || []).some(function (status) {
                        if ((status.recordType || 'Product') !== 'Category') {
                            return false;
                        }
                        return terminalStatuses.includes(status.status);
                    });

                    if (!hasTerminal || typeof this.gridReload !== 'function') {
                        return;
                    }

                    var now = Date.now();
                    if (now - (this.lastTerminalReloadAt || 0) < 1500) {
                        return;
                    }
                    this.lastTerminalReloadAt = now;

                    this.gridReload();
                } catch (e) {
                    // no-op
                }
            }, this);

            return this;
        },

        /**
         * Initialize observables for disabling of rows.
         */
        initObservableRowsDisabled: function () {
            var observable = ko.getObservable(this, 'rows');

            var isDisabledByOtherUser = function (row) {
                try {
                    var currentEmail = '';
                    var currentUser = listingModel.currentUser && listingModel.currentUser();
                    if (currentUser && currentUser.email) {
                        currentEmail = String(currentUser.email);
                    }

                    var id = row.entity_id;
                    var storeId = row.store_id;

                    var terminal = ['Cancelled', 'Completed', 'Failed', 'TimedOut'];

                    var isOtherUserBulk = (notifications.statuses() || []).some(function (status) {
                        if (!status || terminal.indexOf(status.status) !== -1) {
                            return false;
                        }

                        if ((status.recordType || 'Product') !== 'Category') {
                            return false;
                        }

                        if (currentEmail && status.user && String(status.user) === currentEmail) {
                            return false;
                        }

                        return (status.queuedIds || []).indexOf(id) !== -1
                            || (status.runningIds || []).indexOf(id) !== -1
                            || (status.completedIds || []).indexOf(id) !== -1;
                    });

                    var isOtherUserSingle = (signalRModel.singleGeneratingStatuses() || []).some(function (status) {
                        if (!status || status.stop) {
                            return false;
                        }

                        if (String(status.generationType) !== 'Category') {
                            return false;
                        }

                        if (String(status.recordId) !== String(id) || String(status.storeId) !== String(storeId)) {
                            return false;
                        }

                        if (currentEmail && status.user && String(status.user) === currentEmail) {
                            return false;
                        }

                        return true;
                    });

                    return isOtherUserBulk || isOtherUserSingle;
                } catch (e) {
                    return false;
                }
            };

            observable.subscribe(function (rows) {
                _.each(
                    rows,
                    function (row) {
                        this.rowsDisabled[row.entity_id] = ko.observable(false);
                        this.rowsDisabled[row.entity_id].subscribe(
                            function (value) {
                                if (!value) {
                                    return;
                                }

                                if (!isDisabledByOtherUser(row)) {
                                    return;
                                }

                                try {
                                    var disabledRowIdsObservable = bulkActionsData.getDisabledRowIds('Category');
                                    var current = disabledRowIdsObservable() || [];
                                    var id = row.entity_id;

                                    if (current.indexOf(id) === -1) {
                                        disabledRowIdsObservable(current.concat([id]));
                                    }
                                } catch (e) {
                                    return;
                                }
                            },
                            this
                        );
                    },
                    this
                );
            }, this);
        },

        /**
         * Reload grid.
         */
        gridReload: function () {
            var showLoader = false,
                debounce = true;

            reloadGrid.reloadUIComponent(this.gridName, showLoader, debounce);
        },

        /**
         * Check if row is disabled.
         *
         * @param {Object} row
         * @returns {Boolean}
         */
        isRowDisabled: function (row) {
            return ko.computed(function () {
                try {
                    var isBulkGenerating = this.statuses().some((status) => {
                        if ((status.recordType || 'Product') !== 'Category') {
                            return false;
                        }
                        var isQueued =
                            (status.status === this.statusRunning || status.status === 'Pending' || status.status === 'Preparing') && (
                                status.queuedIds.indexOf(row.entity_id) !== -1 ||
                                status.runningIds.indexOf(row.entity_id) !== -1 ||
                                status.completedIds.indexOf(row.entity_id) !== -1
                            );

                        return isQueued;
                    }, this);

                    var isBulkCancelling = this.statuses().some((status) => {
                        if ((status.recordType || 'Product') !== 'Category') {
                            return false;
                        }
                        return (status.status === 'Cancelling' && (
                            status.queuedIds.indexOf(row.entity_id) !== -1 ||
                            status.runningIds.indexOf(row.entity_id) !== -1 ||
                            status.completedIds.indexOf(row.entity_id) !== -1
                        ));
                    }, this);

                    var isOtherUserSingleGenerating = signalRModel.singleGeneratingStatuses().some(function (status) {
                        return status.recordId == row.entity_id &&
                               status.storeId == row.store_id &&
                               status.generationType == 'Category' &&
                               !status.stop;
                    });

                    var currentlyGeneratingRecordIdentifiers = currentlyGeneratingModel.recordIdentifiers();
                    var categoryIdentifier = 'Category' + '_' + row.entity_id + '_' + row.store_id;
                    var isCurrentlyGenerating = currentlyGeneratingRecordIdentifiers.includes(categoryIdentifier);
                    var isCategoryOptimizationDataRunning = row.optimization_status === 'InProgress';
                    var isCategoryOptimizationDataQueued = row.optimization_status === 'Pending';

                    var isDisabled = isBulkGenerating
                        || isOtherUserSingleGenerating
                        || isBulkCancelling
                        || isCurrentlyGenerating
                        || isCategoryOptimizationDataRunning
                        || isCategoryOptimizationDataQueued;

                    this.rowsDisabled[row.entity_id](isDisabled);

                    return isDisabled;
                } catch (error) {
                    return false;
                }
            }, this);
        },

        /**
         * Check if row is optimizing.
         *
         * @param {Object} row
         * @returns {Boolean}
         */
        isRowOptimizing: function (row) {
            return ko.computed(function () {
                try {
                    var status = keywordAnalysis.statuses().find(function (status) {
                        return Number(status.storeId) === Number(row.store_id)
                        && status.recordId === row.entity_id
                        && status.status === 'Running'
                        && status.recordType === 'Category';
                    });
    
                    if (status) {
                        return true;
                    }

                    return false;
                } catch (error) {
                    return false;
                }
            }, this);
        }
    });
});
