const Resp = require("./helper/response");
const Info = require("./helper/info");
const Log = require("./helper/log");
const imap = require("imap");
const { simpleParser } = require("mailparser");
const fs = require("fs");
const path = require("path");
const serverModel = require("./model/servermodel");
const axios = require("axios");
const qs = require("qs");
const moment = require('moment');
const emailOperation = require('./emailOperation');

const MAX_RETRIES = 3;
const RETRY_DELAY_MS = 2000;

class MailOperation {
    async processIMAP(data, callback) {
        Log.incErrorLog(`IMAP Process Started for ${data.incoming_user_name}`);
        let retries = 0;

        const tryConnect = async (tokenToUse) => {
            return new Promise((resolve, reject) => {
                const imapConfig = this.createIMAPConfig(data, tokenToUse);
                const imapConnection = new imap(imapConfig);
                let connected = false;

                imapConnection.once("ready", () => {
                    connected = true;
                    Log.incErrorLog(`Connected to IMAP server: ${data.incoming_user_name}`);
                    imapConnection.openBox("INBOX", false, async (err, box) => {
                        if (err) {
                            imapConnection.end();
                            return reject(`Error opening mailbox: ${err}`);
                        }
                        const dateString = data.dont_read_mail_before;
                        if (data.dont_read_unread_mail == "1") {
                            const lastReadResult = await serverModel.getLastReadDate(data.queue_id);
                            if (!lastReadResult.status) {
                                callback("Failed to get last read date", null);
                                imapConnection.end();
                                return;
                            }
                            const date = lastReadResult.data.last_read_date;
                            const processedUIDs = await serverModel.getProcessedUIDs(data.queue_id, date);
                            if (!processedUIDs.status) {
                                callback("Failed to get processed UIDs", null);
                                imapConnection.end();
                                return;
                            }
                            const processedUIDSet = new Set(processedUIDs.data.map(i => i.uid));
                            Log.incErrorLog(`Processed UIDs: ${JSON.stringify(Array.from(processedUIDSet))}`);
                            // imapConnection.search([['SINCE', date]], (err, results) => {
                                imapConnection.search([['SINCE', '09-Sep-2025']], (err, results) => {
                                if (err || results.length === 0) {
                                    callback("No Mail found", null);
                                    imapConnection.end();
                                    return;
                                }
                                const newUIDs = results.filter(uid => !processedUIDSet.has(uid));
                                if (newUIDs.length === 0) {
                                    callback("No new Mail found", null);
                                    imapConnection.end();
                                    return;
                                }
                                const lastUID = newUIDs[newUIDs.length - 1];
                                const fetchRequest = imapConnection.fetch(lastUID, { bodies: ['HEADER.FIELDS (DATE)'] });
                                fetchRequest.on("message", msg => {
                                    let buffer = "";
                                    msg.on("body", stream => {
                                        stream.on("data", chunk => buffer += chunk);
                                        stream.on("end", () => {
                                            const lastEmailDate = this.getEmailDateFromBuffer(buffer);
                                            if (!lastEmailDate.startsWith("Error")) {
                                                serverModel.updateLastReadDate(data.queue_id, lastEmailDate);
                                            }
                                        });
                                    });
                                });
                                Log.incErrorLog(`New UIDs to process: ${newUIDs}`);
                                this.fetchEmails(imapConnection, newUIDs, data, callback);
                            });
                        } else {
                            this.fetchEmails(imapConnection, null, data, callback);
                        }
                        resolve();
                    });
                });

                imapConnection.once("error", async (err) => {
                    Log.incErrorLog(`IMAP connection error for ${data.incoming_user_name}: ${err}`);
                    if (!connected && data.is_auth_enable === 1) {
                        try {
                            const newToken = await this.refreshAuthToken(data);
                            data.token = newToken;
                            return reject("RETRY_WITH_NEW_TOKEN");
                        } catch (refreshErr) {
                            return reject(`Failed to refresh token: ${refreshErr}`);
                        }
                    } else {
                        return reject(`IMAP connection error: ${err}`);
                    }
                });

                imapConnection.once("end", () => {
                    Log.incErrorLog("IMAP connection closed");
                });

                imapConnection.connect();
            });
        };

        while (retries < MAX_RETRIES) {
            try {
                await tryConnect(data.token);
                return;
            } catch (err) {
                retries++;
                if (err === "RETRY_WITH_NEW_TOKEN") {
                    Log.incErrorLog(`Retrying IMAP with refreshed token. Attempt ${retries}`);
                    await new Promise(res => setTimeout(res, RETRY_DELAY_MS));
                } else if (err === "EBUSY") {
                    Log.incErrorLog(`Retrying IMAP due to EBUSY. Attempt ${retries}`);
                    await new Promise(res => setTimeout(res, RETRY_DELAY_MS));
                } else {
                    return callback(`Error on IMAP connect: ${err}`, null);
                }
            }
        }

        callback(`Failed to connect to IMAP after ${MAX_RETRIES} attempts`, null);
    }

