const axios = require("axios");
const fs = require("fs");
const path = require("path");
const FormData = require("form-data");
const moment = require("moment");
const { HttpsProxyAgent } = require("https-proxy-agent");
const pool = require("../models/db");
const { getValidToken } = require("./tokenManager");
const { getProxy, markProxyFailed } = require("./proxyManager");
const { checkWeeklyLimit, getRejectedReceipts, deleteReceipt } = require("./historyManager");
const { sleep, logToDatabase } = require("./helpers");

const IMAGE_FOLDER = "C:/Users/Administrator/Desktop/receip-script/image/";
const USED_IMAGE_FOLDER = "C:/Users/Administrator/Desktop/receip-script/used_images/";
const AXIOS_TIMEOUT = 30000; // 30 seconds timeout for all axios requests

function getAxiosProxyConfig(proxy) {
    if (!proxy) {
        console.error("❌ No proxy provided for request");
        throw new Error("Proxy is required for all requests");
    }
    try {
        const agent = new HttpsProxyAgent(proxy);
        return { httpsAgent: agent, proxy: false, timeout: AXIOS_TIMEOUT }; // Added timeout
    } catch (error) {
        console.error(`❌ Failed to create proxy agent: ${error.message}`);
        throw error;
    }
}

// Utility to fetch account name
async function getAccountName(accountId) {
    const [rows] = await pool.query("SELECT name FROM accounts WHERE id = ?", [accountId]);
    return rows.length > 0 ? rows[0].name : `Account ${accountId}`;
}

async function getAccountInfo(accountId, proxy) {
    const accountName = await getAccountName(accountId);
    if (!proxy) throw new Error("Proxy is required for account info fetch");
    try {
        const token = await getValidToken(accountId);
        console.log(`${accountName} - Fetch Account Info - Retrieve total points - Started`);
        await logToDatabase(accountId, `Fetching account info...`);

        const response = await axios.get("https://api2.datatwix.com/rewards/user?voidCache=true&locale=en-US", {
            headers: {
                "Authorization": `Bearer ${token}`,
                "Accept": "application/json, text/plain, */*",
                "If-None-Match": "undefined",
                "Content-Type": "application/json",
                "Accept-Encoding": "gzip, deflate, br",
                "User-Agent": "okhttp/4.9.2"
            },
            ...getAxiosProxyConfig(proxy)
        });

        if (response.status === 200) {
            const totalPoints = response.data.points || 0;
            console.log(`${accountName} - Fetch Account Info - Retrieve total points - Result: ${totalPoints}`);
            await logToDatabase(accountId, `Account Total Points: ${totalPoints}`);
            await saveTotalPoints(accountId, totalPoints);
        } else {
            console.log(`${accountName} - Fetch Account Info - Retrieve total points - Result: Failed with status ${response.status}`);
        }
    } catch (error) {
        console.log(`${accountName} - Fetch Account Info - Retrieve total points - Result: Failed with error ${error.response?.status} - ${error.response?.data || error.message}`);
        await logToDatabase(accountId, `Failed to fetch account info: ${error.message}`);
        throw error;
    }
}

async function saveTotalPoints(accountId, totalPoints) {
    const accountName = await getAccountName(accountId);
    try {
        await pool.query("UPDATE accounts SET total_points = ?, last_run_time = NOW() WHERE id = ?", [totalPoints, accountId]);
        console.log(`${accountName} - Save Total Points - Update database with ${totalPoints} - Result: Success`);
    } catch (error) {
        console.log(`${accountName} - Save Total Points - Update database with ${totalPoints} - Result: Failed with error ${error.message}`);
    }
}

async function getUploadUrl(accountId, proxy) {
    const accountName = await getAccountName(accountId);
    if (!proxy) throw new Error("Proxy is required for upload URL fetch");
    try {
        const token = await getValidToken(accountId);
        console.log(`${accountName} - Get Amazon URL - Request upload URL - Started`);
        const response = await axios.post(
            "https://api.data-123.com/asset-manager/upload",
            { "type": "image/jpeg", "bucket": "receipt-assets", "region": "ap-southeast-1" },
            {
                headers: {
                    "Authorization": `Bearer ${token}`,
                    "Accept": "application/json, text/plain, */*",
                    "If-None-Match": "undefined",
                    "Content-Type": "application/json",
                    "Accept-Encoding": "gzip, deflate, br",
                    "User-Agent": "okhttp/4.9.2"
                },
                ...getAxiosProxyConfig(proxy)
            }
        );
        console.log(`${accountName} - Get Amazon URL - Request upload URL - Result: Success`);
        return response.data;
    } catch (error) {
        console.log(`${accountName} - Get Amazon URL - Request upload URL - Result: Failed with error ${error.message}`);
        throw error;
    }
}

