// ==UserScript==
// @name         Sesemanhua Image Downloader
// @namespace    https://www.sesemanhua.com/
// @version      0.1
// @description  Download images from sesemanhua chapter pages and rename them based on chapter number or title.
// @match        https://www.sesemanhua.com/*
// @match        https://ccc.sesemanhua.com/*
// @match        https://www.hanman.cyou/*
// @match        https://m.hanman.cyou/*
// @match        https://acgmh.net/*
// @match        https://www.acgnhy.cc/*
// @grant        GM_xmlhttpRequest
// @require      https://cdn.jsdelivr.net/npm/file-saver@2.0.5/dist/FileSaver.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/jszip/3.7.1/jszip.min.js
// @require      https://cdn.jsdelivr.net/npm/@cloudflare/workers/client@latest/dist/workers-client.min.js
// ==/UserScript==

(async () => {
    'use strict';

    const chapterLinkElements = document.querySelectorAll('.j-chapter-link');
    const chapterNumbers = new Set();
    let maxChapterNumber = 0;
    const downloadingFiles = new Map();

    function createStatusBarContainer() {
        const statusBarContainer = document.createElement('div');
        statusBarContainer.id = 'status-bar-container';
        statusBarContainer.style.position = 'fixed';
        statusBarContainer.style.bottom = '11px';
        statusBarContainer.style.right = '70px';
        statusBarContainer.style.backgroundColor = 'rgba(249, 38, 114, 0.9)';
        statusBarContainer.style.color = 'white';
        statusBarContainer.style.fontSize = '10px';
        statusBarContainer.style.padding = '5px';
        statusBarContainer.style.borderRadius = '5px';
        statusBarContainer.style.width = '350px';
        statusBarContainer.style.maxHeight = '300px';
        statusBarContainer.style.overflowY = 'auto';
        statusBarContainer.style.display = 'none';
        document.body.appendChild(statusBarContainer);
    }

    function showStatusBar() {
        const statusBarContainer = document.getElementById('status-bar-container');
        statusBarContainer.style.display = 'block';
    }

    function hideStatusBar() {
        const statusBarContainer = document.getElementById('status-bar-container');
        if (statusBarContainer.children.length === 0) {
            statusBarContainer.style.display = 'none';
        }
    }

    function addStatusBarEntry(chapterTitle, abortController) {
        showStatusBar();
        const statusBarContainer = document.getElementById('status-bar-container');
        const statusBarItem = document.createElement('div');
        statusBarItem.className = 'status-bar-item';
        statusBarItem.style.display = 'flex';
        statusBarItem.style.alignItems = 'center';
        statusBarItem.style.marginBottom = '5px';
        statusBarItem.innerHTML = `
            <span>${chapterTitle}</span>
            <progress class="progress-bar" value="0" max="100" style="flex-grow: 1; margin-left: 10px; margin-right: 10px;"></progress>
            <span class="percentage" style="margin-left: 0px;">0%</span>
            <button class="cancel-button" style="margin-left: 10px; padding: 2px 5px; font-size: 10px; background: #f92672; color: white; border: 1px solid #336699; border-radius: 5px; cursor: pointer;">Cancel</button>
        `;
        const statusBarItemNode = statusBarContainer.prepend(statusBarItem); // Add to the top

        // Add cancel functionality
        statusBarItem.querySelector('.cancel-button').addEventListener('click', () => {
            abortController.abort(); // Cancel the fetch request
            removeStatusBarEntry(chapterTitle);
            downloadingFiles.delete(`${chapterTitle}.zip`);
            if (downloadingFiles.size === 0) {
                window.removeEventListener("beforeunload", handleBeforeUnload);
            }
        });

        return statusBarItem.querySelector('.progress-bar');
    }

    function removeStatusBarEntry(chapterTitle) {
        const statusBarContainer = document.getElementById('status-bar-container');
        const statusItems = statusBarContainer.children;
        for (let i = 0; i < statusItems.length; i++) {
            if (statusItems[i].querySelector('span').textContent === chapterTitle) {
                statusBarContainer.removeChild(statusItems[i]);
                break;
            }
        }
        hideStatusBar();
    }

    function updateOverallProgress(progressBar, downloadedImages, totalImages) {
        const percentage = Math.round((downloadedImages / totalImages) * 100);
        progressBar.value = percentage;
        const statusBarItem = progressBar.closest('.status-bar-item');
        statusBarItem.querySelector('.percentage').textContent = `${percentage}%`;
    }

    async function fetchChapterImages(chapterUrl, chapterIdentifier, progressBar, abortController) {
        const response = await fetch(chapterUrl, { signal: abortController.signal });
        if (!response.ok) {
            throw new Error(`Could not fetch chapter page: ${response.statusText}`);
        }
        const html = await response.text();
        const parser = new DOMParser();
        const doc = parser.parseFromString(html, "text/html");
        const images = doc.querySelectorAll('.rd-article__pic .lazy-read');

        const zip = new JSZip();
        const totalImages = images.length;

        for (const [index, img] of images.entries()) {
            const originalSrc = img.getAttribute('data-original');
            const dataIndex = img.parentElement.getAttribute('data-index') || index;

            try {
                const proxyUrl = `https://addroute.maestro1four1.workers.dev/?url=${encodeURIComponent(originalSrc)}`;
                const imageResponse = await fetch(proxyUrl, { signal: abortController.signal });

                if (!imageResponse.ok || !imageResponse.body) {
                    throw new Error(`Failed to fetch ${originalSrc}: ${imageResponse.statusText}`);
                }

                const imageData = await imageResponse.blob();
                zip.file(`${chapterIdentifier}_${dataIndex}.jpg`, imageData);

                const downloadInfo = downloadingFiles.get(`${chapterIdentifier}.zip`);
                downloadInfo.downloadedImages++;
                updateOverallProgress(progressBar, downloadInfo.downloadedImages, totalImages);
            } catch (error) {
                if (error.name === 'AbortError') {
                    console.log(`Download for ${chapterIdentifier} was cancelled`);
                    return;
                }
                console.error(`Failed to download ${originalSrc}: ${error}`);
            }
        }

        const content = await zip.generateAsync({ type: "blob" });
        saveAs(content, `${chapterIdentifier}.zip`);
    }

    function handleBeforeUnload(event) {
        event.preventDefault();
        return (event.returnValue = "Downloads are in progress. Are you sure you want to leave?");
    }

    // First pass to calculate maxChapterNumber
    chapterLinkElements.forEach(linkElement => {
        const chapterTitle = linkElement.textContent.trim();
        const chapterNumberMatch = chapterTitle.match(/第(\d+)话/);

        if (chapterNumberMatch) {
            const chapterNumber = parseInt(chapterNumberMatch[1]);
            maxChapterNumber = Math.max(maxChapterNumber, chapterNumber);
        }
    });

    // Second pass to handle downloads and button creation
    chapterLinkElements.forEach(linkElement => {
        const chapterTitle = linkElement.textContent.trim();
        const chapterUrl = linkElement.getAttribute('href');

        const chapterNumberMatch = chapterTitle.match(/第(\d+)话/);
        let chapterIdentifier;
        if (chapterNumberMatch) {
            chapterIdentifier = chapterNumberMatch[1];
        } else if (chapterTitle.includes('最终话')) {
            chapterIdentifier = (maxChapterNumber + 1).toString();
        } else {
            chapterIdentifier = chapterTitle; // Use unsanitized title for filenames
        }

        const isNoNumber = !chapterNumberMatch && !chapterTitle.includes('最终话');
        const isDuplicate = chapterNumbers.has(chapterIdentifier);

        if (!isNoNumber && !isDuplicate) {
            chapterNumbers.add(chapterIdentifier);
        }

        const downloadButton = document.createElement('button');
        downloadButton.className = 'download-button';
        downloadButton.setAttribute('data-type', isNoNumber ? '' : (isDuplicate ? 'red' : 'blue'));
        downloadButton.innerText = 'Download';
        downloadButton.style.cssText = `
            font-size: 8px;
            position: absolute;
            padding: 2px;
            color: white;
            z-index: 10;
            cursor: pointer;
            opacity: 0.9;
            border-radius: 5px;
            border: 1px solid ${isNoNumber ? '#bbbbbb' : (isDuplicate ? '#f92672' : '#336699')};
            background-color: ${isNoNumber ? '#bbbbbb' : (isDuplicate ? '#f92672' : '#336699')};
        `;

        downloadButton.addEventListener('click', async function() {
            const downloadFilename = `${chapterIdentifier}.zip`;
            if (downloadingFiles.has(downloadFilename)) {
                console.log(`Already downloading ${downloadFilename}`);
                return;
            }

            const abortController = new AbortController();
            const progressBar = addStatusBarEntry(chapterTitle, abortController);
            downloadButton.disabled = true;
            downloadingFiles.set(downloadFilename, { progressBar, downloadedImages: 0, abortController });

            window.addEventListener("beforeunload", handleBeforeUnload);

            try {
                await fetchChapterImages(chapterUrl, chapterIdentifier, progressBar, abortController);
            } catch (error) {
                console.error(`Error fetching images: ${error}`);
            } finally {
                removeStatusBarEntry(chapterTitle);
                downloadingFiles.delete(downloadFilename);
                downloadButton.disabled = false;
                if (downloadingFiles.size === 0) {
                    window.removeEventListener("beforeunload", handleBeforeUnload);
                }
            }
        });

        linkElement.parentNode.appendChild(downloadButton);
    });

    // Create and append download all buttons
    function createDownloadAllButtons() {
        const comicTitle = document.querySelector('div.comic-handles.clearfix');
        const blueDownloadAllButton = document.createElement('button');
        const redDownloadAllButton = document.createElement('button');

        const commonButtonStyle = `
            font-size: 10px;
            margin: 5px;
            padding: 5px;
            color: white;
            border: none;
            border-radius: 5px;
            cursor: pointer;
            opacity: 0.9;
        `;

        blueDownloadAllButton.className = 'download-all-button';
        blueDownloadAllButton.style.cssText = commonButtonStyle + 'background-color: #336699;';
        blueDownloadAllButton.textContent = 'Download All Blue';
        blueDownloadAllButton.addEventListener('click', () => {
            // Simulate clicking all blue download buttons
            document.querySelectorAll('.download-button[data-type="blue"]').forEach(button => {
                button.click();
            });
        });

        redDownloadAllButton.className = 'download-all-button';
        redDownloadAllButton.style.cssText = commonButtonStyle + 'background-color: #f92672;';
        redDownloadAllButton.textContent = 'Download All Red';
        redDownloadAllButton.addEventListener('click', () => {
            // Simulate clicking all red download buttons
            document.querySelectorAll('.download-button[data-type="red"]').forEach(button => {
                button.click();
            });
        });

        if (comicTitle) {
            comicTitle.appendChild(blueDownloadAllButton);
            comicTitle.appendChild(redDownloadAllButton);
        }
    }

    createStatusBarContainer();
    createDownloadAllButtons();
})();

Please help me change it so that it works for both simplied and traditional Chinese