    getEmailDateFromBuffer(buffer) {
        const match = buffer.match(/Date:\s*(.*?)(\r?\n|$)/);
        if (match && match[1]) {
            const date = new Date(match[1].trim());
            if (!isNaN(date)) return date.toISOString().split('T')[0];
        }
        return "Error: Unable to fetch email date";
    }
    
    // async fetchEmails(imapConnection, uids, data, callback) {
    //     // const searchCriteria = uids || ['UNSEEN', ['SINCE', data.dont_read_mail_before]];

    //     let searchCriteria;

    //     if (uids) {
    //         if (typeof uids === 'string') {
    //             searchCriteria = uids.split(',').map(uid => uid.trim());
    //         } else if (Array.isArray(uids)) {
    //             searchCriteria = uids.map(uid => String(uid)); // convert numbers to strings here
    //         } else if (typeof uids === 'number') {
    //             searchCriteria = [String(uids)];
    //         } else {
    //             throw new Error('uids must be a string, number, or array');
    //         }
    //     } else {
    //         searchCriteria = ['UNSEEN', ['SINCE', data.dont_read_mail_before]];
    //     }
    //     Log.incErrorLog(`Search Criteria: ${JSON.stringify(searchCriteria)}`);

    //     imapConnection.search(searchCriteria, (err, results) => {
    //         if (err || results.length === 0) {
    //             callback("No Mail found", null);
    //             imapConnection.end();
    //             return;
    //         }
    //         const fetch = imapConnection.fetch(results, { bodies: '', struct: true, markSeen: true });
    //         fetch.on('message', msg => {
    //             let buffer = '';
    //             msg.on('body', stream => {
    //                 stream.on('data', chunk => buffer += chunk);
    //                 stream.on('end', async () => {
    //                     try {
    //                         const parsed = await simpleParser(buffer);

    //                         const formattedDate = moment(parsed.date).format('YYYY-MM-DD HH:mm:ss');
    //                         const headerData = { ...Object.fromEntries(parsed.headers), date: formattedDate };
    //                         const fromAddress = headerData.from?.value?.[0]?.address || '';
    //                         const msgIdRaw = headerData['message-id'] || '';
    //                         if (!msgIdRaw) return;
    //                         const msgId = msgIdRaw.replace(/[<>.\-/]/g, '').split('@')[0];

    //                         if (
    //                             this.shouldBlockEmail(data, headerData) ||
    //                             this.shouldBlockDomain(data, headerData) ||
    //                             !this.isRecipientFound(data, headerData) ||
    //                             this.isSameEmail(data.incoming_user_name, fromAddress)
    //                         ) {
    //                             Log.incErrorLog(`Email blocked/skipped for ${headerData.from?.value}`);
    //                             // Log.incErrorLog(`Email blocked/skipped for ${data.incoming_user_name}`);
    //                             return;
    //                         }

    //                         const alreadyExists = await serverModel.checkMessageIdInDb(msgIdRaw, data.queue_id);
    //                         if (alreadyExists.status && alreadyExists.data && Object.keys(alreadyExists.data).length > 0) {
    //                             Log.incErrorLog(`Duplicate message-id found. Skipping ${msgIdRaw}`);
    //                             return;
    //                         }