async function uploadToS3(accountId, uploadData, imagePath) {
    const accountName = await getAccountName(accountId);
    const proxy = await getProxy(accountId);
    if (!proxy) throw new Error("Proxy is required for S3 upload");

    const maxRetries = 3;
    let attempt = 0;

    while (attempt < maxRetries) {
        try {
            const form = new FormData();
            Object.entries(uploadData.fields).forEach(([key, value]) => form.append(key, value));
            form.append("acl", "public-read");
            form.append("Content-Type", "image/jpeg");
            form.append("file", fs.createReadStream(imagePath), { filename: uploadData.fields.key, contentType: "image/jpeg" });

            console.log(`${accountName} - Upload to S3 - Upload image ${imagePath} - Attempt ${attempt + 1}/${maxRetries} Started`);
            const response = await axios.post(uploadData.url, form, {
                headers: {
                    "Host": "s3.ap-southeast-1.amazonaws.com",
                    "Accept": "application/json, text/plain, */*",
                    "Accept-Encoding": "gzip, deflate, br",
                    "User-Agent": "okhttp/4.9.2",
                    "Connection": "keep-alive",
                    ...form.getHeaders()
                },
                ...getAxiosProxyConfig(proxy)
            });

            // Validate S3 response
            if (response.status === 204 && response.headers['etag']) {
                console.log(`${accountName} - Upload to S3 - Upload image ${imagePath} - Result: Success (ETag: ${response.headers['etag']})`);
            } else {
                console.warn(`${accountName} - Upload to S3 - Upload image ${imagePath} - Warning: No ETag in response, assuming success`);
            }
            return uploadData.fields.key;
        } catch (error) {
            const status = error.response?.status;
            if (status && status >= 500 && status < 600 && attempt < maxRetries - 1) {
                console.log(`${accountName} - Upload to S3 - Upload image ${imagePath} - Retry ${attempt + 1}/${maxRetries} Failed with ${status}, retrying...`);
                attempt++;
                await sleep(1000); // 1-second delay between retries
            } else {
                console.log(`${accountName} - Upload to S3 - Upload image ${imagePath} - Result: Failed with error ${error.response?.status} - ${error.response?.data || error.message}`);
                throw error;
            }
        }
    }
}

async function submitReceipt(accountId, imageKey, proxy) {
    const accountName = await getAccountName(accountId);
    if (!proxy) throw new Error("Proxy is required for receipt submission");
    try {
        const token = await getValidToken(accountId);
        const requestData = {
            "uploadedDate": moment().format("YYYY-MM-DD"),
            "uploadedTime": moment().format("HH:mm:ss"),
            "source": "UNOMONEY",
            "images_urls": [`https://receipt-assets.s3.ap-southeast-1.amazonaws.com/${imageKey}`]
        };

        console.log(`${accountName} - Submit Receipt - Send receipt data for ${imageKey} - Started`);
        await logToDatabase(accountId, `Sending receipt data...`);

        const response = await axios.post(
            "https://api2.datatwix.com/rewards/receipt",
            requestData,
            {
                headers: {
                    "Authorization": `Bearer ${token}`,
                    "Accept": "application/json, text/plain, */*",
                    "If-None-Match": "undefined",
                    "Content-Type": "application/json",
                    "Accept-Encoding": "gzip, deflate, br",
                    "User-Agent": "okhttp/4.9.2"
                },
                ...getAxiosProxyConfig(proxy)
            }
        );

        console.log(`${accountName} - Submit Receipt - Send receipt data for ${imageKey} - Result: Success`);
        await logToDatabase(accountId, `Receipt submitted successfully`);
        return response.data;
    } catch (error) {
        console.log(`${accountName} - Submit Receipt - Send receipt data for ${imageKey} - Result: Failed with error ${error.response?.status} - ${error.response?.data}`);
        await logToDatabase(accountId, `Failed to submit receipt: ${error.message}`);
        throw error;
    }
}

