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

define([
    'jquery',
    'underscore',
    'WriteTextAI_WriteTextAI/js/model/grid/upload-images',
    'WriteTextAI_WriteTextAI/js/model/grid/reference-products',
    'WriteTextAI_WriteTextAI/js/model/grid/error-messages',
    'WriteTextAI_WriteTextAI/js/model/gallery',
    'WriteTextAI_WriteTextAI/js/model/grid/listing',
    'WriteTextAI_WriteTextAI/js/model/grid/invalid-image-popup',
    'WriteTextAI_WriteTextAI/js/model/grid/keyword-invalid-image-popup',
    'WriteTextAI_WriteTextAI/js/model/grid/popups/image-upload-progressbar',
    'WriteTextAI_WriteTextAI/js/utils/grid/actions'
], function (
    $,
    _,
    uploadImagesModel,
    referenceProducts,
    errorMessagesModel,
    galleryModel,
    listingModel,
    gridInvalidImagePopupModel,
    keywordInvalidImagePopupModel,
    imageUploadProgressbarModel,
    actionsUtils
) {
    'use strict';

    /** Track current AJAX request state */
    var currentAjaxRequest = null;
    var currentRequestData = null;
    var isRequestPending = false;
    var visibilityChangeHandler = null;
    var alreadyOnCallback = false;

    /**
     * Initialize page visibility detection for AJAX retry
     */
    function initVisibilityDetection()
    {
        /** Remove any existing handler to prevent duplicates */
        if (visibilityChangeHandler) {
            document.removeEventListener('visibilitychange', visibilityChangeHandler);
        }

        /** Create new visibility change handler */
        visibilityChangeHandler = function () {
            if (!document.hidden && isRequestPending && currentRequestData && !alreadyOnCallback) {
                console.log('Page became visible, retrying interrupted upload request...');
                
                /** Retry the current request */
                var data = currentRequestData;
                uploadRequest(
                    data.self,
                    data.action,
                    data.data,
                    data.settings,
                    data.imageChunks,
                    data.index,
                    data.callback
                );
            }
        };

        /** Add visibility change listener */
        document.addEventListener('visibilitychange', visibilityChangeHandler);
    }

    /**
     * Clean up visibility detection
     */
    function cleanupVisibilityDetection()
    {
        if (visibilityChangeHandler) {
            document.removeEventListener('visibilitychange', visibilityChangeHandler);
            visibilityChangeHandler = null;
        }
        currentAjaxRequest = null;
        currentRequestData = null;
        isRequestPending = false;
    }

    /**
     * Main function for uploading images
     *
     * @param {Object} self - Self data.
     * @param {Object} action - Action data.
     * @param {Object} data - Selections data.
     * @param {Object} settings - Form settings.
     * @param {String} callback - Callback function name to call after upload ('bulkGenerateRequest' or 'bulkKeywordAnalysisRequest').
     *
     * @returns {void}
     */
    function uploadImages(self, action, data, settings, callback = 'bulkGenerateRequest')
    {
        if (imageUploadProgressbarModel.toCancel()) {
            galleryModel.productsUploading([]);
            imageUploadProgressbarModel.visible(false);
            cleanupVisibilityDetection();
            return;
        }

        /** Initialize visibility detection for this upload session */
        initVisibilityDetection();
        
        imageUploadProgressbarModel.visible(true);
        imageUploadProgressbarModel.toCancel(false);
        imageUploadProgressbarModel.total(0);
        imageUploadProgressbarModel.progress(0);

        if (callback === 'bulkKeywordAnalysisRequest') {
            imageUploadProgressbarModel.isKeywordAnalysis(true);
        } else {
            imageUploadProgressbarModel.isKeywordAnalysis(false);
        }
        
        getImages(self, action, data, settings, callback);
    }

    /**
     * Get alt text images to upload
     *
     * @param {Object} self - Self data.
     * @param {Object} action - Action data.
     * @param {Object} data - Selections data.
     * @param {Object} settings - Form settings.
     *
     * @returns {void}
     */
    function getImages(self, action, data, settings, callback)
    {
        var selections = actionsUtils.processSelections(data, settings, self.defaultStoreId);

        $.ajax({
            url: self.getImagesUrl,
            type: 'POST',
            data: selections,
            dataType: 'json',
            showLoader: false,
            success: function (response) {
                if (!response.success) {
                    errorMessagesModel.messages.push(response.message);
                    if (response.unauthorized) {
                        window.location.href = response.login_url;
                    }
                    if (response.reload) {
                        self.gridReload();
                    }
                    imageUploadProgressbarModel.visible(false);
                } else {
                    prepareChunks(self, action, data, settings, response.images, callback);
                }
            }
        });
    }

    /**
     * Prepare alt text images for upload (batch upload)
     *
     * @param {Object} self - Self data.
     * @param {Object} action - Action data.
     * @param {Object} data - Selections data.
     * @param {Object} settings - Form settings.
     * @param {Array} productImages - Array of images.
     *
     * @returns {void}
     */
    function prepareChunks(self, action, data, settings, productImages, callback)
    {
        var ids = listingModel.ids(); /** Get ids of products in grid with/without filter */
        var selectedProductImages = Object.keys(productImages)
            .filter(productId => {
                if (data.excludeMode) {
                    return ids.includes(productId) && !data.excluded.includes(productId);
                } else {
                    return ids.includes(productId) && data.selected.includes(productId);
                }
            })
            .flatMap(productId => productImages[productId].split(',').map(image => ({
                image: image,
                entityId: productId
            })));

        imageUploadProgressbarModel.total(selectedProductImages.length);

        /** Split images into chunks of 10 */
        var imageChunks = [];
        for (var i = 0; i < selectedProductImages.length; i += 10) {
            imageChunks.push(selectedProductImages.slice(i, i + 10));
        }

        galleryModel.productsUploading(data.selected);
        uploadImagesModel.failedImages([]);
        uploadImagesModel.failedImageIds([]);
        uploadImagesModel.successImages([]);
        uploadImagesModel.invalid([]);
        uploadImagesModel.notSupported([]);
        uploadImagesModel.downloadFailed([]);
        uploadImagesModel.general([]);
        uploadImagesModel.errorMessages([]);

        /** Start uploading the first chunk */
        uploadRequest(self, action, data, settings, imageChunks, 0, callback);
    }
    
    /**
     * AJAX request for uploading alt text images
     *
     * @param {Object} self - Self data.
     * @param {Object} action - Action data.
     * @param {Object} data - Selections data.
     * @param {Object} settings - Form settings.
     * @param {Array} imageChunks - Array of image chunks.
     * @param {Number} index - Index of the current chunk.
     *
     * @returns {void}
     */
    function uploadRequest(self, action, data, settings, imageChunks, index, callback)
    {
        if (imageUploadProgressbarModel.toCancel()) {
            galleryModel.productsUploading([]);
            imageUploadProgressbarModel.visible(false);
            cleanupVisibilityDetection();
            return;
        }

        var errorMessages = uploadImagesModel.errorMessages();
        if (index < imageChunks.length) {
            /** Abort any existing request before starting a new one */
            if (currentAjaxRequest && currentAjaxRequest.readyState !== 4) {
                currentAjaxRequest.abort();
            }

            /** Store request data for potential retry */
            currentRequestData = {
                self: self,
                action: action,
                data: data,
                settings: settings,
                imageChunks: imageChunks,
                index: index,
                callback: callback
            };
            isRequestPending = true;

            currentAjaxRequest = $.ajax({
                url: self.uploadImagesUrl,
                type: 'POST',
                data: {
                    images: imageChunks[index],
                    store_id: referenceProducts.storeId()
                },
                dataType: 'json',
                global: false,
                showLoader: false
            }).done(function (response) {
                /** Clear request tracking on success */
                isRequestPending = false;
                currentAjaxRequest = null;
                currentRequestData = null;

                if (!response.success) {
                    imageUploadProgressbarModel.visible(false);
                    errorMessagesModel.messages.push(response.message);
                    cleanupVisibilityDetection();
                    
                    if (response.unauthorized) {
                        window.location.href = response.login_url;
                    }
                } else {
                    imageUploadProgressbarModel.progress(
                        imageChunks
                            .slice(0, index + 1)
                            .reduce((total, chunk) => total + chunk.length, 0)
                    );

                    uploadImagesModel.failedImages.push(...response.failed_images);
                    uploadImagesModel.failedImageIds.push(...response.failed_image_ids);
                    uploadImagesModel.successImages.push(...response.success_images);
                    uploadImagesModel.invalid.push(...response.invalid);
                    uploadImagesModel.notSupported.push(...response.not_supported);
                    uploadImagesModel.downloadFailed.push(...response.download_failed);
                    uploadImagesModel.general.push(...response.general);
                    uploadImagesModel.errorMessages({...errorMessages, ...response.error_messages});
                        

                    /** Upload next chunk */
                    uploadRequest(self, action, data, settings, imageChunks, index + 1, callback);
                }
            }).fail(function (jqXHR, textStatus, errorThrown) {
                /** Don't clear request data on failure if page is hidden (could be due to screen lock) */
                if (document.hidden) {
                    /** Page is hidden, keep request data for retry when page becomes visible */
                    console.log('Upload request interrupted while page hidden, will retry when visible');
                    return;
                }

                isRequestPending = false;
                currentAjaxRequest = null;

                if (textStatus === 'abort' || imageUploadProgressbarModel.toCancel()) {
                    cleanupVisibilityDetection();
                    galleryModel.productsUploading([]);
                    imageUploadProgressbarModel.visible(false);
                    return;
                }

                currentRequestData = null;
                errorMessagesModel.messages.push('Upload request failed. Please try again.');
                imageUploadProgressbarModel.visible(false);
                cleanupVisibilityDetection();
            });
        } else {
            /** All chunks uploaded, clean up */
            cleanupVisibilityDetection();
            galleryModel.productsUploading([]);
            imageUploadProgressbarModel.visible(false);

            data.params.uploaded_images = [...uploadImagesModel.successImages()];
            alreadyOnCallback = true;
            if (validateInvalidImages()) {
                self[callback](self, action, data, settings);
            } else {
                if (callback === 'bulkKeywordAnalysisRequest') {
                    keywordInvalidImagePopupModel.self(self);
                    keywordInvalidImagePopupModel.action(action);
                    keywordInvalidImagePopupModel.data(data);
                    keywordInvalidImagePopupModel.settings(settings);
                    $('.wtai-grid-keyword-invalid-image-popup').modal('openModal');
                } else {
                    gridInvalidImagePopupModel.data(data);
                    gridInvalidImagePopupModel.settings(settings);
                    if (callback === 'fullAutomationRequest') {
                        gridInvalidImagePopupModel.isFullAutomationRequest(true);
                    } else {
                        gridInvalidImagePopupModel.isFullAutomationRequest(false);
                    }
                    $('.wtai-grid-invalid-image-popup').modal('openModal');
                }
            }
        }
    }

    /**
     * Validate invalid images
     */
    function validateInvalidImages()
    {
        var failedImages = uploadImagesModel.failedImages();

        return failedImages.length === 0;
    }

    return {
        uploadImages: uploadImages
    };
});