    //                         const bodyData = parsed.html || parsed.textAsHtml || parsed.text || '';
    //                         const base64Body = Buffer.from(bodyData).toString('base64');

    //                         // const attachmentData = parsed.attachments.map(att => ({
    //                         //     filename: att.filename,
    //                         //     contentType: att.contentType,
    //                         //     attachmentContent: att.content.toString('base64')
    //                         // }));
    //                         // const attachmentData = parsed.attachments.map(att => {
    //                         //     if (!att.filename) return null;
    //                         //     const attachmentContent = Buffer.from(att.content, "binary");
    //                         //     return {
    //                         //         filename: att.filename,
    //                         //         contentType: att.contentType,
    //                         //         attachmentContent: attachmentContent.toString("base64"),
    //                         //     };
    //                         // }).filter(Boolean);
    //                         const attachmentContent = Buffer.from(
    //                             attachment.content.toString("binary"),
    //                             "binary"
    //                         );

    //                         const today = new Date();
    //                         const dateStr = new Date(today.getTime() - (today.getTimezoneOffset() * 60000))
    //                             .toISOString()
    //                             .slice(0, 10);

    //                         const todayFolderPath = path.join(__dirname, 'mail_json_file', dateStr);
    //                         const folderPath = path.join(todayFolderPath, msgId);

    //                         if (!fs.existsSync(todayFolderPath)) {
    //                             fs.mkdirSync(todayFolderPath);
    //                             fs.chmodSync(todayFolderPath, 0o777);
    //                         } else {
    //                             Log.incErrorLog(`Folder already exists for json file: ${todayFolderPath}`);
    //                         }
    //                         if (!fs.existsSync(folderPath)) {
    //                             fs.mkdirSync(folderPath);
    //                             fs.chmodSync(folderPath, 0o777);
    //                         } else {
    //                             Log.incErrorLog(`Folder already exists for json file: ${folderPath}`);
    //                         }

    //                         // Prepare final data and file info for your new block
    //                         const jsonData = {
    //                             headerData,
    //                             bodyData: base64Body,
    //                             attachmentData,
    //                             uid: msg.uid || 0,
    //                             msgId
    //                         };
    //                         const finalData = JSON.stringify(jsonData, null, 2);
    //                         const fileName = `${msgId}.json`;
    //                         const finalpath = path.join(folderPath, fileName);

    //                         fs.writeFile(finalpath, finalData, (writeErr) => {
    //                             if (writeErr) {
    //                                 Log.incErrorLog({ error: writeErr });
    //                                 return callback(writeErr, null);
    //                             } else {
    //                                 // Use relative folder path from your logic for callback and logging
    //                                 const todayISOString = dateStr; // or use your variable if different
    //                                 const folderName = msgId;
    //                                 const fileFolderPath = `${todayISOString}/${folderName}/`;

    //                                 Log.incErrorLog(`Mail data saved to JSON file ${headerData}`);

    //                                 if ("references" in headerData) {
    //                                     const references = headerData["references"];
    //                                     serverModel.getReferenceData(references, data.queue_id)
    //                                         .then((result) => {
    //                                             if (result.status === true) {
    //                                                 const idDataList = [];
    //                                                 const idData = result.data;

    //                                                 if (Object.keys(idData).length > 0) {
    //                                                     idDataList.push({
    //                                                         ticket_unique_id: idData.ticket_unique_id,
    //                                                     });
    //                                                 }

    //                                                 if (idDataList.length > 0) {
    //                                                     serverModel.getTicketIdRefrenceData(data.queue_id, idDataList[0].ticket_unique_id)
    //                                                         .then((result) => {
    //                                                             const replyTicketDataList = [];
    //                                                             if (result.status === true) {
    //                                                                 const replyTicketData = result.data;
    //                                                                 if (Object.keys(replyTicketData).length > 0) {
    //                                                                     replyTicketDataList.push({
    //                                                                         ticket_unique_id: replyTicketData.ticket_unique_id,
    //                                                                         status_id: replyTicketData.status_id,
    //                                                                         conversation_date: replyTicketData.conversation_date,
    //                                                                         conversation_id: replyTicketData.conversation_id,
    //                                                                         assigned_to: replyTicketData.assigned_to,
    //                                                                         is_assigned: replyTicketData.is_assigned,
    //                                                                     });
    //                                                                 }
    //                                                             }