async function processReceiptUpload(accountId, imagePath) {
    const accountName = await getAccountName(accountId);
    try {
        console.log(`${accountName} - Process Receipt Upload - Upload ${imagePath} - Started`);
        let proxy = await getProxy(accountId);
        if (!proxy) {
            console.log(`${accountName} - Check Proxy - Ensure proxy assigned - Result: Failed, no proxy available`);
            await logToDatabase(accountId, "No proxy available");
            return null;
        }
        console.log(`${accountName} - Check Proxy - Ensure proxy assigned - Result: Success, using ${proxy}`);

        const uploadData = await getUploadUrl(accountId, proxy);
        const imageKey = await uploadToS3(accountId, uploadData, imagePath);
        const receiptResponse = await submitReceipt(accountId, imageKey, proxy);

        const usedPath = path.join(USED_IMAGE_FOLDER, path.basename(imagePath));
        fs.renameSync(imagePath, usedPath);
        await pool.query("UPDATE accounts SET images_uploaded = images_uploaded + 1 WHERE id = ?", [accountId]);

        console.log(`${accountName} - Process Receipt Upload - Upload ${imagePath} - Result: Success`);
        return receiptResponse;
    } catch (error) {
        console.log(`${accountName} - Process Receipt Upload - Upload ${imagePath} - Result: Failed with error ${error.message}`);
        await logToDatabase(accountId, `Error processing receipt upload: ${error.message}`);
        return null;
    }
}

async function processSingleUpload(accountId, imagePath, proxy) {
    const accountName = await getAccountName(accountId);
    if (!proxy) throw new Error("Proxy is required for single upload");
    try {
        console.log(`${accountName} - Single Upload - Upload ${imagePath} - Started`);
        await logToDatabase(accountId, `Uploading image: ${imagePath}`);

        const uploadData = await getUploadUrl(accountId, proxy);
        const imageKey = await uploadToS3(accountId, uploadData, imagePath);
        const receiptResponse = await submitReceipt(accountId, imageKey, proxy);

        console.log(`${accountName} - Single Upload - Upload ${imagePath} - Result: Success`);
        await logToDatabase(accountId, `Receipt uploaded successfully: ${imagePath}`);

        const usedPath = path.join(USED_IMAGE_FOLDER, path.basename(imagePath));
        fs.renameSync(imagePath, usedPath);
        await pool.query("UPDATE accounts SET images_uploaded = images_uploaded + 1 WHERE id = ?", [accountId]);

        return receiptResponse;
    } catch (error) {
        console.log(`${accountName} - Single Upload - Upload ${imagePath} - Result: Failed with error ${error.message}`);
        await logToDatabase(accountId, `Error uploading image: ${error.message}`);
        throw error;
    }
}

