// ==UserScript==
// @name         Add Buttons to Xiuren
// @namespace    http://tampermonkey.net/
// @version      2.3
// @description  Add custom buttons to each index_selected_box anchor in the Xiuren website for parallel downloads, ensuring valid image files only
// @author       Your Name
// @match        https://xiuren.mobi/*
// @grant        none
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/FileSaver.js/2.0.5/FileSaver.min.js
// ==/UserScript==

(function() {
    'use strict';

    function createButtons() {
        const targetDivs = document.querySelectorAll('div.index_selected_warp div.index_selected_box a');

        if (targetDivs.length > 0) {
            console.log(`Found ${targetDivs.length} target divs.`);

            targetDivs.forEach((targetDiv) => {
                const downloadButton = document.createElement('button');
                downloadButton.className = 'download-button';
                downloadButton.innerText = 'Download';
                downloadButton.style.cssText = `
                    font-size: 8px;
                    position: absolute;
                    background-color: #336699;
                    border: 1px solid #f92672;
                    border-radius: 3px;
                    padding: 2px;
                    color: white;
                    z-index: 10;
                    cursor: pointer;
                    opacity: 0.9;
                `;
                downloadButton.addEventListener('click', function() {
                    const imgElement = targetDiv.querySelector('img.lazy.index_selected_img.img-responsive');
                    const textElement = targetDiv.parentElement.querySelector('div.index_selected_text');
                    if (imgElement && textElement) {
                        const imageUrl = imgElement.dataset.src || imgElement.src;
                        const issueMatch = imageUrl.match(/\/(\d{5,8})\//);
                        if (!issueMatch) {
                            console.error('Issue number not found in image URL.');
                            return;
                        }
                        const issue = issueMatch[1];
                        const alt = imgElement.alt;
                        detectActualTotalImages(imageUrl, issue, alt);
                    } else {
                        console.error('Required elements not found.');
                    }
                });

                const parentDiv = targetDiv.parentElement;
                const parentRect = parentDiv.getBoundingClientRect();
                downloadButton.style.top = `${parentRect.height + 5}px`;
                downloadButton.style.right = '2px';

                parentDiv.appendChild(downloadButton);
            });
        } else {
            console.error('No target divs found!');
        }
    }

    async function fetchImageThroughWorker(url) {
        try {
            console.log(`Fetching image from ${url}`);
            const proxyUrl = `https://xiuren.maestro1four1.workers.dev/?url=${encodeURIComponent(url)}`;
            const response = await fetch(proxyUrl);
            if (response.ok) {
                const blob = await response.blob();
                if (blob.size > 100) {
                    console.log(`Successfully fetched image from ${url}`);
                    return blob;
                } else {
                    console.warn(`Received empty or small blob from ${url}`);
                    return null;
                }
            } else {
                console.warn(`Failed response for ${url}: ${response.statusText}`);
                return null;
            }
        } catch (error) {
            console.error(`Error fetching from ${url}:`, error);
            return null;
        }
    }

    async function detectActualTotalImages(baseImageUrl, issue, alt) {
        if (!baseImageUrl || !issue) {
            console.error('Invalid image URL or issue number.');
            return;
        }

        const baseDir = baseImageUrl.match(/https:\/\/.*\/(\d{4})\//)[0];
        let actualTotalImages = 0;

        // Prepare an array of image URLs to check
        const imageUrls = [];
        for (let index = 1; index <= 99; index++) {
            const imageIndex = index.toString().padStart(2, '0');
            const imageUrlWithIndex = `${baseDir}${issue}/${issue}${imageIndex}.jpg`;
            imageUrls.push(imageUrlWithIndex);
        }

        // Initialize an array of promises to test which images actually exist
        const checkPromises = imageUrls.map(url => fetchImageThroughWorker(url).then(blob => !!blob));

        // Await all checks to complete
        const checkResults = await Promise.all(checkPromises);

        // Count how many images returned a valid blob
        actualTotalImages = checkResults.reduce((count, valid) => valid ? count + 1 : count, 0);

        // Alert the user with the actual number of images
        alert(`Detected ${actualTotalImages} valid images for download.`);

        if (actualTotalImages > 0) {
            console.log(`Found ${actualTotalImages} valid images for issue: ${issue}`);
            downloadImagesInParallel(baseImageUrl, issue, alt, actualTotalImages);
        } else {
            console.warn(`No valid images found for issue: ${issue}`);
        }
    }

    async function downloadImagesInParallel(baseImageUrl, issue, alt, totalImages) {
        if (!baseImageUrl || !issue) {
            console.error('Invalid image URL or issue number.');
            return;
        }

        const baseDir = baseImageUrl.match(/https:\/\/.*\/(\d{4})\//)[0];
        const zip = new JSZip();

        const imageUrls = [`${baseDir}${issue}/cover.jpg`]; // Start with the cover image
        for (let index = 1; index <= totalImages; index++) {
            const imageIndex = index.toString().padStart(2, '0');
            const imageUrlWithIndex = `${baseDir}${issue}/${issue}${imageIndex}.jpg`;
            imageUrls.push(imageUrlWithIndex);
        }

        const CONCURRENT_DOWNLOADS = 100;
        let index = 0;
        let downloadedCount = 0;

        while (index < imageUrls.length) {
            const batch = imageUrls.slice(index, index + CONCURRENT_DOWNLOADS).map(url => fetchImageThroughWorker(url));
            const results = await Promise.allSettled(batch);

            results.forEach((result, resultIndex) => {
                if (result.status === 'fulfilled' && result.value) {
                    const imageFileName = index + resultIndex === 0 ? `${issue}00.jpg` : `${issue}${(index + resultIndex).toString().padStart(2, '0')}.jpg`;
                    zip.file(imageFileName, result.value);
                    downloadedCount++;
                    console.log(`Added ${imageFileName} to zip. Total downloaded: ${downloadedCount}`);
                } else {
                    console.warn(`Image from batch index ${index + resultIndex} not included: ${result.reason || 'Failed to fetch'}`);
                }
            });

            index += CONCURRENT_DOWNLOADS;
        }

        console.log(`Downloaded ${downloadedCount} images, starting zip generation...`);

        try {
            if (Object.keys(zip.files).length > 0) {
                console.log('Generating zip file...');
                const zipContent = await zip.generateAsync({ type: "blob" });
                saveAs(zipContent, `${alt || issue}.zip`);
                console.log('Zip file created and downloaded successfully.');
            } else {
                console.warn('No valid images were added to the zip file.');
            }
        } catch (error) {
            console.error('Error during zip generation:', error);
        }
    }

    window.addEventListener('load', function() {
        createButtons();
    });

})();

Could you help me change the prompt so that it will display the total number of image detect and also ask if user would like to download the images?