    //                                                             const dataWithMsgId = {
    //                                                                 ...JSON.parse(finalData),
    //                                                                 msgId,
    //                                                                 fileFolderPath,
    //                                                                 replyTicketDataList,
    //                                                             };

    //                                                             callback(null, dataWithMsgId);
    //                                                         });
    //                                                 } else {
    //                                                     if (!this.isRecipientFound(data, headerData)) {
    //                                                         Log.incErrorLog("Recipient email not found in queue");
    //                                                         return;
    //                                                     } else {
    //                                                         const dataWithMsgId = {
    //                                                             ...JSON.parse(finalData),
    //                                                             msgId,
    //                                                             fileFolderPath,
    //                                                         };
    //                                                         callback(null, dataWithMsgId);
    //                                                     }
    //                                                 }
    //                                             } else {
    //                                                 if (!this.isRecipientFound(data, headerData)) {
    //                                                     Log.incErrorLog("Recipient email not found in queue");
    //                                                     return;
    //                                                 }
    //                                             }
    //                                         });
    //                                 } else {
    //                                     if (!this.isRecipientFound(data, headerData)) {
    //                                         Log.incErrorLog("Recipient email not found in queue");
    //                                         return;
    //                                     }
    //                                     const dataWithMsgId = {
    //                                         ...JSON.parse(finalData),
    //                                         msgId,
    //                                         fileFolderPath,
    //                                     };
    //                                     callback(null, dataWithMsgId);
    //                                 }
    //                             }
    //                         });

    //                     } catch (err) {
    //                         Log.incErrorLog(`Error processing message: ${err.message}`);
    //                     }
    //                 });
    //             });
    //         });

    //         fetch.once('error', err => {
    //             callback(`Fetch error: ${err}`, null);
    //         });

    //         fetch.once('end', () => {
    //             Log.incErrorLog('Finished processing messages');
    //         });
    //     });
    // }

    // async fetchEmails(imapConnection, uids, data, callback) {
    //     const searchCriteria = uids || ['UNSEEN', ['SINCE', data.dont_read_mail_before]];
    //     imapConnection.search(searchCriteria, (err, results) => {
    //         if (err || results.length === 0) {
    //             callback("No Mail found", null);
    //             imapConnection.end();
    //             return;
    //         }
    //         const fetch = imapConnection.fetch(results, { bodies: '', struct: true, markSeen: true });
    //         fetch.on('message', msg => {
    //             let buffer = '';
    //             msg.on('body', stream => {
    //                 stream.on('data', chunk => buffer += chunk);
    //                 stream.on('end', async () => {
    //                     try {
    //                         const parsed = await simpleParser(buffer);

    //                         const formattedDate = moment(parsed.date).format('YYYY-MM-DD HH:mm:ss');
    //                         const headerData = { ...Object.fromEntries(parsed.headers), date: formattedDate };
    //                         const fromAddress = headerData.from?.value?.[0]?.address || '';
    //                         const msgIdRaw = headerData['message-id'] || '';
    //                         if (!msgIdRaw) return;
    //                         const msgId = msgIdRaw.replace(/[<>.\-/]/g, '').split('@')[0];

    //                         if (
    //                             this.shouldBlockEmail(data, headerData) ||
    //                             this.shouldBlockDomain(data, headerData) ||
    //                             !this.isRecipientFound(data, headerData) ||
    //                             this.isSameEmail(data.incoming_user_name, fromAddress)
    //                         ) {
    //                             Log.incErrorLog(`Email blocked/skipped for ${data.incoming_user_name}`);
    //                             return;
    //                         }