async function processBatchUpload(accountId, signal, usedProxies, usedImages) {
    const accountName = await getAccountName(accountId);
    console.log(`${accountName} - Batch Run Initiation - Start single account automation - Started`);

    signal.throwIfAborted();

    let proxy = await getProxy(accountId);
    if (!proxy) {
        const [newProxyRows] = await pool.query(
            "SELECT proxy FROM proxies WHERE status = 'unused' AND assigned_to IS NULL AND proxy NOT IN (SELECT proxy FROM proxy_history WHERE account_id != ?) LIMIT 1",
            [accountId]
        );
        if (newProxyRows.length === 0) {
            console.log(`${accountName} - Check Proxy - Ensure proxy assigned - Result: Failed, no unused proxies available`);
            await logToDatabase(accountId, "No proxy available");
            await pool.query("UPDATE accounts SET status = 'error' WHERE id = ?", [accountId]);
            throw new Error("No proxy available");
        }
        proxy = newProxyRows[0].proxy;
        await pool.query("UPDATE accounts SET proxy = ? WHERE id = ?", [proxy, accountId]);
        await pool.query("UPDATE proxies SET assigned_to = ?, status = 'active' WHERE proxy = ?", [accountId, proxy]);
        await pool.query("INSERT INTO proxy_history (proxy, account_id) VALUES (?, ?)", [proxy, accountId]);
        usedProxies.add(proxy);
        console.log(`${accountName} - Check Proxy - Ensure proxy assigned - Result: Success, assigned new proxy ${proxy}`);
    } else {
        const [historyRows] = await pool.query("SELECT account_id FROM proxy_history WHERE proxy = ? AND account_id != ?", [proxy, accountId]);
        if (historyRows.length > 0) {
            console.log(`${accountName} - Check Proxy - Ensure proxy unique - Result: Failed, proxy ${proxy} already used`);
            await logToDatabase(accountId, `Proxy ${proxy} already used by another account`);
            const [newProxyRows] = await pool.query(
                "SELECT proxy FROM proxies WHERE status = 'unused' AND assigned_to IS NULL AND proxy NOT IN (SELECT proxy FROM proxy_history WHERE account_id != ?) LIMIT 1",
                [accountId]
            );
            if (newProxyRows.length === 0) {
                console.log(`${accountName} - Check Proxy - Assign new proxy - Result: Failed, no unused proxies available`);
                await logToDatabase(accountId, "No unused proxies available");
                await pool.query("UPDATE accounts SET status = 'error' WHERE id = ?", [accountId]);
                throw new Error("No proxy available");
            }
            proxy = newProxyRows[0].proxy;
            await pool.query("UPDATE accounts SET proxy = ? WHERE id = ?", [proxy, accountId]);
            await pool.query("UPDATE proxies SET assigned_to = ?, status = 'active' WHERE proxy = ?", [accountId, proxy]);
            await pool.query("INSERT INTO proxy_history (proxy, account_id) VALUES (?, ?)", [proxy, accountId]);
            usedProxies.add(proxy);
            console.log(`${accountName} - Check Proxy - Assign new proxy - Result: Success, assigned ${proxy}`);
        } else {
            console.log(`${accountName} - Check Proxy - Ensure proxy assigned - Result: Success, using ${proxy}`);
        }
    }

    signal.throwIfAborted();

    console.log(`${accountName} - Check Image Folder - Ensure images available - Started`);
    const initialImages = fs.readdirSync(IMAGE_FOLDER).filter(file => (file.endsWith(".jpg") || file.endsWith(".jpeg")) && !usedImages.has(file));
    console.log(`${accountName} - Check Image Folder - Ensure images available - Result: ${initialImages.length > 0 ? `Found ${initialImages.length} images` : "Empty"}`);

    try {
        console.log(`${accountName} - Validate Token - Check token validity - Started`);
        await getValidToken(accountId);
        console.log(`${accountName} - Validate Token - Check token validity - Result: Success`);
    } catch (error) {
        console.log(`${accountName} - Validate Token - Check token validity - Result: Failed with error ${error.message}`);
        await logToDatabase(accountId, `Token validation failed: ${error.message}`);
        await pool.query("UPDATE accounts SET status = 'error' WHERE id = ?", [accountId]);
        throw error;
    }

    let retries = 0;
    const maxRetries = 3;
    let totalUploadedImages = 0;

    while (retries < maxRetries) {
        try {
            await pool.query("UPDATE accounts SET status = 'running' WHERE id = ?", [accountId]);
            signal.throwIfAborted();

            let points;
            try {
                console.log(`${accountName} - Check Weekly Limit - Minimum 120 points - Started`);
                points = await checkWeeklyLimit(accountId, proxy);
                signal.throwIfAborted();
                console.log(`${accountName} - Check Weekly Limit - Minimum 120 points - Result: ${points}/120 ${points >= 120 ? "Skip upload" : "Proceed"}`);
            } catch (error) {
                console.log(`${accountName} - Check Weekly Limit - Minimum 120 points - Result: Failed with error ${error.message}`);
                await logToDatabase(accountId, `Failed to check weekly limit: ${error.message}`);
                await pool.query("UPDATE accounts SET status = 'error' WHERE id = ?", [accountId]);
                throw error;
            }

            console.log(`${accountName} - Save Weekly Points - Update database with ${points} - Started`);
            await pool.query("UPDATE accounts SET weekly_points = ? WHERE id = ?", [points, accountId]);
            console.log(`${accountName} - Save Weekly Points - Update database with ${points} - Result: Success`);

            const images = fs.readdirSync(IMAGE_FOLDER).filter(file => (file.endsWith(".jpg") || file.endsWith(".jpeg")) && !usedImages.has(file));
            if (images.length === 0 || points >= 120) {
                console.log(`${accountName} - Upload Images - Check for images - Result: ${images.length === 0 ? "No images left" : "Weekly limit reached"}, skipping upload`);
                await logToDatabase(accountId, images.length === 0 ? "Image folder is empty." : "Weekly limit reached.");

                console.log(`${accountName} - Process Rejected Receipts - Check and delete rejected - Started`);
                await processRejectedReceipts(accountId, proxy, signal);
                signal.throwIfAborted();
                console.log(`${accountName} - Process Rejected Receipts - Check and delete rejected - Result: Success`);

                console.log(`${accountName} - Fetch Account Info - Retrieve total points - Started`);
                await getAccountInfo(accountId, proxy);
                console.log(`${accountName} - Save Total Points - Update database - Result: Success`);

                await pool.query("UPDATE accounts SET status = 'idle' WHERE id = ?", [accountId]);
                console.log(`${accountName} - Batch Run Completion - Finalize automation - Result: Success`);
                return;
            }

            let uploadedImagesThisRound = 0;
            const batchSize = totalUploadedImages === 0 ? 10 : 5;

            console.log(`${accountName} - Upload Images - Process ${batchSize} images - Started`);
            for (let i = 0; i < batchSize && images.length > 0; i++) {
                const imagePath = path.join(IMAGE_FOLDER, images.shift());
                usedImages.add(path.basename(imagePath));
                await processSingleUpload(accountId, imagePath, proxy);
                uploadedImagesThisRound++;
                totalUploadedImages++;
                await sleep(60000);
                signal.throwIfAborted();
            }
            console.log(`${accountName} - Upload Images - Process ${batchSize} images - Result: Uploaded ${uploadedImagesThisRound} images, total ${totalUploadedImages}`);

            console.log(`${accountName} - Wait Period - Delay 5 minutes post-upload - Started`);
            await logToDatabase(accountId, "Waiting 5 minutes for processing...");
            for (let j = 0; j < 300; j++) {
                await sleep(1000);
                signal.throwIfAborted();
            }
            console.log(`${accountName} - Wait Period - Delay 5 minutes post-upload - Result: Completed`);

            while (true) {
                console.log(`${accountName} - Recheck Weekly Limit - Minimum 120 points - Started`);
                const newPoints = await checkWeeklyLimit(accountId, proxy);
                signal.throwIfAborted();
                console.log(`${accountName} - Recheck Weekly Limit - Minimum 120 points - Result: ${newPoints}/120 ${newPoints >= 120 ? "End upload" : "Continue"}`);

                await pool.query("UPDATE accounts SET weekly_points = ? WHERE id = ?", [newPoints, accountId]);

                if (newPoints >= 120) break;

                const remainingImages = fs.readdirSync(IMAGE_FOLDER).filter(file => (file.endsWith(".jpg") || file.endsWith(".jpeg")) && !usedImages.has(file));
                if (remainingImages.length === 0) {
                    console.log(`${accountName} - Upload Images - Check for remaining images - Result: No images left, ending upload`);
                    await logToDatabase(accountId, "No more images left.");
                    break;
                }

                uploadedImagesThisRound = 0;
                console.log(`${accountName} - Upload Images - Process 5 more images - Started`);
                for (let i = 0; i < 5 && remainingImages.length > 0; i++) {
                    const imagePath = path.join(IMAGE_FOLDER, remainingImages.shift());
                    usedImages.add(path.basename(imagePath));
                    await processSingleUpload(accountId, imagePath, proxy);
                    uploadedImagesThisRound++;
                    totalUploadedImages++;
                    await sleep(60000);
                    signal.throwIfAborted();
                }
                console.log(`${accountName} - Upload Images - Process 5 more images - Result: Uploaded ${uploadedImagesThisRound} images, total ${totalUploadedImages}`);

                console.log(`${accountName} - Wait Period - Delay 5 minutes post-upload - Started`);
                await logToDatabase(accountId, "Waiting 5 minutes for processing...");
                for (let j = 0; j < 300; j++) {
                    await sleep(1000);
                    signal.throwIfAborted();
                }
                console.log(`${accountName} - Wait Period - Delay 5 minutes post-upload - Result: Completed`);
            }

            console.log(`${accountName} - Process Rejected Receipts - Check and delete rejected - Started`);
            await processRejectedReceipts(accountId, proxy, signal);
            signal.throwIfAborted();

            await getAccountInfo(accountId, proxy);
            await pool.query("UPDATE accounts SET status = 'idle' WHERE id = ?", [accountId]);
            console.log(`${accountName} - Batch Run Completion - Finalize automation - Result: Success with ${totalUploadedImages} images uploaded`);
            break;
        } catch (error) {
            if (error.message === "Process aborted by user") {
                console.log(`${accountName} - Batch Run Abortion - User stopped process - Result: Aborted`);
                await logToDatabase(accountId, "Process aborted by user");
                try {
                    await pool.query("UPDATE accounts SET status = 'stopped' WHERE id = ?", [accountId]);
                    console.log(`${accountName} - Update Status - Set to stopped - Result: Success`);
                } catch (updateError) {
                    console.log(`${accountName} - Update Status - Set to stopped - Result: Failed with error ${updateError.message}`);
                }
                return;
            }
            console.log(`${accountName} - Batch Run Error - Handle failure - Result: Failed with error ${error.message}`);
            await logToDatabase(accountId, `Error in batch upload: ${error.message}`);
            if (error.response && error.response.status === 407) {
                retries++;
                console.log(`${accountName} - Proxy Retry - Attempt ${retries}/${maxRetries} due to 407 error - Started`);
                await markProxyFailed(proxy);
                usedProxies.delete(proxy);
                const [newProxyRows] = await pool.query(
                    "SELECT proxy FROM proxies WHERE status = 'unused' AND assigned_to IS NULL AND proxy NOT IN (SELECT proxy FROM proxy_history WHERE account_id != ?) LIMIT 1",
                    [accountId]
                );
                if (newProxyRows.length === 0) {
                    console.log(`${accountName} - Proxy Retry - Assign new proxy - Result: Failed, no unused proxies available`);
                    await logToDatabase(accountId, "No unused proxies available after retries.");
                    await pool.query("UPDATE accounts SET status = 'error' WHERE id = ?", [accountId]);
                    throw new Error("No proxy available");
                }
                proxy = newProxyRows[0].proxy;
                await pool.query("UPDATE accounts SET proxy = ? WHERE id = ?", [proxy, accountId]);
                await pool.query("UPDATE proxies SET assigned_to = ?, status = 'active' WHERE proxy = ?", [accountId, proxy]);
                await pool.query("INSERT INTO proxy_history (proxy, account_id) VALUES (?, ?)", [proxy, accountId]);
                usedProxies.add(proxy);
                console.log(`${accountName} - Proxy Retry - Assign new proxy - Result: Success, using ${proxy}`);
            } else {
                await markProxyFailed(proxy);
                await pool.query("UPDATE accounts SET status = 'error' WHERE id = ?", [accountId]);
                throw error;
            }
        }
    }
}