    //                         const alreadyExists = await serverModel.checkMessageIdInDb(msgIdRaw, data.queue_id);
    //                         if (alreadyExists.status && alreadyExists.data && Object.keys(alreadyExists.data).length > 0) {
    //                             Log.incErrorLog(`Duplicate message-id found. Skipping ${msgIdRaw}`);
    //                             return;
    //                         }

    //                         const bodyData = parsed.html || parsed.textAsHtml || parsed.text || '';
    //                         const base64Body = Buffer.from(bodyData).toString('base64');

    //                         const attachmentData = parsed.attachments.map(att => ({
    //                             filename: att.filename,
    //                             contentType: att.contentType,
    //                             attachmentContent: att.content.toString('base64')
    //                         }));

    //                         //   const today = new Date();
    //                         //   const dateStr = new Date(today.getTime() - (today.getTimezoneOffset() * 60000)).toISOString().slice(0, 10);
    //                         //   const folderPath = path.join(__dirname, 'mail_json_file', dateStr, msgId);
    //                         // //   fs.mkdirSync(folderPath, { recursive: true });
    //                         // if (!fs.existsSync(folderPath)) {
    //                         //     fs.mkdirSync(folderPath, { recursive: true, mode: 0o777 });
    //                         // } else {
    //                         //     Log.incErrorLog(`Folder already exists for json file: ${folderPath}`);
    //                         // }
    //                         const today = new Date();
    //                         const dateStr = new Date(today.getTime() - (today.getTimezoneOffset() * 60000))
    //                             .toISOString()
    //                             .slice(0, 10);

    //                         const todayFolderPath = path.join(__dirname, 'mail_json_file', dateStr);
    //                         const folderPath = path.join(todayFolderPath, msgId);

    //                         // Check and create 'today' folder if missing
    //                         // if (!fs.existsSync(todayFolderPath)) {
    //                         //     fs.mkdirSync(todayFolderPath, { mode: 0o777 });
    //                         //     console.log(`Created folder: ${todayFolderPath}`);
    //                         // } else {
    //                         //     Log.incErrorLog(`Folder already exists for json file: ${todayFolderPath}`);
    //                         // }

    //                         // // Then check and create 'msgId' folder inside 'today' folder
    //                         // if (!fs.existsSync(folderPath)) {
    //                         //     fs.mkdirSync(folderPath, { mode: 0o777 });
    //                         //     console.log(`Created folder: ${folderPath}`);
    //                         // } else {
    //                         //     Log.incErrorLog(`Folder already exists for json file: ${folderPath}`);
    //                         // }

    //                         if (!fs.existsSync(todayFolderPath)) {
    //                             fs.mkdirSync(todayFolderPath);
    //                             fs.chmodSync(todayFolderPath, 0o777);
    //                         } else {
    //                             Log.incErrorLog(
    //                                 `Folder already exists for json file: ${todayFolderPath}`
    //                             );
    //                         }
    //                         if (!fs.existsSync(folderPath)) {
    //                             fs.mkdirSync(folderPath);
    //                             fs.chmodSync(folderPath, 0o777);
    //                         } else {
    //                             Log.incErrorLog(
    //                                 `Folder already exists for json file: ${folderPath}`
    //                             );
    //                         }

    //                         const filePath = path.join(folderPath, `${msgId}.json`);
    //                         const jsonData = {
    //                             headerData,
    //                             bodyData: base64Body,
    //                             attachmentData,
    //                             uid: msg.uid || 0,
    //                             msgId
    //                         };

    //                         fs.writeFileSync(filePath, JSON.stringify(jsonData, null, 2));
    //                         Log.incErrorLog(`Saved mail JSON: ${filePath}`);

    //                         callback(null, jsonData);
    //                     } catch (err) {
    //                         Log.incErrorLog(`Error processing message: ${err.message}`);
    //                     }
    //                 });
    //             });
    //         });

    //         fetch.once('error', err => {
    //             callback(`Fetch error: ${err}`, null);
    //         });

    //         fetch.once('end', () => {
    //             Log.incErrorLog('Finished processing messages');
    //         });
    //     });
    // }
    async fetchEmails(imapConnection, uids, data, callback) {
    let searchCriteria;

    if (uids) {
        if (typeof uids === 'string') {
            searchCriteria = uids.split(',').map(uid => uid.trim());
        } else if (Array.isArray(uids)) {
            searchCriteria = uids.map(uid => String(uid));
        } else if (typeof uids === 'number') {
            searchCriteria = [String(uids)];
        } else {
            throw new Error('uids must be a string, number, or array');
        }
    } else {
        searchCriteria = ['UNSEEN', ['SINCE', data.dont_read_mail_before]];
    }
    Log.incErrorLog(`Search Criteria: ${JSON.stringify(searchCriteria)}`);

    imapConnection.search(searchCriteria, (err, results) => {
        if (err || results.length === 0) {
            callback("No Mail found", null);
            imapConnection.end();
            return;
        }

        const fetch = imapConnection.fetch(results, { bodies: '', struct: true, markSeen: true });
        fetch.on('message', msg => {
            let buffer = '';
            msg.on('body', stream => {
                stream.on('data', chunk => buffer += chunk);
                stream.on('end', async () => {
                    try {
                        const parsed = await simpleParser(buffer);

                        const formattedDate = moment(parsed.date).format('YYYY-MM-DD HH:mm:ss');
                        const headerData = { ...Object.fromEntries(parsed.headers), date: formattedDate };
                        const fromAddress = headerData.from?.value?.[0]?.address || '';
                        const msgIdRaw = headerData['message-id'] || '';
                        if (!msgIdRaw) return;
                        const msgId = msgIdRaw.replace(/[<>.\-/]/g, '').split('@')[0];

                        if (
                            this.shouldBlockEmail(data, headerData) ||
                            this.shouldBlockDomain(data, headerData) ||
                            !this.isRecipientFound(data, headerData) ||
                            this.isSameEmail(data.incoming_user_name, fromAddress)
                        ) {
                            Log.incErrorLog(`Email blocked/skipped for ${headerData.from?.value}`);
                            return;
                        }

                        const alreadyExists = await serverModel.checkMessageIdInDb(msgIdRaw, data.queue_id);
                        if (alreadyExists.status && alreadyExists.data && Object.keys(alreadyExists.data).length > 0) {
                            Log.incErrorLog(`Duplicate message-id found. Skipping ${msgIdRaw}`);
                            return;
                        }

                        const bodyData = parsed.html || parsed.textAsHtml || parsed.text || '';
                        const base64Body = Buffer.from(bodyData).toString('base64');

                        // ✅ Attachment handling block
                        let attachmentData = [];
                        if (parsed.attachments && parsed.attachments.length > 0) {
                            for (const attachment of parsed.attachments) {
                                if (!attachment.filename) continue; // skip inline/unnamed attachments

                                Log.incErrorLog(` filename ${attachment.filename}`);

                                const attachmentContent = Buffer.from(
                                    attachment.content.toString("binary"),
                                    "binary"
                                );

                                const attachmentFileName = attachment.filename;
                                attachmentData.push({
                                    filename: attachment.filename,
                                    contentType: attachment.contentType,
                                    attachmentContent: attachmentContent.toString("base64"),
                                });

                                // Save file to disk
                                const today = new Date();
                                const dateStr = new Date(today.getTime() - (today.getTimezoneOffset() * 60000))
                                    .toISOString()
                                    .slice(0, 10);

                                const mainFolderPath = path.join(__dirname, "mail_json_file");
                                const todayFolderPath = path.join(mainFolderPath, dateStr);
                                const folderPath = path.join(todayFolderPath, msgId);

                                try {
                                    if (!fs.existsSync(todayFolderPath)) {
                                        fs.mkdirSync(todayFolderPath);
                                        fs.chmodSync(todayFolderPath, 0o777);
                                        Log.incErrorLog(`Folder created for attachment: ${todayFolderPath}`);
                                    }

                                    if (!fs.existsSync(folderPath)) {
                                        fs.mkdirSync(folderPath);
                                        fs.chmodSync(folderPath, 0o777);
                                        Log.incErrorLog(`Folder created for attachment: ${folderPath}`);
                                    }

                                    const attachmentFilePath = path.join(folderPath, attachmentFileName);
                                    fs.writeFileSync(attachmentFilePath, attachmentContent);
                                    Log.incErrorLog(`Attachment ${attachmentFileName} saved successfully.`);
                                } catch (err) {
                                    Log.incErrorLog(`Error saving attachment ${attachmentFileName}: ${err}`);
                                }
                            }
                        }

                        // ✅ Ensure JSON also gets folder path ready
                        const today = new Date();
                        const dateStr = new Date(today.getTime() - (today.getTimezoneOffset() * 60000))
                            .toISOString()
                            .slice(0, 10);

                        const todayFolderPath = path.join(__dirname, 'mail_json_file', dateStr);
                        const folderPath = path.join(todayFolderPath, msgId);

                        if (!fs.existsSync(todayFolderPath)) {
                            fs.mkdirSync(todayFolderPath);
                            fs.chmodSync(todayFolderPath, 0o777);
                        } else {
                            Log.incErrorLog(`Folder already exists for json file: ${todayFolderPath}`);
                        }
                        if (!fs.existsSync(folderPath)) {
                            fs.mkdirSync(folderPath);
                            fs.chmodSync(folderPath, 0o777);
                        } else {
                            Log.incErrorLog(`Folder already exists for json file: ${folderPath}`);
                        }

                        // Prepare final JSON
                        const jsonData = {
                            headerData,
                            bodyData: base64Body,
                            attachmentData,
                            uid: msg.uid || 0,
                            msgId
                        };
                        const finalData = JSON.stringify(jsonData, null, 2);
                        const fileName = `${msgId}.json`;
                        const finalpath = path.join(folderPath, fileName);

                        fs.writeFile(finalpath, finalData, (writeErr) => {
                            if (writeErr) {
                                Log.incErrorLog({ error: writeErr });
                                return callback(writeErr, null);
                            } else {
                                const todayISOString = dateStr;
                                const folderName = msgId;
                                const fileFolderPath = `${todayISOString}/${folderName}/`;

                                Log.incErrorLog(`Mail data saved to JSON file ${headerData}`);

                                if ("references" in headerData) {
                                    const references = headerData["references"];
                                    serverModel.getReferenceData(references, data.queue_id)
                                        .then((result) => {
                                            if (result.status === true) {
                                                const idDataList = [];
                                                const idData = result.data;

                                                if (Object.keys(idData).length > 0) {
                                                    idDataList.push({
                                                        ticket_unique_id: idData.ticket_unique_id,
                                                    });
                                                }

                                                if (idDataList.length > 0) {
                                                    serverModel.getTicketIdRefrenceData(data.queue_id, idDataList[0].ticket_unique_id)
                                                        .then((result) => {
                                                            const replyTicketDataList = [];
                                                            if (result.status === true) {
                                                                const replyTicketData = result.data;
                                                                if (Object.keys(replyTicketData).length > 0) {
                                                                    replyTicketDataList.push({
                                                                        ticket_unique_id: replyTicketData.ticket_unique_id,
                                                                        status_id: replyTicketData.status_id,
                                                                        conversation_date: replyTicketData.conversation_date,
                                                                        conversation_id: replyTicketData.conversation_id,
                                                                        assigned_to: replyTicketData.assigned_to,
                                                                        is_assigned: replyTicketData.is_assigned,
                                                                    });
                                                                }
                                                            }

                                                            const dataWithMsgId = {
                                                                ...JSON.parse(finalData),
                                                                msgId,
                                                                fileFolderPath,
                                                                replyTicketDataList,
                                                            };

                                                            callback(null, dataWithMsgId);
                                                        });
                                                } else {
                                                    if (!this.isRecipientFound(data, headerData)) {
                                                        Log.incErrorLog("Recipient email not found in queue");
                                                        return;
                                                    } else {
                                                        const dataWithMsgId = {
                                                            ...JSON.parse(finalData),
                                                            msgId,
                                                            fileFolderPath,
                                                        };
                                                        callback(null, dataWithMsgId);
                                                    }
                                                }
                                            } else {
                                                if (!this.isRecipientFound(data, headerData)) {
                                                    Log.incErrorLog("Recipient email not found in queue");
                                                    return;
                                                }
                                            }
                                        });
                                } else {
                                    if (!this.isRecipientFound(data, headerData)) {
                                        Log.incErrorLog("Recipient email not found in queue");
                                        return;
                                    }
                                    const dataWithMsgId = {
                                        ...JSON.parse(finalData),
                                        msgId,
                                        fileFolderPath,
                                    };
                                    callback(null, dataWithMsgId);
                                }
                            }
                        });

                    } catch (err) {
                        Log.incErrorLog(`Error processing message: ${err.message}`);
                    }
                });
            });
        });

        fetch.once('error', err => {
            callback(`Fetch error: ${err}`, null);
        });

        fetch.once('end', () => {
            Log.incErrorLog('Finished processing messages');
        });
    });
}