async function processRejectedReceipts(accountId, proxy, signal) {
    const accountName = await getAccountName(accountId);
    if (!proxy) throw new Error("Proxy is required for rejected receipts processing");
    console.log(`${accountName} - Process Rejected Receipts - Check and delete rejected - Started`);
    await logToDatabase(accountId, "Checking and deleting rejected receipts...");
    signal.throwIfAborted();

    let deletedCount = 0;
    while (true) {
        const rejectedReceipts = await getRejectedReceipts(accountId, proxy);
        signal.throwIfAborted();
        if (!rejectedReceipts || rejectedReceipts.length === 0) {
            console.log(`${accountName} - Process Rejected Receipts - Check and delete rejected - Result: No rejected receipts found, ${deletedCount} deleted`);
            await logToDatabase(accountId, "No more rejected receipts left.");
            break;
        }

        for (const receipt of rejectedReceipts) {
            console.log(`${accountName} - Delete Rejected Receipt - Delete ID ${receipt.id} - Started`);
            await logToDatabase(accountId, `Deleting rejected receipt ID: ${receipt.id}`);
            signal.throwIfAborted();
            const success = await deleteReceipt(accountId, receipt.id, proxy);
            signal.throwIfAborted();
            if (!success) {
                console.log(`${accountName} - Delete Rejected Receipt - Delete ID ${receipt.id} - Result: Failed`);
                await logToDatabase(accountId, `Failed to delete receipt ${receipt.id}`);
            } else {
                await pool.query("UPDATE accounts SET images_rejected = images_rejected + 1 WHERE id = ?", [accountId]);
                deletedCount++;
                console.log(`${accountName} - Delete Rejected Receipt - Delete ID ${receipt.id} - Result: Success`);
            }
            await sleep(5000);
            signal.throwIfAborted();
        }
    }
    console.log(`${accountName} - Process Rejected Receipts - Check and delete rejected - Result: Completed, ${deletedCount} deleted`);
    await logToDatabase(accountId, "Finished processing rejected receipts.");
}

module.exports = { processBatchUpload, processSingleUpload, processReceiptUpload };