    shouldBlockEmail(data, headerData) {
        const blockEmails = (data.block_email_for_ticket_generate || '').split(',');
        return headerData.from?.value?.some(entry => blockEmails.includes(entry.address));
    }

    shouldBlockDomain(data, headerData) {
        const blockDomains = (data.block_domains_for_ticket_generate || '').split(',').map(d => d.trim().replace(/^@/, ''));
        return headerData.from?.value?.some(entry => blockDomains.includes(entry.address.split('@')[1]));
    }

    isRecipientFound(data, headerData) {
        if (!data.forwarded_mail) {
            return headerData.to?.value?.some(entry => entry.address.toLowerCase() === data.incoming_user_name.toLowerCase());
        }
        return headerData.to?.value?.some(entry => [data.incoming_user_name, data.forwarded_mail].includes(entry.address.toLowerCase()));
    }

    isSameEmail(senderEmail, recipientEmail) {
        return senderEmail.toLowerCase() === recipientEmail.toLowerCase();
    }

    createIMAPConfig(data, token) {
        const isTLS = data.security_protocol === 'TLS' || data.security_protocol === 'SSL';
        const config = {
            user: data.incoming_user_name,
            host: data.incoming_mail_server,
            port: data.incoming_mail_server_port,
            tls: isTLS,
            tlsOptions: { rejectUnauthorized: false },
        };

        if (data.is_auth_enable) {
            const xoauth2Token = Buffer.from([
                `user=${data.incoming_user_name}`,
                `auth=Bearer ${token}`,
                '', ''
            ].join('\x01'), 'utf-8').toString('base64');
            config.xoauth2 = xoauth2Token + isReadingMail;
        } else {
            config.password = data.incoming_password;
        }

        return config;
    }

    async refreshAuthToken(data) {
        try {
            const url = `https://login.microsoftonline.com/${data.tenant_id}/oauth2/v2.0/token`;
            const postData = qs.stringify({
                grant_type: 'refresh_token',
                client_id: data.client_oauth2_id,
                client_secret: data.client_secret,
                refresh_token: data.refresh_token,
                scope: 'https://outlook.office365.com/.default'
            });

            const response = await axios.post(url, postData, {
                headers: { 'Content-Type': 'application/x-www-form-urlencoded' }
            });

            const { refresh_token, access_token } = response.data;
            await serverModel.saveToken(refresh_token, access_token, data.incoming_user_name);
            await emailOperation.handlerTokenCompanyObj();

            Log.incErrorLog(`Token refreshed and saved for ${data.incoming_user_name}`);
            return access_token;
        } catch (err) {
            Log.incErrorLog(`Token refresh failed: ${err.message}`);
            throw new Error('Token refresh failed');
        }
    }

    formatDateForDB(rawDate) {
        const date = new Date(rawDate);
        if (isNaN(date)) return null;
        const pad = n => n.toString().padStart(2, '0');
        return `${date.getFullYear()}-${pad(date.getMonth() + 1)}-${pad(date.getDate())} ${pad(date.getHours())}:${pad(date.getMinutes())}:${pad(date.getSeconds())}`;
    }
}

module.exports = new MailOperation();
